3、棋盘格标定板:为什么用棋盘格?棋盘格尺寸、打印与粘贴规范

好,咱们进入正题。这一章聊的是标定板——棋盘格。很多新手会问:为什么非得是棋盘格?用圆点不行吗?用二维码不行吗?嗯,我当年也有这个疑问。后来踩过坑才明白,棋盘格这东西,看着简单,背后全是讲究。

3.1 为什么偏偏是棋盘格?

说白了,棋盘格是计算机视觉里最“好欺负”的图案。为什么这么说?

  • 角点检测极其稳定:棋盘格的内角点(就是黑白方块的交点)在图像里是天然的“特征点”。不管你怎么旋转、缩放、甚至部分遮挡,算法都能稳稳地找到它。我试过用圆点标定板,光照一变,圆点边缘糊了,检测直接崩掉。棋盘格就没这毛病。
  • 亚像素精度高:棋盘格的角点是一个理想的“鞍点”。在数学上,这个点的梯度在两个方向上变化最剧烈。OpenCV 里有个 cornerSubPix() 函数,专门用来把角点定位到亚像素级别。你想想看,一个像素的误差在广角镜头上可能对应好几度的畸变,亚像素精度有多重要不言而喻。
  • 制作门槛低:一张纸,一台打印机,一把尺子,就能搞定。我在项目现场经常遇到设备不全的情况,临时用 A4 纸画个棋盘格都能应急。换成别的图案?没门。

核心结论:棋盘格的角点,是“确定、唯一、可重复”的。这是标定算法能收敛的前提。

3.2 棋盘格尺寸怎么定?

尺寸不是随便选的。我见过有人拿手机拍一张 3x3 的棋盘格去标定,结果自然是惨不忍睹。这里有几个硬指标:

参数 建议值 说明
内角点数量 至少 7x7 或 9x6 太少的话,畸变模型拟合不出来。我习惯用 9x6,也就是 10x7 个格子。
方格边长 20mm ~ 40mm 取决于你的镜头视场角和拍摄距离。广角镜头离得近,边长可以小一点。
整体尺寸 占画面 20%~40% 标定板在画面里不能太大也不能太小。太大容易出画面,太小角点看不清。

我的经验:如果你用的是 120° 以上的超广角,建议把棋盘格边长做到 30mm 以上。否则边缘区域的格子会被严重拉伸,角点检测会飘。我曾经用 15mm 的格子去标定一个鱼眼镜头,结果边缘的角点偏差了 3 个像素,标定出来的畸变参数全是错的。

3.3 打印与粘贴规范

打印不是随便找个打印店就行的。这里有几个坑,我一个个说。

3.3.1 打印要求

  • 纸张要硬:普通 A4 纸太软,容易皱。我建议用 200g 以上的铜版纸或者照片纸。标定板一旦有褶皱,角点位置就变了。
  • 墨水要防反光:哑光打印!哑光打印!哑光打印!重要的事说三遍。亮光纸在强光下会反光,角点直接消失。我吃过这个亏,在户外用亮光纸标定,太阳一照,棋盘格变成一片白板。
  • 尺寸要精确:打印前用尺子量一下打印出来的实际边长。很多打印机有缩放误差,标称 30mm 打出来可能只有 29.5mm。这个误差会直接带入标定结果。

3.3.2 粘贴规范

粘贴到硬板上也有讲究:

  1. 底板要平整:我用的是 3mm 厚的亚克力板或者铝塑板。木板不行,容易变形。
  2. 用喷胶:双面胶会留下气泡,导致棋盘格表面不平。喷胶均匀,贴上去之后用刮板从中间向四周赶气泡。
  3. 边缘加固:棋盘格的四个角容易翘起。我会用透明胶带在背面加固一圈,但注意胶带不要覆盖到格子区域。

警告:千万不要把棋盘格贴在曲面物体上!比如矿泉水瓶、球面。标定算法假设标定板是平面,一旦有弯曲,内参和畸变参数会全部算错。我曾经见过有人把棋盘格贴在显示器屏幕上标定,屏幕本身有弧度,结果标定出来的焦距偏差了 5%。

3.4 知识结构图

下面这张图是我自己整理的棋盘格标定板的核心逻辑,你看一眼就能明白整个流程:

棋盘格标定板核心逻辑 为什么用棋盘格? 角点稳定 · 亚像素精度 · 易制作 尺寸怎么定? 内角点 ≥ 7x7 · 边长 20~40mm 打印与粘贴 哑光 · 硬纸 · 平板 · 喷胶 常见错误 格子太少 · 纸张反光 · 底板弯曲 · 尺寸不准 最终目标:精确的畸变参数 内参矩阵 + 畸变系数 每一步出错,都会导致标定失败。别问我怎么知道的。

3.5 一个简单的检测脚本

打印之前,我习惯先用 Python 跑一遍检测,看看棋盘格在镜头下能不能被正常识别。这里给个最小示例:

import cv2
import numpy as np

# 棋盘格内角点数量 (宽, 高)
pattern_size = (9, 6)

# 读取图像
img = cv2.imread('checkerboard.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 查找角点
ret, corners = cv2.findChessboardCorners(gray, pattern_size, None)

if ret:
    # 亚像素精细化
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
    corners_sub = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
    
    # 绘制并显示
    cv2.drawChessboardCorners(img, pattern_size, corners_sub, ret)
    cv2.imshow('检测结果', img)
    cv2.waitKey(0)
else:
    print('没找到角点!检查一下棋盘格尺寸或光照。')

这个脚本跑通了,说明你的棋盘格至少在物理上是合格的。如果跑不通,别急着调算法,先看看棋盘格本身有没有问题。

避坑指南:我曾经用一张打印偏色的棋盘格去标定,红色通道和绿色通道的对比度不够,角点检测死活少两个点。后来换成纯黑白打印,一次通过。所以,一定要用纯黑白,不要用彩色棋盘格

好了,棋盘格这部分就聊到这儿。你只要把尺寸、打印、粘贴这三关把好了,后面的标定工作就成功了一半。


专注资料整理