4. 棋盘格标定法:从图案设计到张正友标法

棋盘格标定法,说白了就是给鱼眼相机拍一张“标准答案”,然后反推它的畸变参数。我做了这么多年视觉,这个方法是最稳的,没有之一。你想想看,一个黑白相间的棋盘,角点天然就是亚像素级别的特征,比什么圆点网格都好用。

4.1 棋盘格图案设计——别小看这一步

很多人上来就打印棋盘格,结果标定出来误差大得离谱。我踩过这个坑,后来才明白设计阶段就有讲究。

设计参数 推荐值 我的经验
内角点数(列×行) 9×6 或 11×8 别用对称的,比如 8×8,方向容易搞混
方格边长 20-40 mm 太大或太小都会影响角点精度
图案材质 哑光相纸或铝板 反光材料会让角点检测失败
背景色 纯白或纯黑 不要有花纹,否则干扰检测
⚠ 我曾经犯过的错: 用普通打印纸贴在纸箱上,结果棋盘格不平整,标定出来的畸变参数全是错的。后来换成 3mm 铝板覆哑光膜,精度直接提升一个量级。

4.2 角点检测——Harris 与亚像素的配合

角点检测是标定的第一步,也是最容易出问题的一步。我习惯用 Harris 做粗检测,再用亚像素做精定位。

4.2.1 Harris 角点检测

Harris 的原理其实很简单:窗口在角点处移动,灰度变化在任意方向都很大。数学上就是计算自相关矩阵的特征值。

// 伪代码:Harris 角点检测核心
// 1. 计算图像梯度 Ix, Iy
// 2. 构建自相关矩阵 M = [Ix²  IxIy; IxIy  Iy²]
// 3. 计算角点响应 R = det(M) - k * trace(M)²
// 4. 阈值筛选 + 非极大值抑制
💡 我的调参习惯: k 值一般取 0.04-0.06,阈值根据图像对比度动态调整。如果棋盘格光照不均匀,我会先做直方图均衡化再检测。

4.2.2 亚像素角点精化

Harris 只能给出整数像素坐标,但鱼眼标定需要亚像素精度。亚像素角点的原理是利用角点附近梯度与向量正交的特性,通过迭代优化得到浮点坐标。

// OpenCV 实现示例
cv::Mat gray;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

// 粗检测
std::vector<cv::Point2f> corners;
cv::findChessboardCorners(gray, patternSize, corners);

// 亚像素精化
cv::cornerSubPix(gray, corners, cv::Size(5,5), cv::Size(-1,-1),
                 cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.001));
🔑 关键点: 亚像素窗口大小选 5×5 或 7×7 就够了,太大反而引入噪声。迭代次数 30 次,精度 0.001 像素,基本能收敛到稳定值。

4.3 张正友标定法——原理与步骤

张正友标定法,说白了就是利用棋盘格平面约束,把相机内参和外参解耦求解。我当年读这篇时,觉得它最大的贡献是让标定从实验室走向了工程现场。

4.3.1 核心原理

它的核心思想是:棋盘格上的角点共面,所以可以用单应性矩阵(Homography)把世界坐标映射到图像坐标。每张棋盘格图像提供一个单应性矩阵,多个单应性矩阵联合求解内参。

张正友标定法流程 拍摄棋盘格图像 角点检测 计算单应性矩阵 求解内参初值 求解外参初值 非线性优化 输出内参 + 畸变系数 💡 注意:非线性优化阶段同时优化内参、外参和畸变系数, 使用 Levenberg-Marquardt 算法最小化重投影误差。

4.3.2 具体步骤

  1. 准备棋盘格:打印并粘贴到平整表面,测量方格边长。
  2. 拍摄图像:从不同角度拍摄 10-20 张,覆盖视场各个区域。
  3. 角点检测:用 Harris + 亚像素精化提取所有内角点。
  4. 计算单应性矩阵:每张图像建立一个世界坐标到图像坐标的映射。
  5. 求解内参:利用单应性矩阵的约束,线性求解内参矩阵。
  6. 求解外参:固定内参,每张图像单独求解旋转和平移。
  7. 非线性优化:用 LM 算法最小化所有角点的重投影误差。
📊 重投影误差指标: 好的标定结果,平均重投影误差应该在 0.1-0.3 像素。如果超过 0.5 像素,说明图像质量或角点检测有问题。

4.4 实战避坑指南

我做了不下 50 次鱼眼标定,总结出几个最容易翻车的地方:

  • 图像数量不够:少于 10 张,内参解不稳定。我一般拍 15-20 张。
  • 角度变化太小:所有图像几乎同一个视角,外参退化。要旋转、倾斜、平移都覆盖。
  • 棋盘格占画面太小:角点太少,约束不足。棋盘格至少占画面的 1/4。
  • 光照不均匀:部分角点被阴影遮挡。用漫射光源或调整拍摄角度。
💡 我的小技巧: 标定前先拍一张棋盘格正对相机的图像,手动检查角点是否全部正确检测。如果这一步就出错,后面的标定全是白费功夫。

嗯,棋盘格标定法就讲到这里。记住,标定的精度决定了后续校正的效果,花时间把这一步做扎实,后面会省很多事。