第4章:标定板设计——棋盘格、AprilTag、ChArUco的选择与制作规范
做外参标定这么多年,我见过太多人栽在标定板上。
有人拿着打印店随便打的棋盘格,标出来结果一塌糊涂。有人用AprilTag标定,精度倒是上去了,但角点检测总出问题。还有人用ChArUco,觉得它万能,结果制作不规范,标定误差大得离谱。
说白了,标定板是外参标定的“基准尺”。它不准,后面所有工作都是白费。今天我就把这三类标定板的选型思路和制作规范,一次性讲清楚。
核心观点:没有最好的标定板,只有最适合你场景的标定板。选对了,事半功倍;选错了,事倍功半。
4.1 三类标定板的底层逻辑
先看一张图,帮你快速建立知识框架:
4.2 棋盘格——经典但别乱用
棋盘格是标定界的“老黄牛”。它靠黑白格子交替产生的角点,精度非常高。我早期做相机标定时,一直用它。
优点:
- 角点检测精度高,亚像素级别
- 实现简单,OpenCV一行代码搞定
- 制作成本低,打印即可
缺点:
- 没有ID信息,无法区分不同区域
- 必须完整可见,遮挡一点就废
- 对光照敏感,反光时角点检测会飘
我的经验:棋盘格最适合单目内参标定和双目外参标定。但如果你要做多相机系统(比如3个以上相机),棋盘格会让你崩溃——因为每个相机看到的棋盘格区域不同,你很难建立对应关系。
制作规范:
- 格子数量:建议 9×6 或 11×8(内角点),别用太少的
- 格子大小:30mm-50mm 为宜,太小了检测不准,太大了边缘畸变严重
- 打印材质:哑光纸或铝板,千万别用反光材料
- 平整度:贴在刚性背板上,软纸板绝对不行
避坑指南:我曾经用普通A4纸打印棋盘格,贴在纸箱上标定。结果标定出来的焦距偏差了5%以上。后来换成3mm铝板,误差直接降到0.3%。记住:标定板的平整度,直接决定了你的标定精度上限。
4.3 AprilTag——灵活但别迷信
AprilTag是MIT开发的二维码家族成员。它最大的特点是每个Tag都有唯一ID,而且支持部分遮挡检测。
我为什么喜欢它?因为做多相机标定时,你只需要在场景里贴几个AprilTag,每个相机看到不同的Tag组合,系统就能自动匹配对应关系。这比棋盘格方便太多了。
优点:
- 每个Tag有唯一ID,自动匹配
- 支持部分遮挡,哪怕只看到一半也能用
- 可以估计6DoF位姿
缺点:
- 角点精度不如棋盘格(因为角点是Tag边界,不是亚像素级)
- 检测算法相对复杂,计算量大
- Tag大小和距离需要匹配,否则检测失败
关键点:AprilTag的精度瓶颈不在检测算法,而在Tag的打印质量和安装平整度。我见过有人用手机屏幕显示AprilTag来标定,结果屏幕的曲面导致位姿误差巨大。
制作规范:
- Tag家族:推荐使用 Tag36h11(检测鲁棒性好)或 TagStandard41h12(精度更高)
- Tag大小:根据标定距离选择,一般边长50-100mm
- 黑白对比度:打印时黑色要足够黑,白色要足够白,灰度打印不行
- 边框:保留至少1个格子的白色边框,否则检测会失败
# AprilTag生成示例(Python)
import cv2
import numpy as np
from apriltag import apriltag
# 生成Tag36h11家族的ID 0
tag_size = 50 # mm
tag_image = apriltag.generate('tag36h11', 0)
cv2.imwrite('tag_0.png', tag_image)
# 检测时指定Tag大小
detector = apriltag('tag36h11')
results = detector.detect(gray_image)
for r in results:
# r.tag_id: Tag的ID
# r.center: 中心点坐标
# r.corners: 四个角点坐标(像素)
# r.homography: 单应性矩阵
print(f"Tag ID: {r.tag_id}, Center: {r.center}")
4.4 ChArUco——棋盘格和AprilTag的“混血儿”
ChArUco是我现在最常用的标定板。它把棋盘格的角点精度和AprilTag的ID信息结合在了一起。
说白了,ChArUco就是在棋盘格的每个格子交叉点附近,嵌入一个小的ArUco标记。这样你既能得到棋盘格的高精度角点,又能通过ArUco标记获得ID信息。
优点:
- 角点精度高(继承棋盘格)
- 有ID信息,支持部分遮挡(继承ArUco)
- 鲁棒性好,光照变化影响小
缺点:
- 制作要求高,ArUco标记太小了检测不到,太大了影响角点精度
- 检测算法更复杂,计算量更大
- 需要仔细调参
我的建议:如果你做的是高精度外参标定(比如激光雷达-相机标定),ChArUco是首选。我在一个项目中用ChArUco标定Lidar-Camera外参,重投影误差从1.2像素降到了0.3像素。但前提是——你得把ChArUco板做对。
制作规范:
- 棋盘格尺寸:建议 7×5 或 9×6 个格子
- ArUco标记大小:占格子边长的 60%-70%,太小了检测不到,太大了角点被遮挡
- ArUco字典:推荐 DICT_6X6_250 或 DICT_5X5_100
- 打印分辨率:至少 300 DPI,确保ArUco标记清晰
# ChArUco板生成示例(Python + OpenCV)
import cv2
import cv2.aruco as aruco
# 参数设置
squares_x = 7 # 横向格子数
squares_y = 5 # 纵向格子数
square_length = 40 # 格子边长(mm)
marker_length = 25 # ArUco标记边长(mm)
# 创建字典和棋盘
dictionary = aruco.getPredefinedDictionary(aruco.DICT_6X6_250)
board = aruco.CharucoBoard_create(
squares_x, squares_y,
square_length / 1000.0, # 转成米
marker_length / 1000.0,
dictionary
)
# 生成图像
img = board.draw((2000, 1500))
cv2.imwrite('charuco_board.png', img)
# 检测ChArUco角点
charucoCorners, charucoIds = detector.detectBoard(gray_image)
if charucoCorners is not None:
print(f"检测到 {len(charucoCorners)} 个角点")
4.5 选型决策指南
说了这么多,到底怎么选?我整理了一个决策表:
| 场景 | 推荐标定板 | 理由 |
|---|---|---|
| 单目内参标定 | 棋盘格 | 简单、精度高、够用 |
| 双目外参标定 | 棋盘格 或 ChArUco | 棋盘格够用,ChArUco更鲁棒 |
| 多相机系统(3+) | AprilTag 或 ChArUco | 需要ID信息自动匹配 |
| 激光雷达-相机标定 | ChArUco | 需要高精度角点+ID信息 |
| 大场景/远距离标定 | AprilTag(大尺寸) | Tag可以做大,检测距离远 |
| 快速原型验证 | 棋盘格 | 打印快、实现简单 |
重要提醒:不管你选哪种标定板,制作时都要注意以下几点:
- 打印后测量实际尺寸,不要相信设计尺寸(打印机有缩放误差)
- 贴在刚性背板上,确保平整
- 保存时避免弯折、受潮
- 定期检查标定板是否有磨损
4.6 实战经验总结
最后,分享几个我踩过的坑:
- 别用手机屏幕显示标定板:屏幕有曲率,而且亮度不均匀,标定结果会带系统误差
- 标定板尺寸要匹配视场:太小了角点太少,太大了边缘畸变严重。一般占图像面积的 1/4 到 1/3 比较合适
- 多拍不同姿态:至少拍20-30张,覆盖不同角度、距离、位置。我习惯拍50张,然后挑出质量最好的30张
- 检查角点检测结果:不要直接跑标定,先可视化角点检测结果,看看有没有漏检或误检
一句话总结:标定板是标定精度的基石。花1小时做好标定板,能省下10小时排查标定误差的时间。这个投入,绝对值。