一、什么是亚像素角点检测?
在机器视觉中,角点(Corner)通常代表图像中灰度变化最明显的位置,例如棋盘格交点、矩形顶点、零件边缘交点等。
OpenCV 提供的 Harris、Shi-Tomasi 等角点检测算法得到的角点坐标通常都是整数像素坐标,例如:
(325, 148)
但是实际中,一个角点真正的位置往往位于两个像素之间,例如:
(325.43, 147.82)
这种精度称为亚像素(Sub-Pixel)精度。
亚像素角点检测就是利用周围灰度信息,对角点位置进行迭代优化,使角点定位精度达到 0.1 像素甚至 0.01 像素。
在工业视觉中,这一步通常是相机标定、尺寸测量和高精度定位的重要环节。
二、为什么需要亚像素?
假设一台相机:
- 分辨率:2448×2048
- 一个像素对应实际尺寸:1 Pixel = 0.05 mm
普通角点:
- 误差 ±1 Pixel
- ≈ ±0.05 mm
亚像素优化后:
- 误差 ±0.05 Pixel
- ≈ ±0.0025 mm
精度提升约 20 倍。
因此,以下场景都会使用亚像素优化:
- 相机标定
- 视觉定位
- PCB检测
- 尺寸测量
三、cornerSubPix() 函数
OpenCV 提供 cv2.cornerSubPix() 函数。
函数原型:
python
cv2.cornerSubPix(
image,
corners,
winSize,
zeroZone,
criteria
)
参数说明:
| 参数 | 说明 |
|---|---|
image |
灰度图 |
corners |
初始角点坐标 |
winSize |
搜索窗口大小 |
zeroZone |
忽略中心区域,一般为(-1,-1) |
criteria |
迭代停止条件 |
返回值:
corners 会直接更新为亚像素坐标。
四、停止条件(Termination Criteria)
通常这样设置:
python
criteria = (
cv2.TERM_CRITERIA_EPS +
cv2.TERM_CRITERIA_MAX_ITER,
30,
0.001
)
表示:
- 最多迭代 30 次
- 或者移动距离 < 0.001 Pixel 就停止。
五、完整示例
python
import cv2
import numpy as np
# 读取图片
img = cv2.imread("chessboard.png")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Shi-Tomasi检测角点
corners = cv2.goodFeaturesToTrack(
gray,
maxCorners=100,
qualityLevel=0.01,
minDistance=10
)
# 亚像素停止条件
criteria = (
cv2.TERM_CRITERIA_EPS +
cv2.TERM_CRITERIA_MAX_ITER,
30,
0.001
)
# 亚像素优化
corners = cv2.cornerSubPix(
gray,
corners,
(5,5),
(-1,-1),
criteria
)
# 绘制角点
for corner in corners:
x, y = corner.ravel()
cv2.circle(img,
(int(x), int(y)),
4,
(0,0,255),
-1)
cv2.imshow("Sub Pixel", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
六、cornerSubPix 工作原理
亚像素并不是重新检测角点,而是在已有角点附近进行优化。
假设初始角点:(120, 85)
算法会在附近窗口(如 11×11):
□□□□□□□
□□□●□□□
□□□□□□□
不断计算:
- 灰度梯度
- 最小误差
- 最优位置
最后得到:(120.37, 84.82)
整个过程采用迭代优化,因此速度非常快。
七、与 Harris 检测配合使用
- Harris 负责:找到角点
- cornerSubPix:提高角点精度
流程:
原图 → Harris → 整数角点 → cornerSubPix → 亚像素角点
这是 OpenCV 最经典的组合。
八、棋盘格标定中的应用
OpenCV 标定流程:
python
ret, corners = cv2.findChessboardCorners(
gray,
(9,6)
)
corners = cv2.cornerSubPix(
gray,
corners,
(11,11),
(-1,-1),
criteria
)
这里:
findChessboardCorners得到的是初始角点。- 随后必须调用
cornerSubPix提高角点精度。 - 最后
cv2.calibrateCamera()完成相机标定。
因此,OpenCV 官方标定流程都会包含这一操作。
九、窗口大小如何选择?
- 窗口过小 (3×3):容易受到噪声影响。
- 窗口过大 (25×25):容易包含其它角点。
通常推荐:
| 场景 | winSize |
|---|---|
| 普通检测 | (3,3) |
| 标定 | (5,5) |
| 高精度标定 | (11,11) |
| 大分辨率图像 | (15,15) |
注意:窗口越大,计算量也会增加。
十、实际应用场景
亚像素角点检测广泛应用于:
- 相机标定(Camera Calibration)
- 手眼标定(Hand-Eye Calibration)
- 棋盘格定位
- 工业尺寸测量
- PCB 定位
- Mark 点识别
- 机器人抓取定位
- 精密装配
- AOI 自动光学检测
在工业视觉项目中,凡是涉及毫米级甚至微米级测量,通常都会加入亚像素优化。
十一、总结
亚像素角点检测是 OpenCV 中提高定位精度的重要工具,它通过迭代优化角点位置,将整数像素坐标提升到亚像素级别,显著降低定位误差。
在实际工程中,它通常不会单独使用,而是与 Harris 、Shi-Tomasi 、棋盘格检测 等角点检测算法结合,再应用于 相机标定 、尺寸测量 、视觉定位 等高精度任务。
熟练掌握 cv2.cornerSubPix() 的使用方法,是从基础图像处理迈向工业机器视觉开发的重要一步。