无人机图片目标地理位置计算

因为项目需要,需要通过无人机视频的中的目标位置计算实际的地理坐标位置,一下是计算的方法记录。

1、坐标系定义:

像素坐标系:单位pixel,相机的成像平面,原点在图像的左上方,u轴向右,v轴向下,像素坐标系的单位是像素(pixel),也就是分辨率。
图像坐标系:单位mm,和像素坐标系在同一个平面上,原点是相机光轴与成像平面的交点,通常情况下是成像平面的中点或者叫principal point。单位为物理单位。

机体坐标系:单位m,是以载机位置为原点建立的直角坐标系,X轴指向机头方向,Z轴指向载机垂直向下。即带姿态。
地理坐标系:单位m,以载机位置为原点建立的NED北东地坐标系
大地直角坐标系:单位m,根据参考椭球面建立的笛卡尔直角坐标系,原点为参考椭球面的中心点,Z轴由原点指向地球北极; X轴由原点指向本初子午圈与赤道圈在椭球面上的交点;
WGS84坐标系:与大地直角坐标系一样,只是采用纬度(M)、经度(L)和大地高(H)表示空间中任一点位置。

相机坐标系:单位m,原点是光心,x和y轴与像素坐标系u轴和v轴平行,z轴为相机的光轴。光心到像素平面的距离为焦距f。相机坐标系上的点和成像平面坐标系上的点存在透视投影关系

参考文献:【教程】详解相机模型与坐标转换-CSDN博客

2、像素坐标系 转 图像坐标系

从无人机所拍摄的视频图片的像素坐标系转图片坐标系


    (u,v) 目标点的像素坐标系中的坐标
    (u0,v0) 像素坐标系的中心点
    (dx,dy) 每个像素代表在图像坐标系中的距离 单位mm
    (imageX,imageY) 图像的尺寸 单位像素
    (rx,ry) 目标点在图像中的位置(范围0~1)的比值
 

def pixel_to_image(u,u0,v,v0,dx,dy):
    x=(u-u0)*dx
    y=(v-v0)*dy
    return [x,y]

def getPixel(imageX,imageY,rx,ry):
    return imageX*rx,imageY*ry,imageX/2,imageY/2

u,v,u0,v0=getPixel(imageX,imageY,rx,ry)
print(u,v,u0,v0)
x,y=pixel_to_image(u,u0,v,v0,dx,dy)
print(x,y)

3、图像坐标系 转 机体坐标系

    (x,y) 目标点在图像坐标系中的坐标
    H 目标点在机体坐标系中的Z坐标,为相机到目标点实际的高度距离,在这里我们可以使用无人机飞行的相对高度代替(即默认为所有的目标点的海拔高度与无人机起飞的高度一致,如果目标点区域为高低起伏较大的区域,则需要通过dem来缩小误差)
    f 相机的实际焦距(注意,并非相机厂商提供的等效焦距),即相机到成片的距离
 

def image_to_drone(x,y,H,f):
    Zc=H
    Xc=Zc/f*x
    Yc=Zc/f*y
    return [Xc,Yc,Zc]

Xc,Yc,Zc=image_to_drone(x,y,rel_H,f)
print(Xc,Yc,Zc)

4、机体坐标系 转 neu地理坐标系


    γ 横滚:北偏东为正
    β 俯仰:抬头为正
    α 航向:右倾斜为正
    (x,y,z) 目标点在机体坐标系中的位置


注意此处计算结果为neu坐标系,需要交换结果的前两个参数转为enu坐标系

def drone_to_neu(α,β,γ,x,y,z):
    α = np.radians(α) 
    β = np.radians(β)
    γ = np.radians(γ)
    C11=np.cos(α)*np.cos(β)
    C12=np.cos(α)*np.sin(β)*np.sin(γ)-np.sin(α)*np.cos(γ)
    C13=-np.cos(α)*np.sin(β)*np.cos(γ)-np.sin(α)*np.sin(γ)
    C21=np.sin(α)*np.cos(β)
    C22=np.cos(α)*np.cos(γ)+np.sin(α)*np.sin(β)*np.sin(γ)
    C23=-np.sin(α)*np.sin(β)*np.cos(γ)+np.cos(α)*np.sin(γ)
    C31=np.sin(β)
    C32=-np.cos(β)*np.sin(γ)
    C33=np.cos(β)*np.cos(γ)
    Ccb=np.array([[C11,C12,C13],[C21,C22,C23],[C31,C32,C33]])
    xyz=np.array([x,y,z])
    return np.dot(Ccb,xyz)

5、enu坐标系 转 大地直角坐标系

    (lon,lat,H) 无人机的经纬高度
    (x,y,z) 目标点在enu坐标系中的位置


此处的H为无人机的绝对高度,即无人机的海拔高度,与上面的相对高度(无人机起飞的高度)不同。

import pymap3d as pm

def enu_to_ecef(xb,yb,zb,lon,lat,H):
    return pm.enu2ecef(xb,yb,zb,lat,lon,H)

6、大地直角坐标系:ECEF (EPSG:4978) 转 WGS84 经纬高 (EPSG:4979)

# 定义坐标系:ECEF (EPSG:4978) 转 WGS84 经纬高 (EPSG:4979)
"""
    使用 pyproj 将 ECEF 坐标转换为经纬高 (WGS84)
    参数: X,Y,Z (单位: 米)
    返回: 经度lon(度), 纬度lat(度), 高度h(米)
"""

from pyproj import Proj
from pyproj import Transformer

def ecef_to_lla(X,Y,Z):
    transformer = Transformer.from_crs("EPSG:4978", "EPSG:4979", always_xy=True)
    lon, lat, h = transformer.transform(X,Y,Z)
    return lon, lat, h

 7、相机物理焦距的计算方法

import math

def calculate_physical_focal_length(equivalent_focal_length, sensor_width, sensor_height):
    # 计算传感器的对角线长度 (mm)
    sensor_diagonal = math.sqrt(sensor_width**2 + sensor_height**2)
    
    # 计算裁切系数(Crop Factor)
    crop_factor = 43.3 / sensor_diagonal  # 43.3 是 35mm 全画幅传感器的对角线长度 (mm)
    
    # 计算物理焦距 (mm)
    physical_focal_length = equivalent_focal_length / crop_factor
    
    return physical_focal_length, sensor_diagonal, crop_factor

# 输入参数
equivalent_focal_length = 24  # 等效焦距 (mm)
sensor_width = 9.69  # 传感器宽度 (mm)
sensor_height = 7.27  # 传感器高度 (mm)

# 计算
physical_focal_length, sensor_diagonal, crop_factor = calculate_physical_focal_length(
    equivalent_focal_length, sensor_width, sensor_height
)

# 输出结果
print(f"传感器对角线: {sensor_diagonal:.2f} mm")
print(f"裁切系数: {crop_factor:.2f}")
print(f"物理焦距: {physical_focal_length:.2f} mm")

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值