ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Halcon相机标定全流程:内参外参、标定板与RMSE避坑

Halcon相机标定全流程:内参外参、标定板与RMSE避坑

简介:这份中文标定章节手册面向计算机视觉工程师、Halcon使用者及机器视觉学习者,聚焦英文版第六章Calibration的直译与无删减整理,用于厘清相机内外参标定、畸变补偿与手眼/多相机设置中的概念和流程。压缩包仅含1个PDF文件,约813KB,便于检索与离线查阅。已有362人学习,具备一定参考热度。内容围绕标定目标、校准板与标记提取、标定数据模型构建、calibrate_cameras执行及RMSE评估展开,并说明区域扫描相机的内部参数、投影与反投影、校正和自标定等模块,同时覆盖单目、双目、多视图与手眼标定场景。读者可理解Halcon标定算子间的调用关系、参数含义与结果检查思路,也能对照校准板选择、图像采集注意事项和3D相机模型限制,为视觉检测项目的精度提升与排错提供中文参考。

1. 相机标定到底在干什么:一台相机的眼睛为什么要先"上课"

家里那台电子秤如果每次都多称 0.3 公斤,聪明人的做法不是每次称完手动减 0.3,而是先弄清楚它偏多少、往哪个方向偏、偏得是不是均匀,把这笔账算清楚,之后所有称重才有意义。相机标定就是给相机算这笔账:用一块尺寸完全已知的板子当"标准答案",让相机去拍,再反推它把三维世界投影成像素时到底用了什么规则、偏在哪里。Halcon 参考手册英文直译中文版第六章 Calibration 讲的就是这套东西,它是计算机视觉里所有几何测量的地基——相机标定没做对,后面视觉检测算法算出来的尺寸、角度、位置,都只是一串好看的错数字。

2. 为什么标定必须先有一块"已知答案"的板子

标定本质上是解一道反问题。正问题是:已知相机模型的全部参数,把一个三维点投影到图像上,算出它落在第几行第几列。反问题才是标定要做的事——已知一堆三维点和它们在图像里的像素坐标,反推出那套参数。既然是反推,那"已知"的那一半就必须真的已知,而且必须足够精确,否则求出来的参数只是在拟合一个错误的答案。

校准对象(Calibration Object)就扮演这个"已知"的角色。它是一块表面覆盖着多个校准标记的板子,每个标记在板子自身坐标系里的三维坐标由厂家随板提供,写在描述文件里。标定时,算法在图像中找到这些标记的像素位置,与描述文件里的三维坐标一一配对,每一对点都能列出方程,点越多、分布越广,方程越充分,参数就解得越稳。这也是为什么一块板子能决定整场标定的上限。

2.1 两种标准校准板:六边形排列和矩形排列差在哪

手册里明确提到,经销商可提供两种不同排列的标准校准板,它们的定位方式、可见性要求和最少拍摄张数都不一样,混用会直接报错。

第一种是六边形排列标记的校准板,对应生成算子是 create_caltab。它的定位靠一种特殊的取景器图案(finder pattern):若干六边形标记组成一组,其中一部分标记上带点状孔。这种设计的好处是宽容度高——图像里只要有一个取景器图案可见,就能定位板子,板子不必完整出现在画面里。如果同时能看到两个取景器图案,算法还能判断板子是不是被镜像拍摄了,一旦发现镜像,HDevelop 会返回一个明确的错误而不是悄悄算出一堆废参数。它的坐标系原点位于第一个取景器图案中心标记的中心,z 轴垂直于板面,x 轴向右,y 轴向下。

第二种是矩形排列标记的校准板,对应 gen_caltab。它的取景器图案由外围框架和三角形角标记构成,因此整块板子必须在图像里完完整整地可见,缺一个角就没法定位。它的坐标系原点位于板面正中间,坐标轴方向与上面一致。这两类板子的差别不只是外观:手册特别提示,使用较早的 camera_calibration 算子时,六边形排列的板子并不适用,要走 calibrate_cameras 这条链路。

