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。

相机成像模型与标定参数关系 世界坐标系 P_w (X_w, Y_w, Z_w) 标定板/工作台坐标系 外参 [R | t] 旋转 R (3×3) 平移 t (3×1) 相机坐标系 P_c (X_c, Y_c, Z_c) Z_c 沿光轴向前 内参 K fx, fy, cx, cy 像素单位 畸变模型(Brown-Conrady) 径向 k1, k2, k3 | 切向 p1, p2 去畸变 像素坐标 (u, v) 图像平面上的最终观测值 标定板 棋盘格 / 圆点阵列 已知格距 d (mm) 角点世界坐标已知 提供 3D-2D 对应点对 输入 精度验证 重投影误差 RMS (px) 目标:< 0.3 px 棋盘格尺寸反算误差 判断标定是否可用 输出 标定流程:采集多姿态标定板图像 → 提取角点 → 求解内参/外参/畸变 → 重投影验证

三、标定板使用要点

标定板是标定的物理基准,其质量直接决定标定上限。常用类型有棋盘格和圆点阵列:棋盘格角点检测精度高、算法成熟,适合大多数工业场景;圆点阵列对透视变形更鲁棒,适合大倾角拍摄。使用时应关注以下要点:

  • 格距精度:标定板格距误差应比目标精度高一个数量级。若要求 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 之间,可认为标定质量良好。

五、精度验证:不只看重投影误差

重投影误差是标定质量的第一道指标,但它只反映标定板角点的拟合程度,不能完全代表实际抓取精度。建议补充以下验证:

  1. 尺寸反算:用标定后的参数对一张未参与标定的标定板图像去畸变,测量已知格距的像素距离,反算物理尺寸,与真实格距比较。若误差小于 0.05 mm,说明内参和畸变可信。
  2. 外参复核:将标定板放置在工作台已知位置,用外参将标定板原点投影到图像,与图像中实际原点比较,偏差应小于 1 个像素。
  3. 抓取点验证:在标定板上选取若干角点作为目标,用视觉系统计算其三维坐标,与标定板已知坐标比较,重复 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 变换到工作台坐标系,与机械臂基座坐标系统一。这样,视觉给出的抓取点才能被机械臂正确执行。