实现正射图像中某个像素的位置定位,基于大疆无人机实现
·
无人机正射影像实现像素坐标定位
代码原理
无人机正射拍摄,已知像素物理尺寸,使用大疆飞机拍摄的信息,进行像素坐标估算,理论精度应该在米级,但是航偏角以及定位误差导致与实际有所不同
部分参数查看无人机相机参数

关键代码 1. 提取图像参数
def Get_Image_Yaw_angle(file_path):
"""
:param file_path: 输入图片路径
:return: 图片的偏航角
"""
# 获取图片偏航角
#print("----------------------------------大疆exifread信息---------------------------------")
# 定义字节模式 b 和 a,用于查找大疆EXIF数据的起始和结束标记
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(file_path, 'rb')
# 初始化一个字节数组用于存储EXIF数据
data = bytearray()
# 初始化一个标志,用于判断是否已经找到EXIF数据的起始标记
flag = False
# 逐行读取图片文件内容
for line in img.readlines():
# 如果当前行包含EXIF数据的起始标记,则设置标志为True
if a in line:
flag = True
# 如果标志为True,则将当前行添加到EXIF数据中
if flag:
data += line
# 如果当前行包含EXIF数据的结束标记,则跳出循环
if b in line:
break
# 如果提取到的EXIF数据不为空
dj_data_dict = {}
# 遍历过滤后的行,并提取键值对存入字典中
if len(data) > 0:
# 将字节数据解码为ASCII字符串
data = str(data.decode('ascii'))
# 过滤出包含drone-dji的行,并分割每行为键值对
lines = list(filter(lambda x: 'drone-dji:' in x, data.split("\n")))
#lines = list(filter(lambda x: x, data.split("\n")))
# 初始化一个空字典用于存储提取到的数据
for d in lines:
if "640" in d:
print(d)
d = d.strip()[10:] # 去除每行的前后空格和'\n'字符,并从第10个字符开始处理(因为drone-dji:占据了前9个字符)
res = d.split("=")
k, v = res[0],res[1] # 将当前行分割为键和值两部分
dj_data_dict[k] = v # 将键值对存入字典中
return dj_data_dict # 返回偏航角的值。如果未找到偏航角,则返回None。
def get_value(dj_data_dict, key):
valu = dj_data_dict[key]
valu = valu.replace('"', '').replace('+', '')
return valu
关键代码 2.旋转位姿
# 定义经纬度与平面坐标系的转换
wgs84 = Proj(init="epsg:4326") # WGS 84 经纬度坐标系
mercator = Proj(init="epsg:3857") # 墨卡托投影坐标系
def rotate_point(x, y, x_center, y_center, pic_row):
# 将点平移至旋转中心
x_prime = x - x_center
y_prime = y - y_center
# 将角度转换为弧度
theta = radians(pic_row)
# 应用旋转矩阵
x_rot = x_prime * cos(theta) - y_prime * sin(theta)
y_rot = x_prime * sin(theta) + y_prime * cos(theta)
# 将旋转后的坐标平移回去
x_rot += x_center
y_rot += y_center
return x_rot, y_rot
关键代码 3.计算坐标
def calculate_pos(center_pix: tuple, center_pos: tuple, height: float, board_corners: tuple, pic_row: float) -> Tuple[float, float]:
focal_length, dist_per_pix = (91*53/40)*1e-4, 6e-6 # unit: m, m/pix / 2
#维度
ratio = height / focal_length # unit: None
board_center = board_corners # unit: pix
dx_pix, dy_pix = board_center[0] - center_pix[0], center_pix[1] - board_center[1] # unit: pix, pix
dx_ccd, dy_ccd = dx_pix * dist_per_pix, dy_pix * dist_per_pix # unit: m, m
dx_real, dy_real = dx_ccd * ratio, dy_ccd * ratio # unit: m, m
#dlon, dlat = dx_real / dist_per_lon, dy_real / dist_per_lat # unit: deg, deg
result = (center_pos[0] + dx_real, center_pos[1] + dy_real)
#这个为假设图像为正北方向,如果图像不是正北方向,需要根据实际情况
# 点result绕点center_pos中心点旋转pic_row度的坐标
result = rotate_point(result[0], result[1], center_pos[0], center_pos[1], pic_row)
result = (result[0], result[1])
return result
详细完整代码放在我的资源下载,可以免费下载
更多推荐

所有评论(0)