拍摄张数的门槛也不同。六边形板至少需要 6 张图像,其中至少 4 张是倾斜拍摄的;矩形板至少需要 15 张。这个差距来自约束来源的不同——六边形板允许只拍局部,单张图能提供的定位信息相对独立;矩形板依赖整块框架完成定位,单张图的可用约束更依赖"整板完整可见"这个前提,所以需要更多张来凑够约束。数字是手册给死的下限,实际拍摄通常要多拍几张留余量。

2.2 一组合格图像要满足什么:从 30 到 45 度,从 20 像素到 100 灰度

板子买对了只是开始,图像拍砸了照样白搭。手册把要求分成三类,每一类背后都有一个明确的原因。

相机设置上,三样东西在采集过程中不能变。光圈不能变,因为标定算的是"相机 + 镜头 + 采集卡"这个固定组合的投影特性,光圈一动,进光锥角变了,投影关系就变了——校正完成之后再调光圈,必须重新标定,没有后悔药。相机位置不能变,因为外参描述的就是这套设备相对世界坐标系的站位,位置一动,之前算的外参全部作废。对焦不能变,也就是焦距锁定,图像必须清晰对焦,物体之间的过渡要清楚可辨,虚焦会让标记的中心提取产生系统性偏移。

板子的摆放上,覆盖和倾斜是两个关键词。一组图像里,视场的每一个部分至少要被板子覆盖一次,板子铺满整幅图像也可以。更关键的是倾斜:图像集里必须包含板子以大约 30 到 45 度向不同方向倾斜的照片。原因在手册最后一节说得很直白——如果所有图像里板子彼此平行,特别是全部位于同一平面,那么六个外部参数加上焦距就无法同时唯一确定,焦距和板子到相机的距离会互相耦合,算出一组"看起来能拟合、实际没有物理意义"的解。如果景深有限实在做不到推荐角度,那就尽量往陡了倾斜,别躺平。

图像属性上有几条硬红线。每个标记在校准图像中的直径至少要 20 像素,手册用了"至关重要"这个词,因为标记太小,中心提取的亚像素精度撑不住。板子明暗区域之间的对比度至少要 100 灰度值(按字节图像算)。为了避免过曝,亮部灰度值不要超过 240,尤其是标记附近不能曝。为了保证照明均匀,亮部灰度值的波动范围不应超过 45,反光和阴影都要避开。这几条不是苛刻,它们共同保证一件事:标记的像素坐标提得准。而标定的全部信息,就来自这些坐标。

提示:板子不能反着拍。玻璃材质的校准板如果从背面成像,标记是镜像的,这种图像进不了优化,只会污染结果。

2.3 为什么自己打印的板子撑不起高精度

很多人第一反应是:描述文件不就是一个文本吗,我拿打印机打一张贴到硬板上不就行了。手册对此的态度很明确——自打印的校准对象通常不够精确,不能用于高精度应用。

原因不难想。打印机的定位精度、墨滴扩散会让标记的实际尺寸和名义尺寸差出几十微米;纸张受潮会拱起,平面度一破,标记的 z 坐标就全错了;贴在什么基材上、贴得平不平,又是一层误差。这些误差不会显示在结果里,它们会安安静静地渗进重投影残差,让你以为标定做完了,其实只是把板子的变形学进了相机参数。

手册也留了口子:可以使用任意物体做标定,唯一的要求是这个物体具有能在图像中鲁棒检测到的特征点,并且这些点的三维世界坐标是高精度的。反过来读这句话就很清楚——能不能用,取决于"三维坐标有多准",而不取决于"是不是官方板"。对普通的面扫单目设置来说,买一块带描述文件的标准板,是省掉一大串扯皮的最短路径。

3. 内部参数与外部参数:一份相机体检报告的两半

