4. 棋盘格角点检测与亚像素优化
任务目标
本案例实现棋盘格角点检测,并利用亚像素精细化提升角点坐标精度,为后续手眼标定提供高精度图像坐标输入。输入为一张棋盘格图像,输出为亚像素级角点坐标及可视化结果。
环境依赖
需要 OpenCV (4.x) 与 NumPy。若需显示结果,还需 Matplotlib。安装命令:
pip install opencv-python numpy matplotlib
关键完整代码
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 棋盘格内角点数量(列数-1,行数-1)
pattern_size = (9, 6)
# 读取图像(请替换为实际路径)
img = cv2.imread('chessboard.jpg')
if img is None:
raise FileNotFoundError("图像读取失败,请检查路径")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 1. 初始角点检测
found, corners = cv2.findChessboardCorners(gray, pattern_size, None)
if not found:
print("未检测到完整棋盘格,请检查图像或调整pattern_size")
else:
# 2. 亚像素精细化
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
corners_subpix = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
# 3. 计算细化前后偏移量(验证精度提升)
shift = np.linalg.norm(corners_subpix - corners, axis=2).flatten()
print(f"检测到角点数: {len(corners_subpix)}")
print(f"亚像素偏移量: 最大={shift.max():.4f}px, 平均={shift.mean():.4f}px")
# 4. 可视化对比
img_show = img.copy()
cv2.drawChessboardCorners(img_show, pattern_size, corners_subpix, found)
plt.figure(figsize=(10, 8))
plt.imshow(cv2.cvtColor(img_show, cv2.COLOR_BGR2RGB))
plt.title("亚像素角点检测结果")
plt.axis('off')
plt.show()
# 5. 输出角点坐标(可用于标定)
print("前5个角点坐标(x, y):")
print(corners_subpix[:5].reshape(-1, 2))
运行与验证
运行方式:将代码保存为 detect_corners.py,与棋盘格图像放在同一目录,修改图像路径后执行:
python detect_corners.py
验证方法:
- 检测成功标志:程序输出角点数量为
54(9×6),且可视化图中角点按行列顺序正确连接。 - 亚像素有效性:输出的最大偏移量通常大于0.01px,平均偏移量在0.01~0.5px之间(具体取决于图像质量与初始检测精度)。若偏移量全为0,说明初始检测已足够精确或图像分辨率过低。
- 精度判定:将细化前后角点分别用于标定,若重投影误差降低,则说明亚像素优化有效。本案例仅输出坐标,标定验证在后续案例中完成。
常见问题
- 检测不到棋盘格:确认图像中棋盘格完整无遮挡,且内角点数量与
pattern_size一致(如9×6表示每行9个内角点,共6行)。 - 角点顺序错乱:OpenCV按从左到右、从上到下的顺序排列角点,若图像倾斜严重,可先进行透视校正。
- 亚像素窗口大小:
(11,11)为搜索窗口,对低分辨率图像可减小至(5,5),高分辨率可增大至(15,15)。