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)。