4. 棋盘格角点检测与亚像素优化

任务目标

本案例实现棋盘格角点检测,并利用亚像素细化(cornerSubPix)将角点坐标精度从像素级提升至亚像素级。检测结果将直接用于后续手眼标定中的相机内参求解与棋盘格位姿估计。

环境依赖

需要 OpenCV(含 contrib 模块)与 NumPy。安装命令:

pip install opencv-contrib-python numpy

关键完整代码

import cv2
import numpy as np

# 棋盘格内角点尺寸(列数=9,行数=6,即每行9个内角点,共6行)
pattern_size = (9, 6)

# 读取图像(请将路径替换为实际棋盘格图像)
image = cv2.imread('chessboard.jpg')
if image is None:
    raise FileNotFoundError("无法读取图像,请检查路径")

gray = cv2.cvtColor(image, 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)
    # 搜索窗口半宽(通常取5或11)
    win_size = (5, 5)
    # 零区域(通常取(-1,-1)表示不使用)
    zero_zone = (-1, -1)

    # 3. 执行亚像素细化
    corners_refined = cv2.cornerSubPix(gray, corners, win_size, zero_zone, criteria)

    # 4. 可视化结果(可选)
    image_draw = image.copy()
    cv2.drawChessboardCorners(image_draw, pattern_size, corners_refined, found)
    cv2.imshow('Refined Corners', image_draw)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    # 5. 输出细化前后对比(取第一个角点为例)
    print("细化前第一个角点坐标:", corners[0][0])
    print("细化后第一个角点坐标:", corners_refined[0][0])
    print("偏移量:", corners_refined[0][0] - corners[0][0])

运行与验证

运行方式:将上述代码保存为 corner_detection.py,与棋盘格图像放在同一目录,执行 python corner_detection.py。

验证方法:

  • 程序输出“未检测到棋盘格角点”时,检查图像是否完整、棋盘格是否清晰、pattern_size 是否与实际内角点数一致。
  • 检测成功时,窗口显示带彩色角点标记的棋盘格,角点应准确落在黑白格交界处。
  • 终端打印的细化前后坐标差值通常小于 0.5 像素(亚像素精度),且细化后坐标不再随迭代变化(已收敛)。

常见问题

  • 检测失败:棋盘格需尽量平整、光照均匀,避免强烈反光或阴影遮挡角点。
  • pattern_size 错误:该参数是内角点数而非棋盘格方格数。例如 10×7 的棋盘格,内角点为 9×6。
  • 亚像素不收敛:增大 criteria 中的迭代次数(如从 30 改为 50),或适当增大 win_size 至 (11, 11)。