相机参数被切成两半,这个划分不是人为的分类癖,而是因为它们回答两个完全不同的问题。内部参数回答"这台相机自己是什么样"——传感器像元多大、镜头焦距多少、主点偏在哪、畸变有多严重。外部参数回答"拍这张图的时候,它站在哪儿、朝向哪边"。前者只要设备不换、光圈不动,就是一套固定值;后者每换一个拍摄位置就换一套。搞混这两者,后面所有的调试都会变成玄学。

3.1 内部参数:焦距、比例因子与主点分别在描述什么

面扫相机按类型不同有 9 到 16 个内部参数,手册里带星号的那些是固定的,算法不会去估计它们。这个星号不是随便标的,每一个都对应一处"数学上解不出来"的耦合。

Focus(焦距)只对在镜头物方一侧做透视投影的镜头有意义,初始值取所用镜头的标称焦距,比如 0.008 米。手册还特意提了一句术语问题:焦距这个词严格来说只在物距无穷远时才准确,其他情况其实是像距,但为了简单起见统一叫焦距。这种坦白挺难得,也提醒你别拿初中的物理公式硬套。

Magnification(放大倍率)是远心镜头的对应物,等于图像尺寸除以物体尺寸,初始值取标称值,比如 0.2。远心镜头在物方做的是平行投影,没有"焦距"这个概念可用,所以换成了放大倍率。

Sx、Sy(比例因子)是传感器上两个相邻像元之间的水平和垂直距离,本质上描述的是像元尺寸。大多数情况下图像信号是同步采样的,Sy 由传感器尺寸直接决定,不需要通过标定去估计,所以它带星号。这里有个坑:射影相机用针孔模型描述时,焦距、Sx、Sy 三者无法同时确定,算法选择固定 Sy;远心镜头同理,放大倍率、Sx、Sy 也无法同时确定,还是固定 Sy。对于像侧远心的倾斜镜头,焦距、Sx、Sy 加上倾斜参数 Tilt 和 Rot 也不能同时定,于是除了 Sy 之外,Sx 也一并固定。

注意:如果图像做过次采样,Sx、Sy 的数值会变大,而 Cx、Cy、ImageWidth、ImageHeight 会变小。改之前先确认采样方式,别拿原始分辨率的值硬套。

Cx、Cy(主点)是图像主点,也就是径向畸变的中心,分别对应列坐标和行坐标,初始值用图像宽度和高度的一半。ImageWidth、ImageHeight是采样后图像的宽高。这两个值看起来只是"记录一下",实际上它们参与了从米制坐标到像素坐标的最后一步换算,填错了整幅图都会系统性偏移。

线扫相机的内部参数是 12 或 16 个,结构类似但有两处不同:Sx 和 Sy 都带星号(线扫里 Sx 与焦距或放大倍率的耦合更紧,Sy 在整个标定过程中只以 pv = -Sy·Cy 的形式出现,所以也被固定),并且多出 Vx、Vy、Vz 三个运动矢量分量。

3.2 畸变系数:一个 Kappa 和五个系数的分工

畸变模型有两种,参数数量差别很大。

分割模型(division model)只用一个参数 Kappa 来模拟径向透镜畸变,单位是 m⁻²,初始值取 0.0。它的参数表长这样:['area_scan_division', Focus, Kappa, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight]。

多项式模型(polynomial model)用五个参数:K1、K2、K3 描述径向畸变,P1、P2 描述离心畸变,五个系数的初始值都取 0.0。它的参数表是['area_scan_polynomial', Focus, K1, K2, K3, P1, P2, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight]。

一个参数和五个参数,直观感受是后者更强,但真实取舍没那么简单。分割模型的方程可以解析地求逆,从畸变坐标反算无畸变坐标是一步到位;多项式模型没有解析逆,必须用数值迭代去反解。投影方向(世界到图像)两者都快,反投影方向(图像到世界)差距就出来了。这一点会直接影响你后面做测量时的耗时,选模型时要一起考虑。

3.3 外部参数与运动矢量:相机站在哪,线扫还要多一组数

