第4章:标定技术精讲
相机内参标定、手眼标定、多传感器联合标定——这三个词,几乎是三维扫描工程师的必修课。我刚开始接触这行时,觉得标定就是个“走流程”,随便拍几张棋盘格就完事了。结果呢?扫描出来的点云全是扭曲的,模型拼接对不上,折腾了两天才发现是内参没标好。嗯,从那以后,我再也不敢小看标定这一步了。
4.1 相机内参标定:张正友法
说白了,相机内参就是描述“镜头怎么把三维世界映射到二维图像上”的那组参数。包括焦距、主点坐标、畸变系数等等。张正友法是目前最主流的标定方法,因为它只需要一块棋盘格,拍几张不同角度的照片就能搞定。
核心原理:利用棋盘格上已知的角点坐标,建立从世界坐标系到像素坐标系的映射关系。通过多张照片的约束,解算出内参矩阵和畸变系数。
我个人习惯用OpenCV来做这件事。代码其实不复杂,但有几个坑要注意。
import cv2
import numpy as np
# 准备棋盘格角点坐标(假设棋盘格内角点数为9x6)
objp = np.zeros((6*9, 3), np.float32)
objp[:,:2] = np.mgrid[0:9, 0:6].T.reshape(-1, 2)
# 存储所有图像中的角点
objpoints = [] # 世界坐标系中的点
imgpoints = [] # 图像坐标系中的点
# 读取图像并提取角点
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, corners = cv2.findChessboardCorners(gray, (9, 6), None)
if ret:
objpoints.append(objp)
imgpoints.append(corners)
# 标定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
我的经验:拍棋盘格时,一定要让棋盘格占满画面不同区域。我见过有人只拍中间区域,结果标定出来的畸变系数完全不靠谱。另外,照片数量建议在15-20张之间,太少解不稳定,太多也没必要。
4.2 手眼标定:Eye-in-Hand vs Eye-to-Hand
手眼标定解决的是“相机和机械臂之间的相对位置关系”。你想想看,机械臂带着相机移动,相机看到的物体在机械臂坐标系下到底在哪?这就是手眼标定要回答的问题。
两种模式:
- Eye-in-Hand(眼在手上):相机固定在机械臂末端。相机跟着机械臂动,标定目标是求相机坐标系到机械臂末端坐标系的变换矩阵。
- Eye-to-Hand(眼在手外):相机固定在工作台上,机械臂在相机视野内运动。标定目标是求相机坐标系到机械臂基座坐标系的变换矩阵。
我在项目中遇到过Eye-in-Hand的情况比较多。比如用机械臂夹持扫描仪去扫描大型工件,相机跟着机械臂走,每次移动后都要知道相机的新位置。标定公式其实就一个:AX = XB。A是机械臂末端的位姿变化,B是相机看到的标定板位姿变化,X就是我们要找的手眼矩阵。
避坑指南:我曾经在Eye-in-Hand标定时,机械臂运动范围太小,导致解算出的X矩阵误差很大。建议让机械臂做多组大角度旋转和平移运动,覆盖工作空间的不同区域。另外,标定板一定要固定好,别让它晃动。
4.3 多传感器联合标定
现在的三维扫描系统,往往不止一个相机。可能是双目立体视觉,也可能是结构光+相机,甚至加上激光雷达。多传感器联合标定,就是把这些传感器的坐标系统一到一个公共坐标系下。
举个例子:双目相机标定,除了每个相机的内参,还要标定两个相机之间的外参(旋转矩阵R和平移向量T)。我常用的方法是拍一组棋盘格图像,左右相机同时采集,然后通过立体标定函数求解。
# 双目立体标定
ret, M1, d1, M2, d2, R, T, E, F = cv2.stereoCalibrate(
objpoints, imgpoints_left, imgpoints_right,
mtx_left, dist_left, mtx_right, dist_right,
gray.shape[::-1]
)
如果是结构光系统,还要标定投影仪和相机之间的关系。投影仪可以看作一个“逆相机”,同样可以用棋盘格法来标定。嗯,这里要注意:投影仪的标定需要投影棋盘格图案到平面上,然后用相机拍摄,通过相位解算得到投影仪像素对应的三维坐标。
多传感器标定的关键:所有传感器必须同时观测同一个标定物。时间同步和空间同步缺一不可。我见过有人用不同时间采集的数据去做联合标定,结果误差大得离谱。
4.4 标定流程与知识体系
下面这张图是我自己总结的标定技术知识体系,你可以对照着梳理思路。
4.5 标定精度验证
标定完了,怎么知道标得好不好?我一般用两个方法:
- 重投影误差:把标定板上的角点通过标定结果投影回图像,计算投影点和实际检测点之间的像素误差。一般小于0.5像素就算不错了。
- 实际测量验证:扫描一个已知尺寸的标准件,看看测量结果和真实值差多少。我习惯用陶瓷球或者量块来验证,误差在0.1mm以内才算合格。
小技巧:标定完成后,把内参和畸变系数保存成YAML文件,方便后续调用。我每次标定都会在文件名里加上日期和相机型号,避免搞混。
好了,标定这部分就讲到这里。记住一句话:标定是三维扫描的基石,基础不牢,地动山摇。下一章我们会聊点更实战的内容——点云采集与预处理。
公众号:蓝海资料掘金营,微信deep3321