【代码】无人机航拍图像的空间分辨率计算
【代码】无人机航拍图像的空间分辨率计算
ytkz遥感图像的空间分辨率
遥感图像的空间分辨率是衡量图像上可检测到的最小地面单元尺寸的关键指标,它通常用地面采样间距(GSD)或像元大小来表示。
像元大小直接关联着图像中每个像素所代表的地面面积。例如,在1米空间分辨率的图像中,每个像素对应着实际地面上1米×1米的区域。
GSD是无人机或遥感卫星拍摄的影像中每个像素所代表的实际空间距离。它可以通过以下公式计算:
d = (s * H) / (f * 10) # 注意单位转换
其中:
- d:单位厘米(cm),指空间分辨率。
- s:单位微米(µm),指像元尺寸(也叫像素大小、像素间距)。
- H:单位米(m),指飞行高度。(不是绝对高度)
- f:单位毫米(mm),指镜头的焦段(焦距)。
请注意,在公式中我们进行了单位转换,因为1毫米等于10微米,所以除以10来确保单位的一致性。
单位关系为:
- 1米(m)= 100厘米(cm)
- 1毫米(mm)= 10微米(µm)
通过这个公式,我们可以根据已知的像元尺寸、飞行高度和焦距来计算GSD,从而了解遥感图像的空间分辨率。这对于遥感数据的分析和应用至关重要,因为它直接影响到图像中地物细节的识别能力。
示例
以大疆精灵 Phantom 4 RTK 为例,其像元大小为 2.41 微米(µm),而相机焦距设定为 8.8 毫米(mm)。将这两个参数代入地面采样距离(GSD)的计算公式中,我们得到:
GSD = (2.41µm × 飞行高度H) / 8.8mm
= (0.241mm × 飞行高度H) / 8.8mm
≈ 飞行高度H / 36.5
换言之,GSD 近似等于飞行高度(H)除以 36.5。基于这一公式,当客户 A 需要 GSD 为 5 厘米/像素(cm/pixel)的数据时,通过计算,我们得到理论上的飞行高度应为约 182 米。
然而,在实际飞行作业中,我们需要考虑到环境因素(如风速、天气条件等)对无人机稳定性和数据质量的潜在影响。因此,为了确保数据的准确性和安全性,我们通常会在理论计算值的基础上,选择稍低于 182 米的飞行高度进行作业。这样做不仅可以保证数据的精度,还能为无人机提供更加稳定、安全的飞行环境。
自动获取参数
经过测试,除了像元尺寸不能自动从文件中获取,飞行高度和焦距都可以从文件提取信息。
飞行高度可以从航片的元数据信息中查看,用记事本的方式打开航片文件。过程如下:
因为每景图片的飞行高度可能不一样,如果每次手动去获取高度信息是很麻烦,所以想办法实现自动获取。
相关代码如下:
def get_image_info(imgfile):
"""
:param imgfile: 输入图片路径
:return: 图片的偏航角,飞行高度(相对高度)
"""
# 获取图片偏航角
b = b"\x3c\x2f\x72\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x3e"
a = b"\x3c\x72\x64\x66\x3a\x44\x65\x73\x63\x72\x69\x70\x74\x69\x6f\x6e\x20"
img = open(imgfile, 'rb')
data = bytearray()
dj_data_dict = {}
flag = False
for line in img.readlines():
if a in line:
flag = True
if flag:
data += line
if b in line:
break
if len(data) > 0:
data = str(data.decode('ascii'))
lines = list(filter(lambda x: 'drone-dji:' in x, data.split("\n")))
for d in lines:
d = d.strip()[10:]
key, value = d.split("=")
dj_data_dict[key] = value
return float(dj_data_dict["FlightYawDegree"][1:-1]), float(dj_data_dict["RelativeAltitude"][1:-1])
这个函数 get_image_info
的主要目的是从一个图片文件中提取特定的元数据,特别是与大疆无人机(Drone DJI)相关的偏航角(FlightYawDegree)和相对高度(RelativeAltitude)
函数逻辑:
- 函数首先定义了两个二进制字符串
a
和b
,它们分别是大疆无人机图片元数据的开始和结束标记。 - 使用二进制读取模式(’rb’)打开图片文件。
- 初始化一个空的
bytearray
来存储从文件中读取的、包含所需元数据的部分。 - 使用一个
flag
变量来跟踪是否已经找到了开始标记。 - 遍历文件的每一行(这里假设文件内容以换行符分隔,这在图片文件中可能不是标准的,但基于特定的元数据存储格式可能是正确的)。
- 当找到开始标记时,将
flag
设置为True
,并开始将后续的行添加到data
中。 - 当找到结束标记时,停止读取并退出循环。
- 如果
data
中有数据,则将其解码为 ASCII 字符串,并按行分割。 - 使用列表推导式和
filter
函数来提取包含 “drone-dji:” 的行。 - 对每一行进行处理,提取键和值,并将它们存储在字典
dj_data_dict
中。 - 最后,返回偏航角和相对高度的浮点数表示。注意,这里假设
FlightYawDegree
和RelativeAltitude
的值被方括号包围(如"[value]"
),因此在提取时要去掉这些方括号。
同理,焦距可以从图像文件的exif信息获取。
相关代码如下:
from PIL import Image
from PIL.ExifTags import TAGS
def get_focal_length(imgfile):
"""
:param imgfile: 输入图片路径
:return: 图片的镜头焦距
"""
exif_data = {}
try:
# 使用PIL库打开图片
i = Image.open(imgfile)
# 获取图片的EXIF标签
tags = i._getexif()
for tag, value in tags.items():
# 尝试从预定义的TAGS字典中获取标签的中文描述,否则使用标签ID
decoded = TAGS.get(tag, tag)
# 将标签及其值存储到exif_data字典中
exif_data[decoded] = value
except Exception as e:
print(e)
if exif_data.get('LensSpecification'):
Lens = exif_data['LensSpecification']
focal_length = Lens[0] # 焦距
return focal_length
像元尺寸信息则不能自动获取,需要自行根据你的无人机的硬件信息获取。
大疆的禅思 P1像元尺寸是4.4μm。相关信息可以在其官网获取。
题外话—精度与飞行高度的关系
例如客户要求的精度不得超过5厘米,这意味着无论采用何种测量方法或技术,生成的数据在精确性方面应满足一个标准:即测量值与实际值之间的差异不应超过5厘米。在遥感与无人机测绘领域,这种精度要求通常涉及两种精度类型:
- 相对精度:这是指通过测量合成模型(如三维地图或模型)中的特征(如道路长度)来评估的精度。相对精度关注的是测量值与实际值之间的相对差异,即模型中的测量数据与实际数据之间的偏差。
- 绝对精度:这是指合成模型中地物(如路灯)的位置与实际位置之间的直接差异。绝对精度关注的是模型中的位置数据与实际位置之间的直接对应关系。
以大疆精灵Phantom 4 RTK为例,它在厘米级定位条件下的性能使得其在相对和绝对精度上都能达到较高水平。具体来说,其精度能达到1至2倍的GSD(地面采样距离),即图像上每个像素代表的实际距离。
当客户要求相对精度为5厘米时,为确保数据的精确性,我们可以选择调整飞行参数,如采用GSD为2厘米/像素的设置,并在约73米的高度进行数据采集。这样的设置将有助于提高数据的分辨率和精度,从而确保满足客户的精度要求。