外部参数一共 6 个,描述世界坐标系相对相机坐标系的位置和姿态。相机坐标系的 x 轴和 y 轴分别平行于图像的列轴和行轴,z 轴垂直于图像平面。六个量分别是:TransX、TransY、TransZ 沿三个轴的平移,RotX、RotY、RotZ 绕三个轴的旋转。pose 元组里还多一个元素,编码了姿态的表示类型,也就是 OrderOfTransform、OrderOfRotation、ViewOfTransform 三个选项的组合,具体含义要查 create_pose 的说明。

使用标准校准板时,世界坐标系就由板子的坐标系定义,所以外参的物理含义是"板子相对相机在哪"。用 find_calib_object 可以一次性拿到所有参数的初始值;如果用的是矩形排列的板子,find_caltab 加 find_marks_and_pose 这对老组合效果等价。

线扫相机要多一组数:运动矢量 V = (Vx, Vy, Vz)ᵀ,单位是米/行,在相机坐标系中给出。手册对运动做了三条假设——相机沿直线匀速移动、方向恒定、所有图像的运动相等。这个矢量描述的是相机在动、物体不动;换个参考系,等价于相机不动、物体沿 -V 方向移动。线扫的相机坐标系定义很讲究:原点在投影中心(针孔)或畸变中心(远心),z 轴沿光轴,y 轴垂直于传感器线且方向选得让运动矢量有正分量,x 轴与 y、z 构成右手系。因为每条图像线都是从不同位置成像的,每条线理论上都有自己的位姿,为了简化,从世界坐标到相机坐标的所有转换都只基于第一条图像线的位姿。

这里有个必须记住的限制:远心线扫相机里,Vz 对三维点的图像位置没有影响,所以它无法被确定,标定过程中不会被优化,会保留初始值。手册建议把 Vz 的初值直接设成 0。另外,线扫的 Vx、Vy、Vz 初值质量对整个标定成败至关重要,初值不够准,优化可能直接跑飞。

4. 从建模型到出结果:标定链路里每一步在防什么错

Halcon 的标定不是"调一个函数就完事",而是先把所有信息塞进一个校准数据模型,再让优化器一次性吃下去。这个设计看起来啰嗦,实际是在防一类很常见的错误:数据来源分散、参数被反复覆盖、出错之后不知道是哪张图哪个参数的问题。把模型当容器,每一步写进去的东西都可查、可改、可排除,调试才有抓手。

4.1 五步搭起标定数据模型:每一步在防哪种错

手册给出的步骤是五步,顺序不能乱。

第一步,create_calib_data 创建校准数据模型,指定安装的相机数量和使用的校准对象数量。这两个数字决定了模型内部预分配多少个槽位,后面所有写入都按索引寻址。

第二步,set_calib_data_cam_param 指定相机类型和初始内部参数。这一步是很多人翻车的地方——相机类型字符串写错,整个参数数组的含义就全变了。比如把area_scan_division写成area_scan_polynomial,Kappa 那个位置就会被当成 K1 读,后面算出来的东西毫无意义。

第三步,set_calib_data_calib_object 指定所有校准对象的描述。描述文件来自板子供应方,写明了每个标记的三维坐标,是"已知答案"的载体。

第四步,find_calib_object 或 set_calib_data_observ_points 收集观测数据,也就是提取出的标记图像坐标,以及校准对象相对观测相机的粗位姿。粗位姿只是起点,不要求准,但要求"在正确的吸引域里",偏太远优化会收敛到错误解。

第五步,配置校准过程,比如用 set_calib_data 把某些相机参数从优化中排除。手册给的例子很典型:如果相机 0 的图像传感器单元尺寸已经被精确知道,只需要标定其余参数,就调用set_calib_data (CalibDataID, 'camera', 0, 'excluded_settings', ['sx', 'sy'])。排除掉这些参数,等于把它们钉死在初值上,减少自由度,让优化更稳。

