2 分钟阅读
残差很小,标定却是错的
做标定的人都盯着残差看。跑完一条链,RMS 0.08 px,心里就踏实了。
这个踏实经常是假的。
两个不一样的东西
- 残差:模型对参与求解的那批数据的拟合误差;
- 偏差:你的结果与真值之差。
残差小只说明一件事:你的模型能解释你采的这批数据。 如果数据本身带着系统性问题,模型会连同这个问题一起拟合进去,然后给你一个漂亮的残差。
一个能自己复现的例子
在 demo-2axis-vision 上:
- 先正常跑一遍像素当量标定,记录:残差 RMS 0.081 px,偏差 0.018 mm,PASS。
- 把镜头畸变
k1从 −0.0214 改成 −0.08(相当于换了个便宜镜头却没重标畸变)。 - 只重跑 acquire 和 solve。
结果:
| 残差 RMS | 偏差 | |
|---|---|---|
| 正常 | 0.081 px | 0.018 mm |
| 畸变没标 | 0.213 px | 0.150 mm |
残差涨了 2.6 倍——看起来还行。偏差涨了 8.3 倍,直接超差 3 倍。
如果你只看残差,你会觉得「有点变差但还能用」。实际上这台机器已经不能干活了。
为什么会这样
畸变是一个随半径变化的系统性偏移。求解像素当量时, 最小二乘会找到一个折中的 mm/px,让所有点的残差都不太大—— 中心的点被拉大一点,边缘的点被拉小一点,平均下来残差还好看。
但这个折中值在任何一个具体位置上都不对。用到产线上, 中心区域的工件误差小,边缘区域的误差大,表现为「时好时坏」。
怎么揭穿它
用一批没参与求解的数据回算。 这就是标定链里 verify 步骤的全部意义。
具体做法:
- 采集 N 个位姿,拿 70% 求解,30% 留作验证;
- 用求出来的参数预测验证集的位置,和实际比;
- 这个误差才是你该信的数字。
在虚拟设备上还可以再进一步:因为知道真值,可以直接算偏差, 连验证集都不用留。真机上没这个条件,所以留验证集是必须的。
三条能直接用的规矩
- 永远不要用同一批数据既求解又验证。 这是标定报告里最常见的自欺欺人。
- 残差异常时先怀疑数据,不要先调模型。 加高阶畸变项能把残差压下去, 但那是在拟合噪声,偏差只会更大。
- 采集跨度比采集点数重要。 走 50 mm 采 9 个点,比走 5 mm 采 50 个点准得多。
噪声通过最小二乘平均掉的量和
跨度 × √点数成反比,跨度是一次项。