4、张正友标定法(上):棋盘格角点检测、单应性矩阵求解内参的闭环推导
张正友标定法,说白了就是「用一张棋盘格照片,把相机内参和外参一起算出来」。这个方法在工业界和学术界都极其常用,我当年刚入行时,第一个上手的标定工具就是基于这个原理。今天我们先讲上半部分:棋盘格角点怎么检测,以及单应性矩阵如何帮我们反推出内参。
4.1 棋盘格角点检测:从图像到亚像素坐标
角点检测是整个标定流程的第一步,也是最容易出坑的一步。你想想看,如果角点坐标都歪了,后面算出来的内参肯定不准。
4.1.1 为什么用棋盘格?
棋盘格有几个天然优势:
- 角点特征明显:黑白交替,梯度变化剧烈,容易定位
- 结构规则:角点间距已知,方便建立世界坐标系
- 抗干扰能力强:比圆点标定板更鲁棒
我个人习惯用 9×6 或 7×5 的内角点棋盘格,太大太小都不好。太大容易拍不全,太小角点数量不够,解算不稳定。
4.1.2 检测流程
- 图像预处理:灰度化、直方图均衡化,增强对比度
- 粗定位:用 Harris 或 Shi-Tomasi 角点检测器找到候选角点
- 亚像素精化:在粗定位周围做二次曲面拟合,得到亚像素级坐标
- 排序与编号:按棋盘格结构给每个角点分配 (u, v) 索引
4.1.3 亚像素精化原理
粗定位得到的角点坐标是整数像素,精度不够。亚像素精化的核心思想是:在角点附近,梯度方向与角点到邻域点的向量垂直。用数学表达就是:
对于角点 q 的邻域点 p_i:
∇I(p_i) · (q - p_i) = 0
其中 ∇I(p_i) 是 p_i 处的图像梯度
q 是待求的亚像素角点坐标
通过最小二乘法求解这个方程组,就能得到亚像素级的角点坐标。我做过实验,亚像素精化后,角点重复性可以从 0.5 像素提升到 0.05 像素左右。
4.2 单应性矩阵:连接世界与图像的桥梁
有了角点坐标,下一步就是建立世界坐标系和图像坐标系之间的映射关系。这个映射就是单应性矩阵 H。
4.2.1 单应性矩阵的物理意义
单应性矩阵描述的是两个平面之间的投影变换。在张正友标定法中,棋盘格平面(世界坐标系 Z=0)到图像平面的映射就是一个单应性变换:
s * [u, v, 1]^T = H * [X, Y, 1]^T
其中:
(u, v) 是图像坐标
(X, Y) 是世界坐标(Z=0)
s 是尺度因子
H 是 3×3 的单应性矩阵
4.2.2 单应性矩阵与内参的关系
单应性矩阵 H 可以分解为内参矩阵 K 和外参(旋转 R、平移 t)的乘积:
H = K * [r1, r2, t]
其中:
r1, r2 是旋转矩阵的前两列
t 是平移向量
K 是内参矩阵
这个分解关系是张正友标定法的核心。通过多张不同角度的棋盘格图像,我们可以利用旋转矩阵的正交约束来求解内参。
4.3 内参求解的闭环推导
这部分是数学推导的核心,我尽量讲得直观一些。
4.3.1 约束条件
旋转矩阵 R 的列向量 r1 和 r2 是正交的,且模长为 1。所以:
r1^T * r2 = 0
||r1|| = ||r2|| = 1
把 H = [h1, h2, h3] 代入,得到:
h1^T * K^{-T} * K^{-1} * h2 = 0
h1^T * K^{-T} * K^{-1} * h1 = h2^T * K^{-T} * K^{-1} * h2
4.3.2 构建线性方程组
令 B = K^{-T} * K^{-1},B 是一个对称矩阵,有 6 个独立元素。把 B 写成向量形式:
b = [B11, B12, B22, B13, B23, B33]^T
对于每一张棋盘格图像,我们可以得到两个约束方程:
v12^T * b = 0
(v11 - v22)^T * b = 0
其中 vij 是由单应性矩阵元素构成的向量。
4.3.3 从 B 矩阵反解内参
解出 b 后,通过 Cholesky 分解可以从 B 矩阵中恢复出内参矩阵 K:
K = [fx, 0, cx;
0, fy, cy;
0, 0, 1]
其中:
fx = sqrt(1 / B11)
fy = sqrt(1 / B22)
cx = -B13 * fx^2
cy = -B23 * fy^2
这里有个细节:B 矩阵的符号问题。我刚开始做的时候,解出来的 fx 是负数,查了半天才发现是 B 矩阵的符号取反了。嗯,遇到这种情况,把 K 矩阵整体取反就行。
4.4 完整流程总结
我把整个流程整理成一张图,方便你理解:
4.5 避坑指南
这部分是我这些年踩过的坑,分享给你:
| 常见问题 | 原因 | 解决方案 |
|---|---|---|
| 角点检测失败 | 光照不均、棋盘格反光 | 使用漫反射标定板,避免强光直射 |
| 内参结果不稳定 | 图像数量太少或角度变化太小 | 至少 15 张,角度覆盖 30°-60° |
| fx 和 fy 差异过大 | 图像分辨率或镜头畸变严重 | 先做畸变校正,再重新标定 |
| 重投影误差偏大 | 角点坐标精度不够 | 检查亚像素精化参数,增加迭代次数 |