OpenCV 从零学习 · 第 14 讲:特征点检测与匹配
函数:goodFeaturesToTrack / ORB_create / BFMatcher | 难度:★★★☆☆
模板匹配遇上旋转、缩放就失灵。特征点方法换思路:在图上找一批"有辨识度"的点(角点、斑点),给每个点算一个描述子向量,然后比对这些向量,就能在另一张图里认出"同一个点",即使图被转过、缩放过。它是图像拼接、物体识别、视觉定位的核心。
一、角点检测 goodFeaturesToTrack
corners = cv2.goodFeaturesToTrack(img, maxCorners, qualityLevel, minDistance)
| 参数 | 含义 |
img | 8 位单通道灰度图 |
maxCorners | 最多返回多少个角点(0=不限) |
qualityLevel | 质量阈值,如 0.01 |
minDistance | 角点间最小像素距离,避免扎堆 |
返回形状 (N,1,2) 的浮点角点坐标。它是"找点"最常用函数,比 cornerHarris 更省心(Harris 返回的是响应图,还得自己筛)。
二、ORB:检测 + 描述(免费、快)
orb = cv2.ORB_create()
kp, des = orb.detectAndCompute(gray, None)
kp 是关键点列表(含位置、尺度、方向),des 是对应的描述子(二进制向量)。ORB 无专利、速度快,是入门首选。
三、暴力匹配 BFMatcher + 比值检验
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2) # 或 knnMatch 做比值检验
matches = sorted(matches, key=lambda m: m.distance)
ORB 描述子是二值,用 NORM_HAMMING 距离。匹配质量看 m.distance,越小越像。用 cv2.drawMatches 可画出连线图。
场景 A · 两张图找相同物体(旋转/缩放不变)
同一本书,一张正拍、一张斜拍。
同一本书,一张正拍、一张斜拍。
ORB 提取特征 → BFMatcher 匹配 → 取 distance 最小的若干对,画连线。模板匹配在这里会直接失败。
场景 B · 图像拼接 / 全景
相邻两张照片用特征匹配找到重叠区,再算单应矩阵对齐拼接——手机全景功能就是这个原理的简化版。
相邻两张照片用特征匹配找到重叠区,再算单应矩阵对齐拼接——手机全景功能就是这个原理的简化版。
场景 C · SIFT(精度更高)
cv2.SIFT_create()(专利已过期,主库可用),描述子为浮点向量,匹配用 NORM_L2,对尺度/旋转更鲁棒但更慢。ORB 不够用时升级 SIFT。
⚠ 新手必踩坑
goodFeaturesToTrack/ ORB / SIFT 都要灰度图。- ORB 用
NORM_HAMMING,SIFT 用NORM_L2,距离类型用错匹配会乱。 - 匹配结果要筛距离(取 top-K 或 Lowe 比值检验),否则大量误匹配会糊成一片。
本讲要点
- 角点
goodFeaturesToTrack最常用;返回(N,1,2)坐标。 - ORB = 检测+描述,免费快;SIFT 更准更慢。
- BFMatcher 比对描述子,按
distance筛选好匹配。 - 特征法能抗旋转/缩放,弥补模板匹配短板。
下一讲:第 15 讲 · 视频的读取与写入(VideoCapture / VideoWriter)——把前面所有的静态图像处理,应用到"一帧帧的视频"上。