// HDevelop 风格的标定主流程示意:算子名与手册一致,参数顺序以实际参考为准 // 1) 建模型:1 台相机,1 块校准板 create_calib_data ('calibration_object', 1, 1, CalibDataID) // 2) 写相机类型与初始内参:投影面扫 + 分割畸变模型 // 依次为 Focus, Kappa, Sx, Sy, Cx, Cy, ImageWidth, ImageHeight set_calib_data_cam_param (CalibDataID, 0, 'area_scan_division', \ [0.008, 0.0, 3.45e-6, 3.45e-6, 640.0, 512.0, 1280, 1024]) // 3) 写校准板描述:文件名随板子提供,内含每个标记的三维坐标 set_calib_data_calib_object (CalibDataID, 0, 'caltab_30mm.descr') // 4) 逐张图找标记,写入观测坐标与粗位姿 for Index := 1 to 8 by 1 read_image (Image, 'calib_' + Index$'02d') find_calib_object (Image, CalibDataID, 0, 0, Index, [], []) endfor // 5) 排除已知参数,然后执行真正的标定 set_calib_data (CalibDataID, 'camera', 0, 'excluded_settings', ['sx','sy']) calibrate_cameras (CalibDataID, Error) // 6) 取回结果:内参、外参、标准差都在这个模型里 get_calib_data (CalibDataID, 'camera', 0, 'params', CameraParam)

这段代码的关键不在语法,而在两个"写死"的地方。第二步的初始内参不是随便填的:Focus 填镜头标称焦距,Kappa 填 0,Sx、Sy 填传感器像元尺寸,Cx、Cy 填半宽半高——这些值只是优化的起点,但因为模型里有耦合项被固定,起点偏差会被吸收掉一部分,偏差太大则可能收敛到局部极小。第五步的排除列表同样重要,它等于告诉优化器"这两个数我确定,你别动",把有限的观测信息集中到真正未知的参数上。

4.2 RMSE 与标准差:怎么读"这次标定靠不靠谱"

calibrate_cameras 跑完之后,模型里不只有参数,还有一组用来判断成败的数字:后投影的均方根误差(RMSE)、各内参的标准差和协方差。

RMSE 的含义手册说得很清楚:它是优化后的重投影误差,把校准点按算出来的模型投回图像,与它们实际被提取到的图像坐标之间的平均距离,单位是像素。单相机标定中,0.1 像素左右的误差就说明优化与观测数据拟合得很好——这个量级基本上就是标记坐标提取本身的典型检测误差,再往下压意义不大。如果误差明显偏离 0.1 像素,比如到了 0.5 甚至更高,那这次标定大概率有问题,常见原因包括图像质量差、校准图像数量不足、校准板本身不准确。

# 用重投影残差快速判断一次标定能不能用 import math # residuals:每张图上每个标记的重投影残差,单位像素 residuals = [0.08, 0.11, 0.09, 0.13, 0.07, 0.10, 0.12, 0.09] rmse = math.sqrt(sum(r * r for r in residuals) / len(residuals)) print(round(rmse, 3)) # 单目、图像质量正常时,0.1 上下说明拟合良好 # 残差分布比均值更能说明问题:某一张图残差明显偏大, # 通常是那张图的板子倾斜不够、曝光不匀,或者标记提取偏了 print(max(residuals), min(residuals))

标准差和协方差是另一层信息。RMSE 告诉你"整体拟合得好不好",标准差告诉你"每个参数各自有多不确定"。一组参数可能整体 RMSE 很漂亮,但某个系数的标准差很大,说明这个参数其实没被数据约束住,只是优化器勉强给了一个值。这种参数拿去用,换个场景就会表现得莫名其妙。多相机设置的检查方式另有讲究,要参考多视图章节的对应说明。

4.3 分割模型与多项式模型:快、稳、准之间的取舍

两种畸变模型的差别可以列成一张表看。

对比项分割模型多项式模型
畸变参数Kappa 一个K1、K2、K3、P1、P2 五个
建模能力只建模径向畸变径向 + 离心畸变,用高阶项
逆畸变计算解析可逆,快无解析逆,需数值迭代,慢
少图或覆盖不足时结果通常更稳定容易过拟合,结果飘
板未覆盖区域相对可控可能模拟失真
适用建议默认首选精度不够时再换

