ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

统一单目与多目视觉标定:内参、外参与全局优化实践

2026/9/15 17:56:51 拓冰建站 浏览量
统一单目与多目视觉标定:内参、外参与全局优化实践 单目和多目视觉统一标定这个话题我琢磨了很久。在工业现场做视觉项目最常遇到的情况是手上有几台相机有的是单目有的是双目甚至还有三目、四目组成的拼接系统每台相机的型号、分辨率、镜头畸变都不一样。项目刚开始时永远是测内参、调外参、换镜头、重新标定一套流程走下来非常耗时。后来我干脆把单目和多目相机的标定流程整合到了一套框架里统一建模、统一数据格式、统一误差评估。这篇文章就把我踩过的坑和最终沉淀下来的方法完整拆给你适合刚入行想做视觉标定或者已经在做但被多相机一致性问题折腾过的朋友参考。1. 统一标定到底在解决什么问题1.1 视觉系统的标定本质很多人一听“标定”就觉得是拿标定板拍几张照片跑一下程序就完事。但实际上标定的本质是建立“图像像素坐标”和“真实物理空间坐标”之间的一一映射关系。相机拍到的是一张二维图像像素坐标只能告诉你某个点在画面里的位置但要跟机器人、机械臂、测量平台联动就必须知道这个点在三维空间里的确切位置。这个转换关系由相机的内参、外参共同决定。内参描述的是相机本身的光学属性包括焦距、光心位置和镜头畸变外参描述的是相机在世界坐标系里的位置和朝向。单目相机标定相对简单只需要估计内参和畸变系数推导公式可以简化为像素坐标对三维点的投影映射。多目系统的工作量则成倍增长除了每台相机各自的内参还要确定各相机之间的相对位姿即外参。这个外参误差一旦偏了后面的三维重建、目标定位、拼接融合都会跟着错。更麻烦的是如果你把单目和多目分开标定用两套不同的程序、不同的标定板规格、不同的优化策略得到的参数在统一应用时经常出现坐标系对不齐、误差指标不可比的问题。所以我才决定把两类标定收敛到一个框架里让单目是基础单元多目是多个基础单元加空间约束的扩展。1.2 统一框架的设计目标在我自己的实践中统一标定框架要有四个核心能力。第一单目、多目共用同一套数据采集格式和同一套标定板配置这样现场操作人员不需要学两套流程第二单目标定是独立的模块可以单独输出内参也可以作为多目标定的初始化输入第三多目标定在拿到各相机内参后通过特征点关联自动求解相机间相对位姿并且支持任意数量的相机组合不需要为双目、三目分别写死代码第四统一的误差评估指标不管几台相机最后都用重投影误差来衡量标定质量方便横向对比。这套框架落地之后最直接的收益就是项目周期缩短了。以前做一套双目光学测量标定加调试大概要两三天现在把流程统一后硬件装好、标定板拍一拍半天内就能把内参和外参全部算出来而且精度更稳定。下面我就把这套框架从单目标定到多目标定的实现细节完整拆开讲。2. 单目视觉标定的核心参数与实操流程2.1 需要估计的参数到底有多少单目相机标定最经典的是针孔模型加畸变修正。在针孔模型下空间中的一个三维点会在图像平面上投影出一个像素点这个过程用数学表达就是内参矩阵K [fx 0 cx] [ 0 fy cy] [ 0 0 1]fx和fy代表焦距在像素单位下的数值cx和cy是光轴与成像平面的交点一般靠近图像中心。严格来说如果像素是正方形并且镜头没有安装误差fx等于fycx约等于图像宽度的一半。但在实际项目中CMOS感光芯片的像素尺寸并不是绝对正方形镜头安装也会有轻微偏斜所以我从来不直接假设fx等于fy一律当作独立参数去估计。更关键的是畸变系数。各种工业镜头都有不同程度的畸变常见的径向畸变和切向畸变让直线在图像边缘变成曲线。模型里一般用五个畸变系数描述前三个是径向畸变系数k1、k2、k3后两个是切向畸变系数p1、p2。对于普通工业镜头用k1、k2就差不多了拍摄精度要求高的项目才会引入k3甚至更高级的畸变项。我踩过的坑是不要一上来就用高阶畸变模型畸变参数越多优化不稳定很容易收敛到局部最小值标定结果看起来重投影误差很小但实际上画面被修正得过度扭曲。正确做法是先做五参数模型看看效果如果重投影误差已经很小就不要再加高阶项了。2.2 标定板选择与数据采集要求标定板我强烈推荐用高精度的陶瓷或者玻璃基板而不要用自己用普通打印机打的图纸。打印纸受潮、变形、反光都会直接影响角点提取精度。标定板图案也尽量用非对称圆点阵列虽然棋盘格更通用、角点检测算法更成熟但圆点阵列在极端角度看过去不容易出现“奇异性”问题而且圆心提取精度可以做亚像素对标定精度的贡献比棋盘格稳定。圆点阵列还有一个好处是对遮挡和反光的鲁棒性更强现场实验室灯光复杂时棋盘格经常出现黑白格边界过曝角点检测直接崩掉。采集图像的规则比很多人想象中更重要只拍十几张正面图是绝对不够的。标定板在相机视野内的姿态要覆盖尽量多的变换维度左右平移、上下平移、倾斜、抬头、低头、旋转每种姿态都要有几张。一个比较稳妥的采集方案是拍摄二十到三十张图且保证每张图里的标定板有效面积占据画面的三分之一以上。同时标定板所在平面的角度变化要超过30度如果所有照片的标定板都正对相机内参的解算会非常不稳定尤其是fx和cy这几个参数会“漂移”。我用OpenCV做单目标定时一般要保证检测到的角点数量足够多每张图像至少提取到标准角点数的百分之八十以上少于这个标准的图像我会直接扔掉避免劣质数据拉低整体精度。2.3 利用OpenCV完成单目标定的完整流程单目视觉标定流程在OpenCV里已经很成熟核心函数就一个cv::calibrateCamera但想把它用好还是有不少讲究。完整的数据准备是这样的首先定义物理坐标系下的三维点即标定板上各个特征点的真实空间坐标单位是毫米以标定板左上角为原点板面方向为Z0平面然后从每张图像里检测出所有可见角点或圆心得到对应的像素坐标最终把多组对应关系丢给相对位姿估计算法算法内部会用迭代优化的方式同时估计内外参数并把重投影误差不断压小。具体的核心代码流程大致是这个样子vectorvectorPoint3f objectPoints; // 每张图中特征点的世界坐标 vectorvectorPoint2f imagePoints; // 每张图中特征点的像素坐标 Size imageSize img.size(); Mat cameraMatrix, distCoeffs; vectorMat rvecs, tvecs; double rms calibrateCamera( objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, CALIB_FIX_K3 | CALIB_FIX_ASPECT_RATIO );这里我特别强调一下优化标志位。CALIB_FIX_K3意味着我们不优化三阶径向畸变系数把它固定为0前面说过这是为了防止过度拟合。CALIB_FIX_ASPECT_RATIO意味着固定长宽比不变在工业相机里如果镜头参数明确知道像素是正方形就可以加上这个标志减少自由参数但如果镜头标称值不可靠就不要加让算法自己算。initUndistortRectifyMap可以将内参和畸变系数应用到图像上做去畸变这个map是逐像素映射生成一次后可以在实时视频流里反复使用不会占用过多CPU。标定完成后的第一件事是看RMS值。RMS代表重投影误差的均方根单位是像素。通常低于0.2像素就算优秀低于0.5像素可接受如果超过0.8像素就要认真检查数据了。我见过不少人只盯RMS一个数字其实更科学的做法是看每个图像的单独重投影误差找出误差特别大的那一两张大概率是光线不均匀或相机轻微抖动导致的直接删掉重新标定反而更干净。3. 多目视觉外参标定与坐标系统一3.1 多目标定的核心难点单目标定完成后每台相机已经有了自己的内参和畸变系数但这只是第一步。多目系统要求把所有相机放到同一个世界坐标系下这样才能把多个相机的图像信息融合到一起。以双目系统为例假设左相机坐标系是基准坐标系右相机坐标系相对左相机有一个旋转矩阵R和平移向量T这就是我们要标定的外参。如果系统里有第三台相机就还要标定第三台相机相对基准坐标系的R和T以此类推。多目比双目复杂的地方在于不仅要保证相邻两台相机之间的相对位姿准确还要保证整体位置关系是全局一致的也就是A到B、B到C、C到A的相对位姿经过空间变换后必须闭合到同一个位置否则融合出来的三维重建结果就会漂移。这里要特别提醒一个很容易被忽略的问题多目相机之间的同步性。标定过程中多台相机必须同时采集同一块标定板的图像。如果某台相机触发延迟了哪怕几十毫秒操作人员在移动标定板时就会导致同一物理位置对应到不同时刻的空间姿态求解出来的外参自然就错了。我一般用硬触发信号把所有相机同步触发软件端再检查每帧图像的时间戳是否一致。没有硬件同步能力的话就让标定板完全静止后再触发拍摄虽然效率低但可靠。3.2 两两标定与全局一致性优化我的统一标定框架里多目标定不是让所有相机一次性参加一个大优化而是分成两两标定和全局优化两步。两两标定的好处是稳健先用常规的双目标定方法计算出相邻相机之间的R和T作为初始值再把这个初始值送去全局优化去微调。OpenCV里面的cv::stereoCalibrate就是做这件事的它会把两台相机同时出现的图像的对应点作为输入同时优化两个相机的内参和它们之间的相对位姿。它的输入比单目多了左图、右图的对应点输出则是R和T以及两个相机的内参。伪代码大致是这样的double rms stereoCalibrate( objectPoints, // 左右相机共视标定板的三维点 imagePointsLeft, // 左相机检测到的特征点 imagePointsRight, // 右相机检测到的特征点 cameraMatrixLeft, distCoeffsLeft, cameraMatrixRight, distCoeffsRight, imageSize, R, T, CALIB_USE_INTRINSIC_GUESS );两两标定之后如果系统只有两台相机事情就结束了。但如果是三台或以上两两算出来的外参不一定满足全局闭合约束。比如相机1到相机2的相对位姿是R12、T12相机2到相机3的相对位姿是R23、T23那么相机1到相机3可以由这两段推算出来但同时直接标定相机1和相机3又会得到一个结果这两个结果很可能不一致。我的做法是先用推动建图的方式把所有相机对的初始外参放到一个位姿图里然后用图优化去均匀调整所有节点的位姿让所有成对约束的误差总和最小。这个优化我一般用g2o库实现变量就是每台相机在统一世界坐标系下的位姿约束就是每对相机的相对位姿观测。多目标定框架里这一步的价值就是它保证系统任意两台相机之间的坐标关系都是一致的不会出现A和B衔接好了、B和C也衔接好了但A和C对不上这种尴尬情况。3.3 多目系统的标定操作实例用一个三相机拼接测量系统来举例实际流程是这样的。先把三台相机固定在铝型材框架上调整高度和角度让相邻相机之间的视野有约百分之三十的重叠区域这样可以确保标定板出现在重叠区域时三台相机都能完整看到。然后在重叠区域放置标定板改变标定板的姿态和位置三台相机同步曝光采集大概三十组图像。每组图像里都要能检测到标定板的特征点并且同一组三张图像中标定板出现的空间姿态应该一致。采集完数据后我先用单目模块分别处理三台相机得到三套内参。再用双目标定分别计算相机1和相机2、相机2和相机3、相机1和相机3的相对位姿。最后把这三对相对位姿放进全局优化器输出每台相机的世界坐标位姿。最终结果验证时我会把标定板放在几个不同位置三台相机同时重建标定板中心的物理坐标测量这三组重建结果的最大偏差。在我实际项目中这套方法把最大偏差控制在了0.3毫米以内而之前用两两标定不做全局优化时偏差会到0.8毫米左右多目系统的全局一致性优势非常明显。4. 统一标定的误差来源分析与避坑指南4.1 标定过程中最常见的误差来源所有标定误差最终都体现在重投影误差变大上但根源不一。我归纳下来主要有五类。第一类是标定板本身精度不够。如果标定板上圆点圆心距标称是30毫米实际只有29.8毫米那么三维点坐标全部错了后面怎么优化都是错的。这种情况在廉价打印棋盘格里极其常见所以严肃项目必须用高精度定制标定板最好有出厂精度报告。第二类是图像采集质量有问题包括运动模糊、失焦、局部反光。运动模糊会让角点检测位置偏移失焦会让边缘过渡区变大亚像素提取的精度自然下降。第三类是标定过程中的光照变化。有些现场的照明是频闪的不同曝光时刻亮度差异大这会让二值化和特征点提取在部分图像上失效。第四类比较隐蔽是标定板放置姿态覆盖不足。很多人担心标定板倾斜太多会检测不到特征点于是所有图都是正对镜头拍这导致从图像信息中解出的内参矩阵病态性很强。焦距和光心之间会相互补偿虽然重投影误差好看但真实的焦距值却偏离物理实际。第五类是相机硬件本身的噪声和温漂。工业相机长时间运行后芯片发热焦距会有细微变化标定时室温低、运行后工作温度高标定参数就不完全匹配工作状态了。针对这些误差我的习惯性检查方式是标定完成后把每一张图像的单独重投影误差画成柱状图很快就能发现异常图片再去看那张图的拍摄条件判断是否属于应该删除的脏数据。误差普遍偏大的话先怀疑标定板精度再怀疑图像质量最后才去检查算法参数设置。4.2 重投影误差和生产精度之间的对应关系很多人标定完看到RMS是0.15像素就觉得万事大吉但我要说一句重投影误差只是衡量标定质量的间接指标它和生产系统最终的物理测量精度并不是简单的一一对应关系。仍然要综合看工作距离和视场大小。同样是0.1像素的重投影误差在一个视场为500毫米宽的系统中对应的物理误差可能在0.1毫米级别而在一个视场为2米的系统中对应的物理误差可能就要扩大到0.5毫米。所以标定误差必须结合“每个像素代表多少毫米”这个比例关系去评估。为了更直观我习惯在标定后做一个快速验证让机械臂末端带着一个精密小球移动到几个不同位置通过多目相机重建小球的三维坐标和机械臂反馈的坐标做差这个差值才是生产系统真正关心的三维定位精度。这套验证流程虽然多花一点时间但能提前暴露很多隐藏问题比如相机的安装是否松动、镜头的锁紧是否到位、标定板到工作平面的距离是否超出了适用景深。4.3 现场标定的避坑操作清单我把这些年积累下来的标定避坑经验整理成了一份清单。首先镜头的光圈一定要固定不能在标定过程中调整光圈因为光圈大小会影响畸变的大小和通光量改变光圈相当于改变了相机内参。我对所有参与测量的相机都是手动锁定光圈并且用胶带标记防止现场有人误碰。其次镜头的光学防抖能关就关工业相机的镜头一般没有防抖但固定在移动机械臂上的相机要考虑减振措施标定过程尽量在设备静止状态下进行。再有就是标定板要远离强反射面比如工作台如果是镜面金属反光会直接干扰标定板特征提取。还有一个高频问题相机分辨率在标定和使用时必须一致。有人标定用1920乘1080的原始分辨率使用的时候为了帧率缩放到1280乘720但内参矩阵里的fx、fy、cx、cy是按原始分辨率算出来的不按比例缩放自然会错。如果确实要用低分辨率实时处理一定要把标定参数按分辨率缩放比换算好再使用。5. 统一标定框架的工程化要点和扩展方向5.1 工具链选择与各方案对比统一标定的工具链选择直接关系到项目的维护成本。我在不同阶段试过Matlab标定工具箱、OpenCV标定模块以及开源的Kalibr多相机标定工具。Matlab的单目和立体标定工具箱对小白最友好有图形界面可以实时查看检测误差但自动化批量处理很费劲写脚本又绕不开Matlab授权和体积的问题。OpenCV最灵活部署起来不受限而且和后续视觉处理代码天然是一套技术栈所以我最终把OpenCV作为统一标定框架的主要实现载体。Kalibr在多相机标定和IMU联合标定这块做得很好它的多相机标定支持多种类型相机包括鱼眼模型对多相机全局优化也内置了图优化但它的依赖和环境配置比较重文档也偏学术化现场调试时效率不高。如果是做研究原型Kalibr值得一试但做工业交付我更推荐基于OpenCV自建工具链。表格对比更直观工具上手难度多相机扩展性全局优化工业部署Matlab标定工具箱低一般有限差OpenCV中高可自行实现好Kalibr高高内置一般综合来看我在实际项目里养成了这样一套习惯快速验证和理解原理用Matlab正式项目全部转OpenCV做科研预研时再引入Kalibr做交叉验证。5.2 从标定到批量生产的一体化落地统一标定框架并不只是写在离线脚本里的几段标定代码我把它做成了一个可直接在产线使用的工具模块。具体分成三个环节。第一个环节是设备出厂标定。每套视觉系统组装完成后在专用标定工位拍摄标准图像传入标定算法输出一个包含所有相机内参、外参、镜头畸变系数的JSON文件。第二个环节是现场快速恢复。如果生产现场有设备经过运输或维护后发生位置偏移不需要重新做整套标定只要拍摄当前状态下的标定板并和出厂参数做对比算法自动提示哪台相机发生了偏移、偏移了多少辅助现场人员做调整。第三个环节是周期复校。我建议每三个月做一次完整的标定校核因为振动、热胀冷缩、安装松动都会让外参缓慢漂移而内参一般变化不大所以复校时优先检查外参是否偏移内参的重新标定频率可以放低一些。这套框架做出来之后不同项目的配置也变得更加标准化了。后来接新项目时只需要改一下标定板的圆心间距、相机数量和视野尺寸这些配置核心标定代码完全不动新项目的标定验证周期从上星期的级别压缩到了一天以内。这也是我个人最推荐大家去做的方向把标定逻辑从单次脚本升级成可复用的底层能力模块才能真正解决多视觉系统的生产效率问题。5.3 更高级的扩展与激光雷达或IMU的联合标定统一标定框架里如果再多想一步可以考虑把视觉之外的传感器也纳入进来。现在很多项目里不仅有相机还有激光雷达和惯性测量单元IMU。激光雷达提供三维点云相机提供纹理IMU提供运动状态它们之间的坐标转换关系同样需要标定。视觉传感器和激光雷达的联合标定通常利用标定板在点云中呈现的特殊平面特征完成特征关联视觉和IMU的联合标定则需要借助运动激励采集数据让优化算法同时估计外参和时间延迟。这些联合标定的方法本质上还是视觉标定框架的扩展保持数据格式和误差指标的统一后期维护压力会小很多。我自己在实际项目中已经验证过视觉加激光雷达融合的方案现在回想起来如果当初没有先把多目视觉本身的标定统一到一套框架里直接把激光雷达加进来排查误差来源时会非常痛苦。所以我的建议是先把基础的相机标定做扎实把统一框架的接口预留好后续接其他传感器就是顺理成章的事。在实际操作中我最深的体会是任何标定算法都无法挽救了质量低劣的原始数据。与其盲目收集大量不合格的标定图像去指望算法鲁棒不如在采集端多花一点时间保证每张图像都清晰、无模糊、标定板姿态丰富合理。这一条听上去很简单但大部分人标定失败的原因都藏在原始数据的质量里。做多目系统想稳定标定多从现场采集细节下手把硬件状态和图像质量管好再从算法角度优化流程这才是最稳妥的路线。