ARTICLE DETAIL

资讯详情

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

单目线激光光刀平面标定:从张正友内参到三维重建的完整实战

单目线激光光刀平面标定:从张正友内参到三维重建的完整实战 做线激光扫描的工程师应该都遇到过这种尴尬内参用张正友标定法搞定了棋盘格角点检测误差也压在0.1像素以内满心欢喜打开激光器扫了个零件结果重建出来的点云要么整体倾斜要么尺寸比例完全不对。问题往往不在内参而在光刀平面的标定上。所谓光刀平面就是线激光器发出的光扇面它在相机坐标系里是一个有确定方程的空间平面。这个方程不标准像素坐标到三维坐标的桥梁就是歪的。这篇文章我就围绕单目线激光系统中的光刀平面标定把张正友标定法如何服务于整个流程、光平面怎么采样、怎么拟合、怎么验证完整拆一遍顺便把我自己踩过的坑都交代清楚。1. 单目线激光怎么算三维先把光刀平面的角色搞清楚1.1 三角测量与光平面方程单目加线激光这套方案本质上是结构光三维测量里的一个特例。线激光器投出来的不是一条真正意义上的“线”而是一个扇面光束打在物体表面上时形成一条亮条纹这个扇面就是光刀平面。相机从另一个角度拍摄这条条纹物体表面高度不同条纹在图像里的位置就不同这就是最基本的三角测量关系。要把这个关系变成一个可计算的数学模型需要三个前提第一个前提是相机成像模型已知也就是内参矩阵 K 和畸变系数准确这一部分由张正友标定法解决。第二个前提是相机坐标系下光刀平面的方程已知也就是我们常说的光平面标定。第三个前提是激光器和相机的相对位置在扫描过程中保持不变这个属于机械结构上的约束。光刀平面写成数学表达式就是Ax By Cz D 0这里 x、y、z 是光平面上任意一点在相机坐标系下的三维坐标。A、B、C 构成平面的法向量D 是原点到平面的归一化距离。标定的目标就是把这四个系数求准。三维重建的时候对于图像中任意一个条纹像素点先用内参对它做反投影得到一条从相机光心出发的射线这条射线与光刀平面求交点交点的坐标就是物体表面那个点的三维坐标。整个过程里光平面方程是除了相机模型之外的第二个几何约束少了它单目相机根本不可能恢复深度这也是单目线激光方案和单目普通拍照的本质区别。1.2 为什么单目就够了双目不一定是更优解很多人会问既然要恢复三维为什么不直接用双目相机一左一右两个视角通过立体匹配求深度听起来更“完整”。这里要分场景。双目立体视觉的核心问题是同名点匹配对于没有纹理的金属件、白色塑料件匹配很容易飘而且双目标定涉及两个相机之间的外参标定系统复杂度和标定成本都在上升。线激光方案里激光条纹本身就是一种受控的人工特征不需要在图像之间找同名点只需要在单幅图像里找到条纹中心这个中心点的空间位置由光平面唯一确定。也就是说话线激光方案相当于用“光平面”这个先验约束替代了双目里的“极线约束”。在精度上只要光平面标得足够准单目线激光在近距离扫描场景里完全能做到亚毫米甚至更高精度而且系统更容易小型化成本也更低。我目前手头的一个产线检测项目就用的是单目加线激光部署和维护都比双目方案省心不少。当然单目线激光也有它的短板比如对物体表面反光敏感扫描速度受限于激光器功率和相机帧率但这些都属于工程调优问题不改变系统框架的合理性。2. 张正友法先把相机内参和外参拿到手2.1 用一张棋盘格解决相机建模问题光刀平面的标定一定绕不开张正友标定法。虽然张正友法最初是来解决相机内参标定的但在光平面标定这个流程里它同时承担了另一个重要任务外参求解。内参是什么是相机从三维世界坐标映射到二维像素坐标的那套固定参数主要是焦距、主点和畸变系数。外参是什么是某一时刻相机坐标系和某个世界坐标系比如棋盘格坐标系之间的旋转和平移。张正友法核心思想非常巧妙一个平面棋盘格上所有角点的世界坐标是已知的且它们都在 z0 平面上。相机拍摄一张棋盘格照片后角点的像素坐标和世界坐标之间构成一个单应性矩阵 H。如果不考虑畸变有λ [u, v, 1]ᵀ K [r1, r2, t] [X, Y, 1]ᵀ这里 r1、r2 是旋转矩阵的前两列t 是平移向量。单应性矩阵 H K [r1, r2, t]。通过多张不同姿态的棋盘格照片每张照片提供一个 H多个约束方程联合起来就能把 K 求出来。内参一旦求出来每张棋盘格照片对应的外参 R、t 也就可以从 H 里恢复。张正友法最大的好处是标定物简单一张打印的棋盘格就能干活而且不需要知道相机和标定板之间的距离非常适合现场操作。2.2 单应性矩阵如何同时给出内外参内参标定在 OpenCV 里已经封装得很完整我不重复贴代码只说关键流程和注意事项。我习惯的流程是先用 findChessboardCorners 检测角点再用 cornerSubPix 做亚像素精化最后用 calibrateCamera 一次解出内参和畸变系数。如果标定板是 9x6 的棋盘格方格边长 20mm那就传入对应的世界坐标。这里有一个很关键的点calibrateCamera 返回的重投影误差要重点关注。我一般要求平均重投影误差在 0.1 像素以下才算合格。如果误差跑到 0.3 像素以上不要急着进行光平面标定先把内参标好再说。误差来源可能是标定板不够平整、图像对焦不实、或者角点检测时镜头畸变影响过大。至于外参求解我很少直接从单应性矩阵分解去手算 R 和 t因为在有畸变存在的情况下直接分解会引入额外误差。更稳的做法是用 OpenCV 的 solvePnP把棋盘格角点的世界坐标和对应的像素坐标传进去加上刚刚标定好的相机内参和畸变系数一次求解外参 R 和 t。solvePnP 会把畸变模型纳入优化求出来的外参会更符合真实成像过程。2.3 内参标定数据采集的实用建议内参标定看着简单但数据采集质量直接决定后续所有步骤的精度这里给出我自己的采集建议。标定板要平整。绝对不要用打印纸直接贴在软木板上近距离标定时纸面细微的起伏都会让角点位置偏移我推荐用陶瓷基板或玻璃镀铬的棋盘格表面平整度以毫米级以下误差为标准棋盘格姿态要有变化。不要所有照片都是正对着相机拍的要覆盖上下左右四个角落和中间区域旋转角度在 30 度到 45 度之间变化距离也要远近搭配这样内参标定才能约束住不同方向的畸变采集数量 15 到 20 张就够。张正友法在 5 张以上就能收敛但为了抗噪多拍一些没有坏处。我自己通常拍 18 张左右拍摄时不要开自动对焦不要开自动曝光锁死光圈和对焦环。聚焦点在标定板上而且要保证整块板子在景深范围内都清晰如果我用的是工业相机记得关掉自动增益和自动白平衡。自动白平衡会让颜色偏置虽然对角点检测影响不大但在后续处理激光条纹时会明显干扰灰度信息内参标定完成后结果可以存成一个配置文件包含相机矩阵 K 和畸变系数。只要镜头焦距和光圈不再调整这个内参就一直有效后续每次做光平面标定都可以复用。3. 光刀平面的完整标定流程3.1 采集标定数据的标准操作光平面标定的核心思路是通过标定板这个“已知几何参考”获得光平面上若干三维点的坐标然后用这些点拟合平面方程。具体的采集流程我用下来最顺手的是“同一位姿拍两张”把标定板固定在某个位置相机和激光器位置不动关闭激光器正常均匀光照下拍一张棋盘格图像用于求标定板外参打开激光器激光会投射到标定板表面并形成一条亮条纹拍第二张图像移动标定板到下一个位置改变距离和角度再次重复前面三步累计采集 10 到 15 个不同位姿确保条纹出现在标定板上不同区域覆盖整个光平面这里有个细节同一位置的两张图里标定板必须纹丝不动。哪怕移动了 0.5 毫米棋盘格图求出来的外参和条纹图上的条纹位置就不对应了三维点的坐标就会偏。我的习惯是用一个磁性底座或者重物压住标定板或者干脆固定在光学平台上。为什么需要“关激光拍一张”和“开激光拍一张”两张图因为激光照射到棋盘格上亮条纹会遮挡一部分棋盘格的黑色方块直接做角点检测会失败或者检测出错误的角点。关激光的图专门用于角点检测和外参求解开激光的图专门用于条纹提取两张图各司其职后续通过外参把它们关联到同一个空间坐标系里。3.2 激光条纹中心提取的几种手段从带条纹的图像里提取条纹中心线是整个光平面标定里对精度影响最大的一环。条纹中心提偏 1 个像素三维点的位置就可能偏零点几毫米。最常用也最容易上手的是灰度重心法也叫灰度质心法。对图像中每一列或每一行取条纹覆盖的像素区域计算灰度加权中心center Σ (G_i × i) / Σ G_i这里 G_i 是第 i 列的灰度值i 是像素坐标。灰度重心法的前提是条纹灰度呈近似高斯分布且没有过曝。一旦激光过曝高光区域灰度全部饱和到 255重心就会被拉偏所以拍摄时要保证条纹中心灰度峰值落在 180 到 220 左右不要顶到 255。如果条纹细、背景暗还可以用 Steger 算法基于 Hessian 矩阵求亚像素中心抗噪能力更强。但 Steger 计算量大参数也敏感对现场调试来说要先调好尺度因子。我做产线项目时优先用灰度重心法配合截断阈值和高斯滤波速度精度都够用。提取完条纹中心后会得到一组像素坐标点这些点就是激光条纹与标定板表面交线上的点。下一步要把它们从像素坐标转成三维坐标。3.3 从像素点到相机坐标系三维点这一步是整个标定流程里的理论核心我把推导过程完整写出来。第一步利用关激光那帧棋盘格图求得标定板外参 R 和 t。标定板的坐标系原点在棋盘格某个角点Z 轴垂直于板面所以标定板平面在标定板坐标系下就是 z0 的平面。第二步把标定板平面变换到相机坐标系。标定板坐标系下的点 P_plate变换到相机坐标系为P_cam R × P_plate t因为板平面上所有点满足 z0所以板平面在相机坐标系下由一个法向量和一个位移决定。法向量就是旋转矩阵的第三列 r3板平面上任意一点可以取平移向量 t平面方程可以写成r3ᵀ × P r3ᵀ × t这个式子就是相机坐标系下标定板平面的标准方程右边是一个常数。第三步把条纹图像上的像素点反投影成射线。对于像素坐标 (u, v)由针孔相机模型该点在相机坐标系下的方向向量为 d K⁻¹ [u, v, 1]ᵀ。这里 K⁻¹ 是内参矩阵的逆矩阵这一步需要输入无畸变坐标所以提取到的像素坐标要先用畸变系数做一次去畸变处理。第四步射线和平面的交点就是光平面上的三维点。射线方程为 P λ × d相机光心为射线起点代入平面方程λ × r3ᵀ × d r3ᵀ × t所以 λ (r3ᵀ × t) / (r3ᵀ × d)代回射线方程得到 P 的三维坐标。这个 P 点既在标定板平面上也在光刀平面上它就是光平面的一个采样点。对每一帧条纹图上的每一条纹中心点重复这个过程一次采集就能得到几十个甚至上百个三维点。换个标定板位姿再来一次三维点就会散布到光平面的不同区域。累计 10 多个位姿通常能攒下几百个点足够拟合平面。3.4 多点拟合光平面方程有了足够多的三维点光平面拟合就是一个很标准的最小二乘问题。平面方程写为Ax By Cz D 0把每个三维点代入得到一组线性方程。我们希望找到一个非零向量 (A, B, C, D)使所有点到平面的距离之和最小。实际操作中我习惯构造一个 N×4 的矩阵 M每一行是 (x_i, y_i, z_i, 1)然后对 MᵀM 做特征值分解最小特征值对应的特征向量就是平面系数。也可以用 SVD 对 M 直接分解取 V 矩阵最后一列。这个做法对平面拟合来说是最小二乘意义上的最优解而且实现简单几行代码就能搞定。拟合完成后把 A、B、C 归一化结果保存为光平面参数文件。之后三维重建时直接加载这个平面配合相机内参对每一帧条纹图像作射线-平面相交计算即可得到三维点云。4. 光刀平面标定的误差验证与精度反哺4.1 先用平面拟合残差检验拟合完平面不能直接完事起码要做一次自检。最简单的指标是拟合残差也就是每个三维点到拟合平面的距离。把所有点到平面的距离统计一下看均值和最大值。我的经验是在普通室内环境下用 200 个以上的采样点拟合光平面平均残差应该在 0.05 毫米以下最大值不超过 0.2 毫米。如果你算出来的平均残差到了 0.3 毫米那说明前面的某个环节出问题了先排查不要继续往下走。这里有三种常见情况。第一种是条纹中心提取抖得厉害一般表现为残差整体偏大且分布均匀排查方向是看条纹图是否过曝、是否模糊。第二种是个别点残差特别大很可能是某帧图像里标定板发生了微小移动或者条纹上有反光导致的异常点可以先剔除离群点再重新拟合。第三种是采样点分布不均比如所有点都集中在光平面的左下角这种情况下拟合出的平面在远端区域外推误差很大但残差可能很小所以要检查点的空间分布。4.2 用已知高度物体做端到端验证拟合残差只能说明“这些采样点本身和平面贴合得好”不能说明平面在真实场景里就是准的。端到端验证才是最有说服力的。我常用的方法是用标准量块。把量块放在扫描区域内激光投射到量块表面拍一张图按光平面模型重建出量块上表面的高度和量块的实际厚度做对比。比如放一个 10mm 的标准量块重建出来的高度在 10 ± 0.1mm 以内说明整个环节链路是通的。另一个更直观的方法是扫描一个已知平面比如一块精密大理石平台。把重建出来的点云用 RANSAC 拟合平面看平面度偏差。如果扫描一个平整表面重建出来的点云是扭曲的、鼓包的那十有八九是光平面参数不正确而内参的嫌疑相对小。还有一种我偶尔会做的验证方式转动标定板的角度在不同位姿下测量同一高度差。因为光平面标定结果应该与标定板位姿无关如果你发现某个位姿下测量的量块高度偏差明显大于其他位姿那多半是采样时这个位姿下三维点的计算有偏差。4.3 标定参数对重建结果的影响这里要理解误差是怎么传导的。光平面标定误差对重建结果的影响和相机内参误差的影响路径不同。内参误差主要通过反投影射线方向引入偏差。比如主点偏了 5 个像素那么同一像素点反投影的射线方向就会偏一个明显的角度这会直接影响交点位置。外参误差的来源比较复杂棋盘格角点检测误差、畸变模型误差、标定板不平整都会耦合到 R 和 t 里导致标定板平面方程本身就有偏差进而影响三维点坐标。光平面本身的误差则直接改变交点位置。如果光平面的法向量方向偏了斜入射时交点会沿着表面法线方向产生系统性偏移典型表现就是扫描一个平面平放在台上重建结果是一个倾斜面。如果 D 参数偏了也就是光平面离相机的距离错了重建结果会出现整体偏近或偏远的尺度误差。这也解释了为什么我不建议偷懒只用一个棋盘格位姿做光平面标定。一个位姿最多只能覆盖激光条纹那一小段区域拟合出来的平面在远离采样区域的地方基本靠猜。位姿越分散光平面在不同深度和角度都被约束到外推误差才可控。5. 标定实战中的问题排查与经验沉淀5.1 条纹过曝、断裂与反光线激光标定里最先遇到的问题是过曝。激光器功率太强或者相机曝光时间太长条纹中心一片死白灰度重心法提出来的中心会偏移因为饱和区域的灰度权重重心被拉向亮区中心偏后的位置。我自己解决过曝的办法是按这个顺序试先调低曝光时间再调低激光器功率最后考虑加衰减片。优先调曝光时间因为激光器功率调太低会导致条纹亮度不均匀反而影响提取稳定性。反光问题也很常见。尤其是金属表面或者表面光滑的标定板激光照上去会发生镜面反射图像里出现高光溢出或者条纹断裂。断裂的条纹会造成提取出的中心点不连续拟合平面时这些离散点会拉大残差。我遇到过最典型的情况是标定板表面覆了一层塑封膜激光打上去反光特别厉害换了一块哑光的陶瓷标定板之后问题立刻消失。5.2 内参和外参误差如何传导到光平面很多人以为内参标定完之后就一劳永逸实际上光平面标定的精度完全建立在相机模型正确性的基础上。如果内参里的主点坐标偏了哪怕 2 个像素反投影射线方向就会整体偏移光平面拟合出来也会带着同样的角度偏差最终重建点云整体倾斜。另一个容易被忽视的点是镜头畸变。工业镜头尤其是广角镜头边缘畸变可以达到几个像素。如果内参标定时畸变系数不准或者光平面标定的流程里没有对像素坐标做去畸变处理那么位于图像边缘的条纹点就会在反投影时产生明显的位置偏移拟合出的平面在边缘区域会翘起来。我都是在提取条纹中心之后先对像素坐标做 undistortPoints然后再进行射线-平面求交。外参误差的传导路径更直接。求解标定板外参时如果棋盘格角点检测误差大R 和 t 就会偏标定板平面方程就偏最终算出来的光平面采样点坐标全都会带上这个偏差。所以每次拍摄棋盘格图像时我会在代码里把检测到的角点画出来叠加到原图上用肉眼看一遍确保没有错检漏检。5.3 一个值得养成的校验习惯最后分享一个我自己坚持了很久的习惯每次采集完一组标定数据后先把条纹中心提取结果可视化出来把提取到的中心点叠加在原始条纹图上再把计算出的三维点投影回图像看看重投影误差。这样做能帮你第一时间发现两类问题。一是条纹中心提取是否偏了。如果中心点叠加图显示提取点不在条纹正中说明提取参数需要调整。二是标定板是否移动。如果同一帧图像里三维点重投影回图像后和原条纹对不上但棋盘格角点检测又是对的那十有八九是这帧图像拍摄时标定板动了。这套习惯帮我排掉过大量现场问题。有一次项目验收前扫描一直有零点几毫米的周期性波动排查了半天最后发现是压标定板的夹具在高低速移动时会共振。可视化重投影以后明显看到某几个位置的采样点偏了这才锁定了夹具问题。如果没有可视化的习惯这种现场问题查起来非常痛苦。光平面标定这件事说难不难说简单也不简单核心就是三个词内参准、采样散、拟合稳。内参用张正友法打底采样时把标定板摆满整个扫描区域拟合之前先看残差和可视化结果。做到这几点光平面标定的精度基本不会出大问题。
返回列表