手册的建议很直接:通常应该用分割模型做标定。如果标定精度不够高,再改用多项式模型,但要注意配套条件——用于多项式模型的标定序列必须提供更好的区域覆盖,尤其是后续要测量的那块区域。板子没覆盖到的地方,包括图像边界和视场内的空白区,畸变可能被模拟得不准确。换句话说,多项式模型不是"更强的模型",而是"要求更高的模型",给它喂不够的数据,它会用五个自由度去拟合噪声。

5. 五个最容易踩的易混概念:标定里的说法与它真正的意思

标定这套东西的名词密度很高,Calibration、Rectification、Projection、Pose、Parameters 挤在一章里,初学者很容易把相邻的两个概念当成一件事。下面这五组是最常混的,每一组都值得单独掰开。

5.1 标定不等于校正:求参数和掰图像是两件事

易混点:把 Calibration(标定)和 Rectification(校正)当成同一个动作,以为跑完标定图像就自动变正了。

为什么混:中文里"校准""校正""标定"三个词日常几乎通用,手册里这两个词又挨着出现,都在 Calibration 这个大分类下面,很容易滑过去。

怎么区分:标定是求解,输出是一组参数——内参、外参、畸变系数。校正是应用,输入是原图加这组参数,输出是一张去畸变、拉正了的图。标定是"量体温",校正是"吃药"。两者还有一层依赖关系:校正用的参数必须和拍摄时的物理状态一致,所以手册才强调光圈在校准后如果改变,相机必须重新标定。你拿一组旧参数去校正新光圈的图像,图会变正,但正得不对。

5.2 分辨率不等于精度:像素多不代表测得准

易混点:认为相机像素越高、图像越大,标定精度就越高。

为什么混:直觉上信息越多结果越准,而且高分辨率图像看起来确实"更清楚"。

怎么区分:精度取决于两件事——标记中心能被提取到多准,以及模型和观测拟合得有多好。手册给的参考值是 RMSE 约 0.1 像素,这个数字是像素级的相对量,不是绝对尺寸。同样 0.1 像素的残差,在像元 3.45 微米的相机上对应约 0.35 微米,在像元 6.9 微米的相机上就翻倍。真正卡住精度的是几个工程指标:标记直径至少 20 像素、对比度至少 100 灰度、亮部不超过 240、亮部灰度波动不超过 45。这些没做好,堆分辨率只是把噪声也一起放大了。

5.3 远心镜头和普通镜头:能不能定出距离,答案不一样

易混点:拿针孔相机的那套预期去看远心镜头,以为标定完就能知道板子离相机多远。

为什么混:两种镜头都能拍出清晰的图像,标定流程也长得几乎一样,参数表里差的那几项很容易被忽略。

怎么区分:远心镜头在物方做的是平行投影,标定板和相机之间的距离无法被确定下来,所以手册明确说,板子位姿的 z 分量在测量结果中被设置为 1 米——这只是一个约定值,不是测量值。远心线扫还多一条:Vz 无法确定,会保留初始值,建议初值设 0。针孔相机则有另一头的麻烦:如果所有图像里的板子彼此平行,尤其全部共面,六个外参加焦距无法一起定出来,焦距和物距会互相抵消。所以"多角度倾斜拍摄"对针孔是硬要求,对远心同样重要,但理由不完全一样。

5.4 单目标定和多目、手眼标定:不能拿一套思路套到底

易混点:做完单目标定,觉得双目、多视图、手眼标定就是"多来几台相机"。

为什么混:名字上都带 Calibration,前置步骤(建模型、找标记、收集观测)也确实一样。

