4. 相机成像模型与标定实战
在视觉力觉融合抓取工作站中,相机是感知环节的“第一道尺子”。如果这把尺子本身刻度不准,后续的点云配准、抓取位姿计算、力控补偿都会建立在错误的基础上。相机标定的本质,就是建立从三维世界坐标到二维像素坐标之间的数学映射,并求出映射中的全部未知参数。本节围绕针孔成像模型、内参、外参、畸变模型以及标定板使用与精度验证展开,目标是让读者能够独立完成一次可用的相机标定,并判断标定结果是否可信。
一、针孔成像模型:从世界点到像素点
相机成像可以抽象为四个坐标系的连续变换:世界坐标系、相机坐标系、图像物理坐标系和像素坐标系。一个空间点 P_w = (X_w, Y_w, Z_w) 先经外参变换到相机坐标系,再经内参投影到像素平面。完整模型可写为:
s·[u, v, 1]ᵀ = K · [R | t] · [X_w, Y_w, Z_w, 1]ᵀ
K = [ fx 0 cx ]
[ 0 fy cy ]
[ 0 0 1 ]
其中 K 为内参矩阵,fx、fy 是以像素为单位的焦距,cx、cy 是主点(光轴与像平面的交点)像素坐标;[R|t] 为外参,描述相机在世界坐标系中的位置与姿态。这里约定:世界坐标系采用右手系,Z_w 向上;相机坐标系同样为右手系,Z_c 沿光轴指向被摄物体前方,X_c 向右,Y_c 向下。全文及图示均遵循这一约定。
需要特别注意的是,单目相机标定得到的外参是相对于标定板坐标系的。若标定板固定在工作台上,则外参即相机相对工作台坐标系的位姿;若标定板随机械臂末端移动,则每次拍摄的外参都不同,此时应结合手眼标定求解相机与机械臂基座的关系。
二、畸变模型:径向与切向
真实镜头并非理想针孔,成像点会偏离理论位置,形成畸变。工程上最常用的是 Brown-Conrady 模型,包含径向畸变和切向畸变:
x_d = x(1 + k1·r² + k2·r⁴ + k3·r⁶) + 2·p1·x·y + p2·(r² + 2x²)
y_d = y(1 + k1·r² + k2·r⁴ + k3·r⁶) + p1·(r² + 2y²) + 2·p2·x·y
其中 (x, y) 为归一化理想坐标,r² = x² + y²,k1、k2、k3 为径向畸变系数,p1、p2 为切向畸变系数。径向畸变使直线向外弯曲(桶形)或向内弯曲(枕形),切向畸变则源于镜头与像平面不平行。对于抓取工作站常用的 6 mm 至 12 mm 工业镜头,通常只需标定 k1、k2、p1、p2 即可满足亚像素级需求;若使用广角镜头,则需加入 k3。
三、标定板使用要点
标定板是标定的物理基准,其质量直接决定标定上限。常用类型有棋盘格和圆点阵列:棋盘格角点检测精度高、算法成熟,适合大多数工业场景;圆点阵列对透视变形更鲁棒,适合大倾角拍摄。使用时应关注以下要点:
- 格距精度:标定板格距误差应比目标精度高一个数量级。若要求 0.1 mm 的定位精度,格距加工误差应控制在 0.01 mm 以内,建议使用陶瓷或玻璃基板。
- 平整度:标定板翘曲会直接引入外参误差,使用前可用塞尺或平面度仪检查,必要时压在平整台面上。
- 姿态覆盖:采集 15~25 张图像,标定板应覆盖图像四角与中心,倾角在 ±30° 范围内变化,避免所有图像姿态雷同。
- 光照均匀:避免反光和阴影,否则角点提取会出现系统性偏移。
四、标定实战:从采集到求解
以 OpenCV 为例,一次完整的标定流程如下。假设使用 9×6 棋盘格,格距 10 mm,图像分辨率 1280×1024。
import cv2, numpy as np
pattern = (9, 6) # 内角点数
square = 10.0 # 格距 mm
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
objp = np.zeros((pattern[0]*pattern[1], 3), np.float32)
objp[:, :2] = np.mgrid[0:pattern[0], 0:pattern[1]].T.reshape(-1, 2) * square
objpoints, imgpoints = [], []
for fname in images:
img = cv2.imread(fname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ok, corners = cv2.findChessboardCorners(gray, pattern, None)
if ok:
corners = cv2.cornerSubPix(gray, corners, (11,11), (-1,-1), criteria)
objpoints.append(objp)
imgpoints.append(corners)
ret, K, dist, rvecs, tvecs = cv2.calibrateCamera(
objpoints, imgpoints, gray.shape[::-1], None, None)
print("RMS 重投影误差:", ret)
print("内参 K:\n", K)
print("畸变系数:", dist.ravel())
运行后,ret 即 RMS 重投影误差,K 为内参矩阵,dist 为畸变系数。若 ret 大于 0.5 px,通常说明角点提取质量差或姿态覆盖不足,应重新采集。若 ret 在 0.1~0.3 px 之间,可认为标定质量良好。
五、精度验证:不只看重投影误差
重投影误差是标定质量的第一道指标,但它只反映标定板角点的拟合程度,不能完全代表实际抓取精度。建议补充以下验证:
- 尺寸反算:用标定后的参数对一张未参与标定的标定板图像去畸变,测量已知格距的像素距离,反算物理尺寸,与真实格距比较。若误差小于 0.05 mm,说明内参和畸变可信。
- 外参复核:将标定板放置在工作台已知位置,用外参将标定板原点投影到图像,与图像中实际原点比较,偏差应小于 1 个像素。
- 抓取点验证:在标定板上选取若干角点作为目标,用视觉系统计算其三维坐标,与标定板已知坐标比较,重复 10 次,统计均值和标准差。若均值偏差小于 0.2 mm、标准差小于 0.1 mm,可满足多数抓取任务。
六、标定结果在工作站中的落地
标定完成后,需要将 K、dist 以及外参 [R|t] 写入工作站配置文件,供视觉模块调用。典型配置如下:
camera:
width: 1280
height: 1024
K: [1258.3, 0, 642.1,
0, 1257.8, 518.6,
0, 0, 1]
dist: [-0.112, 0.045, 0.0008, -0.0006, 0.0]
T_base_cam: # 相机相对工作台的外参
R: [0.999, -0.012, 0.035,
0.013, 0.999, -0.021,
-0.035, 0.022, 0.999]
t: [320.5, -85.2, 780.4] # mm
视觉模块在计算抓取位姿时,先用 dist 对像素点去畸变,再用 K 反投影得到相机坐标系下的射线,最后用 T_base_cam 变换到工作台坐标系,与机械臂基座坐标系统一。这样,视觉给出的抓取点才能被机械臂正确执行。