
无人机悬停、避障、定点投物这些功能看着是飞控和算法在起作用但真正让无人机“感知”到三维空间的往往是机身下面那颗不起眼的相机。而相机把三维世界变成二维图像这件事本身是有误差的镜头畸变、安装偏差、像素坐标与真实尺度的换算关系这些统统都要靠相机模型和标定来解决。我在调试植保无人机和室内视觉定位无人机时被重投影误差和畸变问题折磨过不少次后来把相机模型和标定流程彻底吃透之后所有视觉相关的问题都变得可控了。这篇文章就围绕相机模型与标定在无人机上的应用展开讲清楚原理也给出可以直接照做的操作流程适合正在做视觉SLAM、无人机自主导航或者刚接触机器视觉的开发者参考。1. 先搞清楚相机怎么“看”空间从针孔模型开始1.1 针孔模型为什么能描述三维到二维的映射相机成像的本质其实就是一个小孔成像。光线从三维空间中的某个点出发穿过相机光心投射到后方的感光平面上。这个过程中三维点(X, Y, Z)被映射成二维像素坐标(u, v)中间的数学关系就是针孔相机模型。实际相机用的都是透镜组等效光心到感光芯片的距离就是焦距f。把世界坐标系中的一个点P(X, Y, Z)转到相机坐标系再根据相似三角形关系映射到像素平面就得到u fx * X/Z cx v fy * Y/Z cy这里fx、fy是焦距在像素单位下的表示cx、cy是主点偏移。注意X/Z这个形式它说明尺度信息在单目相机里是丢失的这也是为什么无人机单目视觉测距往往需要借助已知高度、已知目标尺寸或者其他传感器辅助。理解了这一点就能明白为什么无人机视觉定位系统里相机标定只是第一步后面往往还要接IMU、气压计或RTK去补全尺度。1.2 内参、外参、畸变三个绕不开的参数组相机标定最终要得到的是三个层面的参数。内参描述的是相机自身的几何属性也就是上面这个矩阵KK [fx 0 cx] [ 0 fy cy] [ 0 0 1]内参决定了像素坐标和归一化平面坐标之间的映射关系。只要相机不换镜头、不改变分辨率内参理论上不会变。外参描述的是相机在某个参考坐标系下的位姿也就是旋转矩阵R和平移向量t。在无人机上外参通常指相机相对于机体坐标系、IMU坐标系或者世界坐标系的相对位姿。比如你要做视觉导航就要知道相机看到的目标在机体坐标系下的方位这时相机到机体的外参就是必须的。畸变参数描述的是镜头加工和装配带来的成像误差。主要分两类一类是径向畸变也就是画面边缘向里凹或向外凸的“桶形”和“枕形”畸变用k1、k2、k3三个系数来拟合另一类是切向畸变源于镜头和感光芯片的平行度偏差用p1、p2两个系数来描述。畸变模型通常写作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实际标定时畸变系数用得最多的就是k1、k2、p1、p2k3一般只在鱼眼镜头或者畸变特别大的广角镜头上才需要。无人机上常用的镜头多为广角或超广角边缘畸变往往不小k3该用还是得用。1.3 无人机场景下的模型选择无人机上用的相机型号很杂从普通的卷帘快门广角相机到全局快门小相机再到双目相机、鱼眼相机模型选择完全不一样。普通广角镜头用标准针孔模型就够。鱼眼镜头如果视场角超过120度针孔模型在边缘的拟合效果会变得很差这时应该用等距投影模型或单位球模型OpenCV里对应的就是fisheye模块Kalibr里也有pinhole-equidistant这种模型组合。双目相机在单目内参标定的基础上还要额外标定左右相机的相对外参和基线长度这直接决定了深度估计的精度。很多工业无人机用的双目模块比如小觅、ZED出厂带标定参数但运输振动、温度变化会导致参数漂移实际项目里我还是建议自己重新标一遍。还有一个容易被忽略的问题卷帘快门。消费级无人机上大多数CMOS都是卷帘快门高速运动时画面会出现果冻效应。如果做高速避障或动态目标跟踪最好选全局快门的工业相机否则标定得再准图像采集本身就已经带了运动畸变。这一点在选型时就该想清楚等算法跑起来发现问题再换相机成本就高了。2. 标定前的准备工作工具选型与标定板设计2.1 常用标定工具对比标定工具我实际用过三类各有优劣。OpenCV自带的cv2.calibrateCamera最基础代码简单文档多适合快速验证但精度一般主要是因为它对棋盘格的角点检测算法比较老旧而且没有对帧间位姿做优化。MATLAB的Camera Calibrator体验好很多交互式界面能实时显示重投影误差和每张图的位姿初学者很容易看懂但需要MATLAB许可。Kalibr是目前视觉SLAM社区里最常用的标定工具它支持多种相机模型、多相机联合标定、相机与IMU联合标定精度高输出直接对接VINS、ORB-SLAM等系统缺点是安装比较麻烦依赖库多。我的建议是普通内参标定用MATLAB或者OpenCV都行做VIO或者视觉惯性导航项目时直接用Kalibr一步到位。Kalibr标出来的相机内参、外参、IMU外参格式和VINS-Mono无缝衔接省去手动转换参数的麻烦。2.2 标定板设计棋盘格、AprilTag、Charuco怎么选标定板的选择直接影响角点检测的稳定性。传统棋盘格是最常见的角点是黑白方块的交点检测算法成熟。但棋盘格有一个致命问题如果图像里只拍到部分棋盘格或者有遮挡会导致角点排序混乱因为棋盘格本身没有方向信息。飞无人机的时候标定板很难一直完整出现在画面中央经常是拍到一半传统棋盘格的鲁棒性就下降了。AprilTag和Charuco这类带编码信息的标定板可以解决这个问题。它们是二维码和棋盘格的结合体每个格子都携带独立的ID信息即使只拍到局部算法也能知道这一部分是标定板的哪个位置。我实际测试下来Charuco在无人机室外标定场景里最实用因为无人机飞行姿态变化大拍到的标定板往往不完整Charuco的鲁棒性让它基本不会出现角点错乱。打印标定板时有两个细节必须注意。第一必须用高分辨率激光打印机普通喷墨打印的黑色块边缘会有毛刺像素级角点检测直接受影响。第二标定板要贴在完全平整的刚性背板上KT板、纸板都会翘边最好用铝塑板轻且硬。2.3 无人机场景的标定环境布置要点无人机标定有个特殊的地方就是相机视角问题。普通相机标定固定相机对着标定板拍就行但无人机相机通常朝下或朝前安装你很难把无人机固定在一个完美的角度。我的经验是如果相机可以拆卸直接拆下来放到三脚架上标定这样图像质量最高。如果相机不可拆就把无人机固定在一个稳定的支架上让标定板在相机视野内移动。注意标定原理其实是标定板在动、相机不动或者反过来都需要保证标定板覆盖视野的各个区域尤其是边缘。环境光线尽量均匀柔和。室外强烈阳光下标定板黑格和白格的对比度会降低甚至反光我遇到过好几次因为反光导致角点检测失败的情况。室内用LED面板灯补光保证标定板亮度均匀是最理想的状态。3. 从零开始做一次完整的相机标定3.1 图像采集数据质量决定了标定质量标定图像采集是整个流程里最容易被忽视、但影响最大的环节。很多初学者拿相机随便拍十几张图就开始跑标定最后重投影误差确实小但实际用在无人机导航里却漂得厉害原因就是标定图像过于类似参数解算不唯一。理想的标定图像应满足以下几个条件数量在20到30张之间太少参数不稳定太多信息冗余计算时间也变长标定板需要出现在画面的不同位置四角、四边、中心都要有覆盖标定板相对相机的姿态要多样包括俯仰角、偏航角的变化不要只是正对着相机前后移动标定板和相机之间的距离要变化让标定板在画面中的尺度有差异这有助于解算出更准确的焦距画面里不能有运动物体遮挡标定板也不能有强反光采集图像时我用过一个实用的技巧边拍边移动标定板同时观察角点检测结果。OpenCV里可以实时显示检测到的角点如果有图像检测异常当场重拍。等到全部拍完再处理发现某几张图有问题还得重新布置场景效率太低。3.2 角点检测与参数求解实际上是怎么算出来的这里说标定算法是怎么一步一步把参数解出来的。先用棋盘格上的角点像素坐标作为输入再通过张正友标定法求解。张正友法的核心思想是把标定板看作一个平面平面上所有点的Z坐标都等于0这样就可以先估计一个单应性矩阵然后利用不同位姿下多个单应矩阵的约束线性地解算出内参的初始值再用最大似然估计对所有参数做非线性优化。OpenCV里的cv2.findChessboardCorners负责角点检测也就是找到图像中棋盘格内部角点的像素坐标。检测到足够多的图像后cv2.calibrateCamera会完成上述的初值计算和非线性优化返回内参矩阵、畸变系数以及每张图像对应的外参。Kalibr的标定流程稍微不同。它使用Aprilgrid或Checkerboard标定板通过kalibr_calibrate_cameras命令在YAML配置文件中指定相机模型和畸变模型输出的结果是一个包含相机内参和畸变系数的JSON文件。Kalibr的优化过程还会考虑标定板自身的误差模型所以精度通常比OpenCV高。有个参数值得单独说标定板的格子边长。这个物理尺寸必须精确测量而不是照抄标定板文件里的标称值。打印过程会有缩放卡纸厚度也会影响实际尺寸用游标卡尺量一下最保险。这个参数错了标定出来的焦距就会成比例地偏大或偏小影响后续所有基于像素坐标换算距离的计算。3.3 结果评估重投影误差怎么看重投影误差是衡量标定质量最直观的指标。它表示把三维角点通过标定出来的内外参重新投影到图像平面得到的像素坐标和实际检测到的像素坐标之间的距离单位是像素。OpenCV标定结果里会直接输出RMS重投影误差。一般要求小于0.5像素如果超过1像素说明图像数据质量有问题或者标定板不平整需要重新采集。MATLAB的Camera Calibrator界面里每一张图片都会显示平均误差用柱状图列出可以很方便地找出误差偏大的图像并将它剔除。单纯看整体RMS还不够我习惯再做一个验证用标定好的参数对图像做畸变校正然后观察画面边缘的直线是否变直。比如拍一扇门或建筑的边缘畸变校正后直线的弯曲程度直观可见。这一步能发现重投影误差掩盖掉的局部畸变问题。无人机上最终用的是校正后的图像所以标定参数的正确性可以通过校正后的图像来判断。如果校正图像边缘有非自然的扭曲说明畸变模型选择可能不对比如普通针孔模型用在鱼眼镜头上就会这样需要考虑换用其他模型重新标定。3.4 把结果用到无人机里内参写入相机驱动标定完成后内参和畸变系数要写到实际的感知代码或相机驱动配置里。这里的关键是坐标系定义必须一致否则参数直接套用会出错。最常用的格式是ROS的CameraInfo消息包含内参矩阵K、畸变系数D、分辨率等信息。在ROS里图像话题通常和CameraInfo话题成对发布图像处理节点通过image_proc包对原始图像做去畸变得到校正图像。如果是在Pixhawk或PX4的视觉惯性导航系统里标定参数一般写到VINS-Mono或ORB-SLAM3的配置文件里同时还要把相机到IMU的外参写进去。外参的坐标系转换关系要格外注意不同框架规定的旋转顺序不一样VINS-Mono用的就是“相机到IMU”的变换写反了整个系统都会发散。还有一个容易被忽略的点校准后的图像分辨率。如果你标定用的是1280x720的图像但运行算法时用1080p那内参必须按缩放比例重新换算不能直接沿用。fx、fy、cx、cy都要乘以对应的比例系数很多开发者都在这上面翻过车。4. 从单相机到多传感器外参标定与手眼标定4.1 无人机视觉定位为什么一定要标外参无人机上很少只靠一个相机工作。视觉惯性导航系统里相机要和IMU配合IMU提供高频的角速度和线加速度相机提供低频的视觉约束两个传感器数据融合的前提就是精确知道相机和IMU之间的相对位姿也就是外参。外参标定常用的工具是Kalibr的kalibr_calibrate_imu_camera模块。它通过让无人机或相机做特定激励运动比如正弦摆动、八字形运动同时采集IMU数据和图像数据联合优化出相机到IMU的旋转矩阵和平移向量。这里有个实操经验标定IMU-camera外参激励运动必须足够丰富。只做匀速运动或者静止IMU的加速度和角速度没有足够的可观测性外参解算不出来。至少要包含三个轴的旋转和三个轴的平移保持1到2分钟期间动作尽量平滑但快速。实测下来绕三个轴画“8”字是效率最高的运动模式。外参标定的结果直接决定了VIO系统的初始化速度和长时间漂移程度。外参误差只要超过1度或平移误差超过1厘米融合后的轨迹就会明显漂移。4.2 手眼标定在无人机云台上的应用无人机云台上的相机标定本质上是一个手眼标定问题。云台转动时相机的朝向在变化但相机相对于云台末端的安装位置是固定的。我们需要求解的就是相机坐标系到云台末端坐标系之间的固定变换。手眼标定的标准方程是AXXB其中A是云台末端的前后两次运动变换B是相机坐标系的前后两次运动变换X就是要求解的相机到云台的固定变换。实际做的时候让无人机云台转到多个不同角度每个角度下用标定板解算相机外参同时记录云台上报的姿态角用solvePnP的结果和云台姿态角就可以构造出A和B然后用Tsai-Lenz或其他求解算法得到X。这个变换对云台相机的视觉锁定和目标跟踪非常重要。因为云台一直在转动如果不知道相机相对云台的精确安装关系就无法把图像中目标的位置换算到云台坐标系下也就无法控制云台精准转动去跟踪目标。很多开源云台相机的跟踪效果不理想就是卡在这一步没有标定。4.3 双目相机和LiDAR相机联合标定无人机避障系统里还有一种常见组合是双目相机或者LiDAR加相机。双目相机需要标定左右目之间的相对外参这个用Kalibr的kalibr_calibrate_cameras可以直接完成它会同时优化左右相机的内参和它们之间的外参结果可以用来做立体校正。LiDAR相机标定稍微复杂一些因为LiDAR点云和图像数据是异构的要在3D点和2D像素之间找对应关系。常规做法是摆放带反光标记的标定板或者用带有明显边角的箱子先在LiDAR点云中检测出平面或角点再在图像中找到对应的像素位置通过P3P或EPnP求解外参。也有基于互信息的自动标定方法不需要标定板但鲁棒性不如手动方法更适合实验结果稳定后的微调。无人机上如果用LiDAR做定位、相机做目标识别这种多传感器融合的场景联合标定的精度直接决定融合效果。我在实际项目中遇到过因为外参没标准LiDAR检测到的障碍物和相机检测到的障碍物在空间上重合不到一块的情况后面重新做了联合标定问题就消失了。5. 常见问题与排查技巧实录5.1 重投影误差偏大的排查思路重投影误差偏大的时候不要急着调整算法参数先按这个顺序排查先检查标定板是否平整。把标定板放在桌面或地板上观察四个角是否悬空。很多标定板用久了会翘角这会导致局部的角点坐标偏移重投影误差自然大。再检查角点检测是否正确。用可视化工具把所有标定图像的角点画出来逐张确认有没有漏检、错检。尤其是棋盘格被部分遮挡时角点顺序很容易乱。然后检查图像数量是否充足。低于15张的标定结果可信度很低。如果前面都没问题试着剔除掉重投影误差最大的一两张图像重新标定误差通常会有明显下降。如果所有图像都剔除后误差还在0.8像素以上那就要怀疑畸变模型选择是否匹配镜头了。普通广角镜头用pinhole-radtan模型鱼眼镜头用pinhole-equidistant或fisheye-equidistant模型模型不匹配时会反映在重投影误差上而且校正后的图像边缘会有明显扭曲。5.2 角点检测失败和误匹配的常见原因角点检测失败最典型的原因是光照不均和反光。标定板上有强反光时白色格子过曝成一片角点附近失去对比度检测器定位不准。解决办法调整标定板角度避免阳光直射产生镜面反射室内用散射光源。另一个原因是运动模糊。手持无人机或标定板不稳快门速度跟不上运动速度图像边缘就会糊角点位置偏移。无人机标定时最好把无人机固定只移动标定板或者反过来保证相对运动可控。如果必须用手持拍摄用大光圈的工业相机配合高快门速度能有效减少模糊带来的定位误差。还有一个容易忽视的是标定板图案分辨率过低。远距离拍摄时棋盘格在画面里只占很小区域单个格子的边缘在像素级别已经模糊角点检测自然不精确。出现这种情况要么靠近一点要么换大格子标定板。5.3 不同分辨率、不同温度下的标定漂移标定参数不是一劳永逸的这个必须说清楚。同一个相机如果工作分辨率变化内参就要按比例重新换算。如果镜头可以变焦那焦距变化后必须重新标定。如果相机模组经历过剧烈振动或者维修内参也可能发生微小漂移因为镜头和感光芯片之间的相对位置可能变了。温度影响是无人机特有的问题。无人机在户外作业时白天暴晒和傍晚降温温差可能超过20度镜头光学元件的折射率和机械结构尺寸都会发生变化表现为标定参数轻微漂移。严格的项目里冷态和热态各标定一次分别存参数根据环境温度切换。大多数消费级场景不需要这么精细但要意识到温度突变后视觉里程计精度下降很可能是标定参数漂移导致的。经验是长时间使用的无人机每季度做一次内参标定检查用旧参数对当前图像做畸变校正如果边缘直线的弯曲明显那就该重新标定了。5.4 实测排除记录一张表速查常见问题我整理了一份无人机相机标定常见问题速查表覆盖我实际开发中遇到过的高频问题帮助快速定位故障原因。现象可能原因排查方法解决方案重投影误差大于1像素标定板翘曲/不平整放在平面上观察四角换铝塑板重新粘贴重投影误差集中在一侧标定板图像不均匀/照明偏差查看单张图像误差分布调整光源重新采集角点检测错乱棋盘格被部分遮挡/方向无编码检查检测可视化使用Charuco/AprilTag标定板校正后边缘扭曲严重畸变模型不匹配换用鱼眼模型对比选择正确的畸变模型校正图像分辨率不对标定和运行分辨率不一致检查图像尺寸按比例重算内参VIO初始化失败相机IMU外参不准检查激励运动是否充分重新采集数据标定外参温度变化后定位漂移镜头热胀冷缩用旧参数测试校正效果冷/热态分别标定双目深度不准基线长度误差重新标定双目外参检查基线是否变动这张表基本就是我遇到的最常见问题的集合。很多问题表面看起来像算法不行实际查到最后都是标定数据没做好花了大量时间往错误方向排查最后绕回来重新做标定就解决了。6. 实操心得标定这件事最容易被忽视的两个细节说两个我踩过坑之后收获最大的经验。第一个是标定板尺寸和拍摄距离的匹配。标定板的棋盘格尺寸决定了它能被准确检测的最近和最远距离。如果标定板太小无人机相机离它近的时候画面里只会有几个格子角点太少单张图像提供的约束不足。如果标定板太大又不容易让它在画面边缘出现。我做室内无人机视觉定位时用的是A2大小的Charuco标定板格子边长30mm无人机在1到3米距离上拍摄效果最理想。室外用大疆无人机标定因为镜头视野广A1大小的棋盘格才能同时满足近处和远处的覆盖需求。第二个是标定数据的“多样性”权重比“数量”更高。我之前犯过一个典型错误为了凑数量在几乎同一个位置、同一个角度拍了30张图最后标定结果重投影误差很小但实际飞行中视觉定位系统表现很差因为那些图像提供的信息几乎是重复的。后来我调整策略每个位置拍两三张但让标定板覆盖画面九个区域同时每次之间改变倾斜角度和距离20张图的效果远超之前30张重复图的效果。标定求解的是一个高维参数空间的最小化问题让观测数据在参数空间里“撑开”才是关键。相机模型和标定这件事看起来是视觉SLAM里最基础的一环但恰恰是这一环决定了整个无人机视觉系统的上限。内参不准确畸变校不准后面的特征匹配、位姿估计、三维重建全都建立在错误的像素坐标上算法再先进也救不回来。我建议在做任何无人机视觉项目时把标定当成一个重要环节来抓而不是随便跑一下脚本就完事。前期多用一点心思把标定做扎实后面调算法的时候会省掉大量的麻烦。