怎么区分:单目标定要解的是"一台相机自己的内参 + 它相对板子的外参"。双目和多视图多了一层约束——相机之间的相对位姿必须由同一批观测同时解出来,共用一块板子在不同视角下的观测,误差会互相牵制。手眼标定则把机器人末端或基座的坐标系拉了进来,要解的是相机坐标系与机器人坐标系之间的固定变换,通常需要在多个机器人位姿下拍摄。检查标定是否成功的方法也不完全一样,多视图设置要看对应章节的专门说明。用单目的 RMSE 经验值去判断一个手眼标定好不好,容易得出错误结论。

5.5 模型选错不算大错,覆盖不够才是真错

易混点:把"用多项式模型"当成精度更高的默认选项,觉得五个参数总比一个强。

为什么混:参数多听起来更精细,而且手册确实写了多项式模型能更准确地模拟畸变。

怎么区分:分割模型的优点是反畸变快、在图像少或视场覆盖不足时结果更稳;多项式模型的优点是能建模径向高阶项和离心畸变,更准,但代价是它会在板子没覆盖的地方乱猜。手册的建议顺序是先用分割模型,精度不够再换多项式,并且换过去之后必须保证测量区域被标定板充分覆盖。真正的红线不是模型选择,而是覆盖范围——视场每个部分至少被板子覆盖一次,倾斜角度 30 到 45 度、多方向分布,标记直径不低于 20 像素。这些条件满足了,分割模型也能给出能用的结果;这些条件不满足,换什么模型都是在给噪声建模。

6. 什么时候值得标、什么时候先别急:一条务实的判断线

相机标定不是视觉项目的第一道工序,而是第一道"需要几何精度"的工序。这个区别决定了你该不该现在动手。

该标的情况很明确:要从图像里换算真实尺寸、角度、位置;要做亚像素级的定位或测量;要用标定结果做去畸变再测量;要做双目、多视、手眼这类需要坐标系转换的任务。这些场景里,标定是前提,跳过它后面的数字都没有物理意义。

先别急的情况同样明确。如果任务只是判断"有没有""是什么"——比如产品有无检测、简单分类、颜色判别,几何精度根本不进入判据,那么先把采集和光照打磨好,比急着买一块标定板更划算。如果你手上的图像还没达到门槛——标记在画面里只有十来个像素、明暗对比不到 100 灰度、亮部过曝一片白、光照不均导致同一块板子半边亮半边暗——那么现在标定只会得到一组看着能跑、实则拟合了成像缺陷的参数。手册把 20 像素、100 灰度、240 上限、45 灰度波动这几条摆出来,就是在告诉你:这些是入场券,不是加分项。

还有一种情况值得单独说:视场没覆盖全就上多项式模型。多项式模型有五个自由度,板子只覆盖了画面中间一小块,边缘区域的畸变它照样会给你算出一个值,只是这个值没有数据支撑。测量点正好落在边缘时,误差会以你意想不到的方式出现。

你的处境建议动作
只做有无/分类检测先不标定,优先稳住采集与光照
要做尺寸、角度、位置测量必须标定,且先确认标记直径与对比度达标
图像质量还没过门槛先修采集,别用标定去补成像缺陷
视场边缘也要测保证板子覆盖每个区域,慎用多项式模型
远心镜头接受"物距不可知",别指望外参 z 给出真实距离
线扫先把 Vx、Vy、Vz 初值弄准,Vz 对远心固定为 0

刚接触这块的时候,我也犯过"先把函数跑通再说"的毛病:板子往桌上一放,连拍八张,张张角度差不多,跑出来 RMSE 也不难看,就以为成了。后来拿这套参数去量一个已知尺寸的工件,误差稳定地偏出一个固定值,怎么调算法都压不下去。回头翻手册才发现,所有板子几乎共面的时候,焦距和物距本来就分不开,那组参数只是把误差摊平成了一个好看的残差。从那以后我每次标定前都强制走一遍检查:板子倾斜角度够不够、每个区域覆盖到没有、亮部有没有曝、标记在图上够不够 20 像素,全过了再调 calibrate_cameras。希望这些能帮你少走一遍我走过的弯路,完整的手册章节和参数表就在那份资料里,需要的时候翻出来对着看。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进