【Python开源-单目测距】单目无人机多视角测距:DJI RTK图像 → 地面目标3D坐标与距离,平均RE仅2.12%

摘要:本文介绍一个开源的单目多视角测距项目,基于 DJI RTK 无人机图像,通过多视角三角测量恢复地面目标的 ECEF 三维坐标,进而计算目标间实际距离。实测 DJI Mavic 3E,25 样本,MAE 0.084m,平均相对误差 2.12%。项目包含核心算法库、Flask Web 演示应用、标定工具及完整文档,MIT 开源。


目录


![户外场景实测](https://i-blog.csdnimg.cn/direct/ab9aef2af64d4a589f17046e719d5b8c.jpeg

一、项目背景

在无人机外业作业中,有一个高频需求:

从航拍图像中,测量地面两个目标之间的实际距离。

现有方案的痛点:

方案 局限
双目相机 成本高,DJI 工业机多为单目
激光测距 只能测相机到目标的距离,无法直接测目标间距
人工 RTK 打点 需要到达目标位置,部分场景无法靠近
GSD 推算 依赖精确 GSD,精度有限,只适合水平面目标

本项目的思路:DJI RTK 无人机在拍摄时已记录厘米级精度的位置(经纬高)与姿态(偏航/俯仰/横滚),结合像素坐标,多视角三角测量可以完整恢复目标的三维坐标。


二、核心原理

核心思路:同一个目标在不同位置拍摄时,每张图产生一条空间射线,多条射线的交点就是目标的 3D 坐标。为什么需要RTK?因为我们需要有一个世界坐标系来构建世界坐标系下的通过目标点的射线方程,RTK坐标系是一个非常精确的坐标系,非常适合用来做测距系统的世界坐标系,2个视角下通过同一个目标点的射线方程相交就可以计算出目标点在RTK坐标系下的精确3D坐标。

2.1 整体流程

复制代码
像素坐标 (u, v)
    ↓  相机内参 + 去畸变
    ↓  归一化相机坐标系射线
    ↓  RTK 姿态变换(camera → NED → ECEF)
    ↓  射线方向 d_i + 光心位置 O_i(ECEF)
    ↓  多视角最小二乘三角测量
    →  3D ECEF 坐标 X
    →  两点欧氏距离 ‖X_a - X_b‖ = 目标间距

2.2 坐标变换

射线方向变换到 ECEF:

d i = R e c e f ← n e d ( l a t , l o n ) ⋅ R n e d ← b o d y ( y a w , p i t c h , r o l l ) ⋅ R c a m ← b o d y ⋅ d c a m \mathbf{d}i = R{ecef\leftarrow ned}(lat,lon) \cdot R_{ned\leftarrow body}(yaw,pitch,roll) \cdot R_{cam\leftarrow body} \cdot \mathbf{d}_{cam} di=Recef←ned(lat,lon)⋅Rned←body(yaw,pitch,roll)⋅Rcam←body⋅dcam

相机光心 ECEF 坐标:

O i = ECEF ( l a t i , l o n i , a l t i ) + [ d X , d Y , d Z ] T \mathbf{O}_i = \text{ECEF}(lat_i,\ lon_i,\ alt_i) + [dX,\ dY,\ dZ]^T Oi=ECEF(lati, loni, alti)+[dX, dY, dZ]T

其中 [ d X , d Y , d Z ] [dX, dY, dZ] [dX,dY,dZ] 为外参偏置,用于补偿云台安装误差。

2.3 最小二乘三角测量

每条观测构造一行方程:

( I − d i d i T ) X = ( I − d i d i T ) O i (I - \mathbf{d}_i\mathbf{d}_i^T)\mathbf{X} = (I - \mathbf{d}_i\mathbf{d}_i^T)\mathbf{O}_i (I−didiT)X=(I−didiT)Oi

将 N N N 条观测堆叠为:

A X = b A\mathbf{X} = b AX=b

使用 numpy.linalg.lstsq 求解三维点 X \mathbf{X} X。

2.4 测距

D = ∥ X a − X b ∥ 2 D = \|\mathbf{X}_a - \mathbf{X}_b\|_2 D=∥Xa−Xb∥2


三、实测精度

测试平台 :DJI Mavic 3E 可见光广角
样本数 :25
真值范围 :2.00m ~ 6.01m
基线范围:0.053m ~ 9.904m

汇总结果

机型 N MAE(m) RMSE(m) 平均 RE(%) Bias(m)
DJI Mavic 3E 25 0.084 0.126 2.120 +0.052

补充:最小 AE = 0.0002m,最大 AE = 0.363m;最小 RE = 0.006%,最大 RE = 6.05%。

分目标结果

观测点 ID N MAE(m) RMSE(m) 平均 RE(%) Bias(m)
0 13 0.024 0.032 0.879 -0.012
1 3 0.158 0.176 2.628 +0.068
2 4 0.240 0.257 4.006 +0.240
3 5 0.071 0.075 3.533 +0.060

四、项目结构

复制代码
MMVDMS/
├── src/
│   └── mvtriangulation/              # 核心算法库
│       ├── __init__.py               # 公开 API 入口
│       ├── triangulator.py           # CameraTriangulator
│       ├── transforms.py             # 坐标变换
│       ├── pipeline.py               # triangulate_dataframe
│       ├── models.py                 # 数据模型
│       ├── exceptions.py
│       ├── parsers/
│       │   └── dji_xmp.py            # DJI EXIF/XMP 元数据解析
│       └── calibration/
│           ├── intrinsics_zhang.py   # 张正友内参标定
│           └── extrinsics.py         # 外参鲁棒拟合
├── apps/
│   └── flask_demo/                   # Web 演示应用
├── examples/
│   ├── minimal_usage.py              # 最小化完整示例
│   ├── fit_intrinsics_zhang.py       # 内参标定示例
│   └── fit_extrinsics_robust.py      # 外参拟合示例
├── docs/
│   ├── zh/                           # 中文文档
│   └── en/                           # 英文文档
├── requirements.txt
└── LICENSE

五、快速开始

环境要求:Python >= 3.8

bash 复制代码
git clone https://github.com/BRAIN-INSPIRED-TECHNOLOGY/MMVDMS.git
cd MMVDMS
pip install -r requirements.txt

5.1 运行最小化 Demo

bash 复制代码
# 使用内置 demo_csv 数据,默认 Mavic 3E 内参
python examples/minimal_usage.py \
  --points-csv examples/demo_csv/keypoints_observation2.csv \
  --image-dir examples/demo_images \
  --camera-model m3e

# 指定机型和关键点对
python examples/minimal_usage.py \
  --points-csv examples/demo_csv/keypoints_observation2.csv \
  --image-dir examples/demo_images \
  --camera-model m3t --pair 1-2

# 其他机型,传入自定义内参 JSON
python examples/minimal_usage.py \
  --points-csv examples/demo_csv/keypoints_observation2.csv \
  --image-dir examples/demo_images \
  --camera-model others \
  --intrinsics-json path/to/camera_intrinsics.json

5.2 启动 Web 演示应用

bash 复制代码
# 默认 Mavic 3E
python -m apps.flask_demo

# 指定机型
python -m apps.flask_demo --camera-model M3T

浏览器访问 http://localhost:5000,流程:导入图像 → 标注关键点 → 三角测量 → 查看距离 → 导出


六、核心 API

三角测量

python 复制代码
from mvtriangulation import (
    CameraTriangulator,
    triangulate_dataframe,
    build_camera_arrays,
)

# 方式一:直接调用 pipeline
# 先构建相机参数(内参 + 外参偏置)
camera_matrix, dist_coeffs, extr_cfg = build_camera_arrays(intrinsics, extrinsics)
# df_xy 包含像素坐标 + 从原图 XMP 提取的位姿字段(lat/lon/alt/gimbal_pitch/yaw/roll)
result_df = triangulate_dataframe(df_xy, camera_matrix, dist_coeffs, extr_cfg)

# 方式二:使用 CameraTriangulator 直接三角测量
triangulator = CameraTriangulator()
point_3d = triangulator.triangulate(origins, directions)

元数据解析

python 复制代码
from mvtriangulation import extract_dji_metadata_from_jpeg_bytes

with open("image.JPG", "rb") as f:
    metadata = extract_dji_metadata_from_jpeg_bytes(f.read())
# 返回:纬度、经度、椭球高、偏航、俯仰、横滚

七、标定工具

7.1 张正友内参标定

bash 复制代码
python examples/fit_intrinsics_zhang.py \
  --images "data/calib/*.jpg" \
  --board-cols 9 \
  --board-rows 6 \
  --square-size 0.025 \
  --out "data/camera_intrinsics.json"

输出格式:

json 复制代码
{
  "camera_matrix": [[fx, 0, cx], [0, fy, cy], [0, 0, 1]],
  "distortion_coefficients": [[k1, k2, p1, p2, k3]]
}

7.2 外参偏置拟合

用于补偿云台安装角误差:

bash 复制代码
python examples/fit_extrinsics_robust.py \
  --intrinsics "data/camera_intrinsics.json" \
  --fit-csv "data/obs_fit.csv" \
  --test-csv "data/obs_test.csv" \
  --out "data/camera_extrinsic_params.json" \
  --with-xyz-offset

7.3 内置默认内参(DJI Mavic 3E / 3T)

无标定文件时可直接使用内置参数快速启动:

机型 分辨率 fx fy cx cy
DJI Mavic 3E 5280×3956 3660.0 3660.0 2640.0 1978.0
DJI Mavic 3T 8000×6000 5500.0 5500.0 4000.0 3000.0

注:默认内参为估算值,高精度场景请执行棋盘格标定。


八、约束说明

约束 说明
必须 RTK 算法依赖厘米级位置与姿态,普通 GPS 精度不足
仅支持 DJI 元数据 其他厂商需自行实现解析接口
最少 2 帧观测 每个关键点至少需要 2 条有效射线
基线几何敏感 射线近平行时深度方向不稳定,精度下降
演示应用内存存储 重启后数据清空,非生产级

九、项目地址

  • GitHubhttps://github.com/BRAIN-INSPIRED-TECHNOLOGY/MMVDMS.git
  • License:MIT
  • 文档 :中英文均有(docs/zh/docs/en/
  • Python 版本:>= 3.8

欢迎提交 Issue 或 PR。Bug 报告请附上复现步骤、Python 版本和报错日志;功能建议请先开 Issue 讨论。


如果本文对你有帮助,欢迎点赞收藏,也欢迎 GitHub Star 支持开源。

相关推荐
Fleshy数模1 小时前
PyQt5 登录界面开发全流程:从环境配置到可视化设计
开发语言·python·qt
bingd011 小时前
慕课网、CSDN、菜鸟教程…2026 国内编程学习平台实测对比
java·开发语言·人工智能·python·学习
大飞哥~BigFei1 小时前
缓存一致性终极解决方案之Facebook租约机制的开源实现集成改造
java·缓存·开源
Wyz201210241 小时前
SQL如何实现实时数据的滑动窗口分析_SQL性能调优
jvm·数据库·python
Greyson11 小时前
Bootstrap制作后台管理系统布局 Bootstrap如何搭建Dashboard框架
jvm·数据库·python
m0_678485451 小时前
mysql如何配置多实例端口隔离_mysql多实例端口规划
jvm·数据库·python
Dontla1 小时前
Prometheus介绍(开源系统监控与告警工具)(时间序列数据库TSDB、标签化label-based多维分析、Pull模型、PromQL查询语言)
数据库·开源·prometheus
2301_814809861 小时前
如何在 Go 中精确安装指定版本的模块
jvm·数据库·python
Sophie_U1 小时前
【Agent开发速成笔记】一、从0到1基础Python学习
笔记·python·学习·agent·智能体