ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

无人机视觉定位核心:相机模型与标定实战全解

无人机视觉定位核心:相机模型与标定实战全解 用标定板把无人机从看得见变成看得懂这件事我做了很久也踩过不少坑。相机模型与标定这个主题看起来是视觉领域最基础的一课但真正放到无人机上跑起来你会发现几乎所有定位、避障、目标跟踪问题的根子都出在像素坐标到空间坐标这一步没打通。这篇东西不是教科书复述是我在飞控与视觉融合项目中实操沉淀下来的一套完整思路结合张正友标定法、畸变校正、相机-IMU外参标定和实际测距定位的链路尽量把每一步的原因、步骤和坑都讲透。1. 为什么无人机必须过相机标定这一关像素不是位置先说一个很多刚接触无人机视觉的人容易忽略的事实相机输出的是一张二维像素图每个像素点的值只代表某个方向上的光强积分它本身不携带任何空间距离信息。无人机要理解自己在空间中的真实位置本质上是需要回答“我看到的那个目标到底在我前方多少米、偏左多少度、高度差多少”这就必须把像素坐标反投影到三维世界坐标系里而反投影的前提就是一套精确的相机几何模型。1.1 无人机视觉任务的共通底座不管是做视觉定位、双目测距、AprilTag降落、目标跟踪还是避障算法链路的前两步几乎固定是内参去畸变、外参坐标变换。很多初学者以为学了OpenCV的calibrateCamera跑出一组内参矩阵就完事了但真正上机你会发现畸变系数选错了模型、标定板拍得不合格、外参没跟IMU对齐任何一个环节出错后面所有算法的精度都会受到直接影响。我在一个项目里就遇到过视觉测距在实验室静态场景下误差不到2%但无人机一旦大机动飞行目标位置估计直接偏出去半米后来查下来就是外参标定时相机与飞控IMU之间的旋转矩阵没对准。业界主流的VIO方案如VINS-Mono、ORB-SLAM3之所以在启动前都需要一个初始化过程本质上也是在在线估计相机与IMU之间的相对位姿这从侧面说明外参标定对无人机状态估计的重要性。可以说相机标定不是可有可无的预处理步骤而是整个无人机视觉感知系统稳定性的地基。1.2 无人机与地面机器人标定的关键差异很多人问无人机相机标定和普通机器人标定有啥区别区别非常大。地面机器人运动是二维平面为主外参标定即使有小误差靠后续的平面约束也能压住一部分无人机是六自由度运动俯仰、横滚、偏航都会让相机光轴方向剧烈变化。一个0.5度的外参旋转误差在20米距离上就会造成约17厘米的位置偏移对于需要精确降落的无人机来说这个误差是灾难性的。此外无人机载重受限相机往往不能做得太大镜头畸变往往比工业相机更严重尤其是广角镜头如常见的1/2.7英寸传感器配2.8mm焦距镜头边缘畸变如果不靠标定校正几乎没法用。所以无人机的相机标定不仅要做得精还要理解每一步背后的物理意义。下面我按从内到外的顺序把整个链路完整过一遍。2. 针孔相机模型与四个坐标系的转换先懂原理再动手相机模型的本质是三维空间点如何投影到二维像素平面而针孔模型是这一过程最简洁的数学描述。虽然真实镜头存在各种畸变但针孔模型是整个标定算法的出发点和归零点。2.1 内参矩阵里装了什么针孔模型的投影过程可以拆成三步世界坐标系下的点先通过外参旋转R和平移t变换到相机坐标系再由内参矩阵K投影到像素坐标系。内参矩阵K通常写作K [fx 0 cx 0 fy cy 0 0 1]其中fx、fy是归一化焦距单位是像素cx、cy是主点坐标也就是光轴与成像平面的交点。焦距的单位为什么是像素而不是毫米因为像素坐标系和物理成像平面之间存在一个缩放关系——传感器上每个像素的物理尺寸是已知的比如2.2μm焦距的物理长度比如4mm除以像素尺寸就得到了以像素为单位的焦距。这个转换关系决定了同样一个镜头传感器分辨率越高、像素尺寸越小fx就越大视野反而越小。很多人在选相机时只看分辨率不看传感器尺寸结果发现标定出来的fx和理论值对不上其实就是没理解这一层。2.2 外参让相机坐标系挂到机体上外参描述的是相机坐标系相对于某个参考坐标系通常是飞控机体坐标系的旋转和平移。对于无人机来说这个参考坐标系一般定义成原点在飞控IMU中心X轴指向机头Y轴指向右翼Z轴向下也有用前-右-下约定的。外参标定的意义就是回答相机安装在机体上什么位置、朝向哪个方向。我见过一些团队为了省事用尺子量安装位置、用量角器估安装角度直接手填外参。这种做法在短距离、小视场角场景下勉强能跑但一旦涉及VIO或者精确降落误差就会暴露出来。一个可靠的做法是用标定板做相机与IMU的联合标定业内常用的工具是Kalibr它可以同时估计相机的内参、畸变系数以及相机与IMU之间的外参和时间延时。2.3 完整投影链路的数学表达假设世界坐标系下有一个三维点Pw它在相机坐标系下的坐标为Pc R * Pw t。归一化后得到Pn [Xc/Zc, Yc/Zc, 1]然后通过内参映射到像素坐标u fx * Xc/Zc cx v fy * Yc/Zc cy这个公式看起来简单但它揭示了几个对无人机应用很重要的结论像素坐标和三维点之间是差一个尺度因子Zc的。也就是说单目相机无法从单帧图像直接得到目标的绝对深度只能得到方向。无人机要获得目标的真实位置要么靠已知目标尺寸PnP问题要么靠多帧图像的运动视差SFM/VIO要么靠双目视差要么靠其他测距传感器融合。这正是为什么相机标定永远和定位方案绑定在一起讨论的原因——标定解决的是方向准不准而深度估计解决的是距离远不远。3. 畸变模型为什么真实镜头都不是针孔以及校正怎么做拿任何一支普通镜头拍一张棋盘格照片你都会发现边缘的直线是弯的这就是畸变。畸变不校正前面说的针孔模型完全没法用。3.1 径向畸变与切向畸变的来源畸变主要分两类径向畸变光线通过透镜时边缘光线比中心光线弯折得更厉害造成画面呈桶形或枕形。广角镜头几乎都是桶形畸变画面中心区域被放大、边缘被压缩。这种畸变是关于光轴对称的用三个系数k1、k2、k3描述现在的相机模型大多采用k1-k2-k3三参数模型有些小畸变镜头也可以只用k1-k2。切向畸变透镜与传感器平面不是绝对平行造成的用p1、p2两个系数描述。切向畸变在高质量工业镜头中通常很小但在无人机搭载的低价镜头比如树莓派Camera模块、各种Action Cam上不可忽略。完整的畸变模型可以写成标定板角点的归一化坐标经过径向和切向偏移后再投影x_distorted x * (1 k1*r^2 k2*r^4 k3*r^6) 2*p1*x*y p2*(r^2 2*x^2) y_distorted y * (1 k1*r^2 k2*r^4 k3*r^6) p1*(r^2 2*y^2) 2*p2*x*y其中r^2 x^2 y^2。注意这里的x、y是归一化坐标不是像素坐标。OpenCV在做畸变校正时就是在归一化平面上处理后再乘内参矩阵映射回像素。3.2 标定板的选择和拍摄规范标定质量的一半取决于标定板一半取决于拍摄手法。我在实践中总结了几条对无人机应用特别重要的规范方格不要太小棋盘格每个方格的边长在传感器上至少要占20个像素以上否则角点检测精度会急剧下降。对于1080p分辨率、焦距2.8mm的广角镜头建议方格边长30-40mm标定板整体8×6或者9×7个内角点。拍摄姿态要覆盖全视场标定板要出现在画面的各个位置特别是四个角落。广角镜头边缘畸变最大如果边缘没有标定板覆盖畸变系数外推就会不准。至少要拍20-30张每张之间转动角度和距离都要有变化。标定板要尽量平整打印的A4纸贴在纸板或者泡沫板上容易弯曲会造成系统性误差。条件允许的话用铝合金板或者玻璃板或者至少用厚卡纸加双面胶固定。我自己做过对比试验贴在不平纸板上的标定板重投影误差从0.15像素直接涨到0.5像素以上。避免纯正面拍摄如果所有照片都是标定板正对相机那么fx和fy的内部约束会被削弱解出来的内参会不稳定。要确保有一部分照片是标定板相对于相机倾斜大约30-45°的。提一句九点标定和标定板标定的区别。九点标定是手眼标定的一种简化形式它完成的是像素坐标→机械臂/平台平面坐标的2D映射只需要九个点适合固定工作平面的引导贴合场景而标定板标定如张正友法是在解相机的物理内参焦距、主点、畸变系数输出结果可以直接用于三维空间重建和测距。两者解决的问题不同不能互相替代。3.3 OpenCV标定流程和结果验证用OpenCV做张正友标定的流程不算复杂大致是提取角点findChessboardCorners、亚像素精化cornerSubPix、标定calibrateCamera、计算重投影误差、可选undistort去畸变。我常用的验证方式有两种重投影误差calibrateCamera返回的RMS误差一般低于0.3像素就算非常理想0.5像素以内可用超过1像素就要怀疑标定板质量或者图片数量不够。直观验证将去畸变后的图像叠加到原图上看边缘直线比如墙面、门框、地面砖缝是否变直。这个测试很土但很有效能快速发现明显的问题。下面是OpenCV标定核心流程的示例代码我习惯用Python写原型验证完再移植到C或者嵌入式端import cv2 import numpy as np import glob checkerboard_size (8, 6) # 内角点数 square_size 0.030 # 方格边长单位米 # 准备标定点 objp np.zeros((checkerboard_size[0] * checkerboard_size[1], 3), np.float32) objp[:, :2] np.mgrid[0:checkerboard_size[0], 0:checkerboard_size[1]].T.reshape(-1, 2) objp * square_size obj_points [] # 世界坐标系下的三维点 img_points [] # 像素坐标系下的二维点 images glob.glob(./calib_imgs/*.jpg) for fname in images: img cv2.imread(fname) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners cv2.findChessboardCorners(gray, checkerboard_size, None) if ret: obj_points.append(objp) corners_refined cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)) img_points.append(corners_refined) ret, mtx, dist, rvecs, tvecs cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None) print(内参矩阵:\n, mtx) print(畸变系数:, dist.ravel()) print(重投影误差:, ret)这段代码跑完后得到的mtx就是内参矩阵dist就是[k1, k2, p1, p2, k3]这五个畸变系数。需要注意的是rvecs和tvecs是每一张标定板图片对应的外参也就是标定板坐标系到相机坐标系的变换它们可以用于后续的手眼标定或者标定板位姿估计但在内参标定这一步通常不直接使用。4. 从内参到定位畸变校正后的像素坐标到底怎么用标定完内参和畸变系数后接下来的核心问题只有一个校正后的像素坐标如何反算空间位置。这里我把几种最常见的应用链路线整理一下。4.1 针孔反投影把像素变成射线去畸变后任意一个像素点(u, v)都可以先转换到归一化平面坐标x (u - cx) / fx y (v - cy) / fy这个(x, y, 1)就是相机坐标系下的一条射线方向。如果已知目标点在相机坐标系下的深度Zc那么它的相机坐标就是[x*Zc, y*Zc, Zc]。如果是双目系统深度Zc通过视差计算得到如果是单目加已知目标尺寸Zc可以通过PnP求解如果是纯单目运动场景深度要靠多帧三角化。这里有一个常见的混淆很多人用undistortPoints对像素点去畸变然后再用unproject变成射线。OpenCV的cv2.undistortPoints输入的是像素坐标输出是归一化平面坐标它已经包含了内参矩阵的逆变换所以输出不是像素坐标。在使用时要注意区分否则会把归一化坐标误当成像素坐标再乘一遍内参得到完全错误的结果。4.2 PnP求解已知目标尺寸时怎么求空间位置无人机视觉降落常见的一个需求是已知地面上降落标志比如AprilTag的真实尺寸求解无人机相对标志的位姿。这本质上是PnP问题——给定一组三维点和它们对应的二维像素点求解相机也就是无人机相对于标志坐标系的R和t。OpenCV的solvePnP可以直接完成。_, rvec, tvec cv2.solvePnP(obj_points, img_points, mtx, dist) R, _ cv2.Rodrigues(rvec)这里的tvec就是标志坐标系原点在相机坐标系下的位置也就是无人机相对目标的相对位置在相机系下的表达。再通过前面标定得到的外参相机到机体坐标系的R、t就可以换算到机体坐标系进而参与飞控的位置闭环控制。我遇到过的坑是solvePnP在目标距离较远时旋转向量和平移向量之间会出现耦合导致解不稳定。解决办法是使用SOLVEPNP_ITERATIVE并给定一个合理的初始猜测或者直接用SOLVEPNP_SQPNP后者在平面目标场景下通常更稳定。4.3 坐标系转换链从像素到飞控控制指令最后把整条链路串一下。无人机视觉定位的完整坐标变换链是这样的像素坐标 → 去畸变(内参) → 归一化坐标 → 相机坐标系(深度/位姿估计) → 机体坐标系(外参R, t) → 世界/导航坐标系(飞控姿态)每一步的精度都受前面环节影响而内参标定和外参标定是整个链路最底层的两个环节。如果有任何一环的数据不对飞控拿到的位置估计就会在空中画出歪歪扭扭的轨迹。我自己调试时习惯在ROS里用tf2把每一步的坐标变换都发布出来在Rviz里检查中间结果。比如把相机检测到的AprilTag角点投影回图像上看是否和原始像素重合把估计出的目标点在Rviz里和真值对比确认链路是通的。5. 无人机进阶标定相机-IMU外参标定与动态场景下的坑内参标定做完只解决了一半问题。无人机上相机固定在机身上IMU固定在飞控内两者之间有一个固定的相对位姿。这个相对位姿如果不精确视觉和惯性融合时就会出现系统性的误差。5.1 为什么手填外参不靠谱有人觉得相机装在机架正下方、镜头竖直朝下外参就是俯仰90度直接填一个旋转矩阵就行了。这个做法的问题在于手工测量无法保证相机的光轴与机体Z轴完全平行哪怕偏了1-2度在10米高度时横向误差就是20-35厘米。对标定要求不高的定高悬停可能无所谓但做精确降落、电力巡检绕飞或者桥梁检测贴近飞行时这个误差会直接导致碰撞风险。5.2 Kalibr联合标定原理与实战流程Kalibr是目前学术界和工业界用的最多的相机-IMU联合标定工具它通过拍摄一张带二维码的标定板Aprilgrid同时采集IMU数据在批优化中同时估计相机的内参、畸变、相机与IMU的外参以及时间延时。使用Kalibr的大致流程打印一张Aprilgrid标定板每个格子边长建议100mm以上行距和列距标称值要准确。采集数据ROS中同时录制相机话题和IMU话题录制约1-2分钟。关键是要让设备在标定板前做充分的旋转和加速运动要覆盖各个轴的运动但又不能太快导致图像运动模糊。我试过几种运动轨迹模式之后发现慢速平移快速小角度旋转抖动激励的组合效果最好基本能把惯性和视觉的信息都约束住。运行Kalibr估计外参kalibr_calibrate_imu_camera \ --target april_6x6_100mm.yaml \ --cam camchain.yaml \ --imu imu.yaml \ --bag dataset.bag检查结果Kalibr会输出相机到IMU的旋转T_ci和延时td还会给一个重投影误差的可视化报告。如果标定结果里时间延时异常大超过一个相机帧周期说明采集数据时同步没对齐需要重新录。Kalibr对输入数据的质量极其敏感。我碰到过几次标定出来外参方差很大的情况后来发现都是IMU的加速度计偏置没有先初始化好或者标定过程中出现了一定时间的饱和。建议在跑Kalibr之前先用imu_utils工具对IMU做一次 Allan 方差分析确认噪声特性然后再做联合标定。5.3 无人机特有场景中的坑振动、快门和温度漂移无人机上的相机标定和桌面上标定最大的不同在于环境极其恶劣高频振动多旋翼的电机振动频率往往在200-500Hz如果相机没有减震球隔离图像会出现高频运动模糊角点检测精度下降。所以无人机上装视觉相机一定要用减震板或者橡胶球悬挂这不仅对机械有益对视觉精度也至关重要。卷帘快门效应消费级相机和大疆一些云台相机都是卷帘快门飞行时相机快速转动会导致图像出现倾斜、拉伸。在标定和定位时要尽量选全局快门相机或者在后处理中做卷帘快门补偿。温度漂移相机在飞行中会因为电子元件发热和气流冷却发生微小的焦距漂移。我实测过一款工业相机从冷启动到热稳定fx大约漂移了0.3%。对于高精度测绘任务建议每次飞行前让相机预热几分钟或者采用在线标定策略在VIO后端中把相机内参作为待优化状态量持续估计。6. 标定的源头数据采集质量控制的实操经验最后这部分我想讲一个很多人不重视、但真正决定标定成败的环节——数据采集。标定算法再先进输入图像质量不行输出就是垃圾。在无人机场景下标定数据的采集多半需要在地面完成所以这篇不能回避的一个问题是如何在地面上模拟出无人机在空中可能遇到的成像条件让标定结果在真实飞行中依然可靠。6.1 光照条件对特征点检测的影响棋盘格角点检测依赖强烈的黑白对比度。很多人图省事在室内灯光下举着标定板就拍了但无人机实际飞行多在户外强光下逆光、阴影、反光都会影响角点检测。我的建议是在室内标定时尽量开亮一点的灯同时避免标定板表面有反光如果条件允许在户外自然光下补拍几张作为鲁棒性验证样本。如果标定板表面是光面打印纸强光下的反光会导致整片区域过曝角点会全部丢失。6.2 标定结果的重复性验证标定不是一次性的工作。我建议每次重新安装相机或者更换镜头后都重新标定内参外参则要定期检查因为无人机经过一次炸机维修或者换减震板之后相机相对IMU的位置可能已经变了。一种简单的重复性验证方法是固定好相机和三脚架对标定板拍摄3组不同角度的照片分别标定出内参然后对比三组内参矩阵的差异。如果fx的差异超过0.5%就要怀疑相机固定结构是否松动或者镜头有没有移位。6.3 仿真先行在无人机仿真环境中验证整个链路把标定结果真正接入飞控之前我建议先在Gazebo、AirSim这类无人机仿真环境中把整个视觉定位链路跑一遍。仿真环境里的相机模型是理想化的但你可以在仿真中故意加入内参误差、外参误差、噪声和时延观察飞控位置估计的退化情况以此校准真实系统中对各类误差的容忍度。这个方法帮我省下了很多不必要的炸机成本。7. 不同应用场景对标定精度的需求对照说了这么多最后用一张表把不同无人机应用场景对标定精度的需求做个汇总方便你根据实际项目定位来倒推标定方案。应用场景标定关键项典型精度要求标定方法建议视觉定高/悬停内参、畸变内参误差3%畸变校正基本可用张正友法20张即可目标识别跟踪内参、外参像素反投影误差1像素张正友法手工外参粗标视觉降落AprilTag内参、外参外参角度误差0.3°平移误差1cm张正友法Kalibr联合标定VIO/SLAM内参、外参、时间延时外参角度误差0.1°延时2msKalibrAllan方差分析电力巡检/测绘内参、畸变、外参测距误差0.5%20m高精度内参标定定期重标参考这个表如果你的无人机只是做简单的视觉跟随用手工测量的外参问题不大。但如果你要在室内GPS拒止环境下靠视觉做自主飞行那内参、外参、时间同步三者一个都不能马虎。我在实际项目中体会最深的一点是标定不是一次性的仪式它是整个系统链路里需要持续维护的度量基准。无人机出现视觉定位漂移的时候先别急着调算法参数回头重新标一次内外参往往效果立竿见影。如果你正准备给自己的无人机接入视觉模块我建议把标定环节当做一个独立的里程碑来规划前面省下的每一个小时后面都要用十几倍的时间来偿还。
返回列表