前言
在计算机视觉领域,角点检测 和特征提取是图像识别、目标跟踪、图像拼接等任务的基础。本文将使用OpenCV实现经典的Harris角点检测算法和SIFT(尺度不变特征变换)特征提取算法,并通过代码演示关键步骤,帮助读者快速上手。
一、环境配置
-
Python 3.x
-
OpenCV contrib(支持SIFT)
-
NumPy
二、Harris角点检测
1. 什么是角点?
角点是图像中局部区域与周围区域灰度变化剧烈的点,例如物体的拐角、边缘交点。Harris角点检测通过计算像素点在各个方向上的灰度变化来判定是否为角点,具有旋转不变性,但对尺度变化敏感。
2. 核心函数
dst = cv2.cornerHarris(src, blockSize, ksize, k)
| 参数 | 说明 |
|---|---|
src |
输入图像,必须是单通道灰度图(float32类型最佳) |
blockSize |
角点检测时邻域窗口大小(整数,如2、3、5),窗口越大检测越宏观 |
ksize |
Sobel算子的卷积核大小(必须是奇数:3、5、7),用于计算图像梯度 |
k |
Harris角点检测的自由参数,经验值范围0.04~0.06 |
返回值dst是一个与输入图像同尺寸的浮点型数组,每个元素表示对应像素点的角点响应值,值越大,该点是角点的概率越高。
3. 代码实现
import cv2
import numpy as np
# 读取图像并调整尺寸
img = cv2.imread("cxk.jpg")
img = cv2.resize(img, (400, 500))
# 转为灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Harris角点检测
dst = cv2.cornerHarris(gray, blockSize=4, ksize=3, k=0.04)
# 标记检测到的角点(阈值处理)
img[dst > 0.05 * dst.max()] = [0, 0, 255] # 将角点标记为红色
cv2.imshow("Harris角点检测", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
代码说明:
-
将彩色图转换为灰度图,减少计算量。
-
调用
cornerHarris进行角点检测,得到响应图dst。 -
使用
0.05 * dst.max()作为阈值,将响应值大于该阈值的像素点设为红色,即标记为角点。
运行结果:原图中的角点被红色像素标记,效果如下图所示(示例):

三、SIFT特征提取
1. 什么是SIFT?
SIFT(Scale-Invariant Feature Transform,尺度不变特征变换)是一种检测图像局部特征的算法。它提取的特征对旋转、尺度缩放、亮度变化保持不变性,非常稳定,广泛应用于图像匹配、物体识别等领域。
2. SIFT主要步骤
-
尺度空间极值检测:通过高斯差分金字塔寻找候选关键点。
-
关键点精确定位:剔除低对比度点和边缘响应点。
-
方向赋值:为每个关键点计算主方向,保证旋转不变性。
-
关键点描述:生成128维特征向量,用于后续匹配。
3. 核心函数
-
cv2.SIFT_create():创建SIFT对象。 -
sift.detect(img):检测关键点。 -
sift.compute(img, kp):计算关键点描述符。 -
sift.detectAndCompute(img, mask):一步完成检测和计算。
4. 代码实现
man = cv2.imread("cxk.jpg")
man = cv2.resize(man, (400, 500))
man_gray = cv2.cvtColor(man, cv2.COLOR_BGR2GRAY)
# 创建SIFT对象
sift = cv2.SIFT_create()
# 检测关键点
kp = sift.detect(man_gray, None)
# 绘制关键点(显示大小和方向)
man_sift = cv2.drawKeypoints(man, kp, None,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow("SIFT关键点", man_sift)
cv2.waitKey(0)
# 计算描述符
kp, des = sift.compute(man, kp)
print("关键点数量:", np.array(kp).shape)
print("描述符形状:", des.shape) # 输出 (N, 128)
cv2.destroyAllWindows()
代码说明:
-
sift.detect()返回关键点列表kp,每个关键点包含坐标pt、尺度size、方向angle等属性。 -
cv2.drawKeypoints的flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS会绘制出关键点的圆形区域和方向线,直观展示特征点的尺度和方向。 -
sift.compute()计算描述符,输出des是一个二维数组,形状为(关键点数量, 128),每个128维向量用于唯一描述该关键点。
运行结果:
-
图像上会显示关键点位置及其圆形区域和方向线。
-
控制台输出类似:
关键点数量: (391,) 描述符形状: (391, 128)

四、SIFT的实际应用:特征匹配(扩展)
SIFT描述符常用于图像匹配。下面是一个简单的特征匹配示例,展示如何将两幅图像的特征点进行匹配:
# 读取两张图像
img1 = cv2.imread("scene.jpg")
img2 = cv2.imread("object.jpg")
sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
# 创建FLANN匹配器
flann = cv2.FlannBasedMatcher()
matches = flann.knnMatch(des1, des2, k=2)
# 应用比率测试筛选良好匹配
good = []
for m, n in matches:
if m.distance < 0.75 * n.distance:
good.append(m)
# 绘制匹配结果
result = cv2.drawMatches(img1, kp1, img2, kp2, good, None, flags=2)
cv2.imshow("SIFT匹配", result)
cv2.waitKey(0)
通过匹配点对的数量或距离阈值,可以实现图像识别、指纹验证等任务。
五、总结
| 方法 | 作用 | 特点 |
|---|---|---|
| Harris角点检测 | 检测图像中的角点 | 旋转不变,但对尺度变化敏感 |
| SIFT特征提取 | 检测关键点并生成描述符 | 尺度、旋转、光照不变,适合匹配 |
通过本文的学习,你已经掌握了OpenCV中两种经典特征提取方法的基本使用。Harris角点检测适合快速定位图像中的角点区域,而SIFT特征则更强大,广泛用于图像匹配与识别任务。
六、参考资料
- OpenCV官方文档:Harris角点检测 | SIFT
如果本文对你有帮助,请点赞、收藏、评论支持一下,你的鼓励是我持续创作的动力!