一、角点检测概述
角点(Corner)是图像中具有重要几何意义的点,它是两条或多条边缘的交点,或者是图像中灰度值变化剧烈的区域。角点检测是计算机视觉中的基础任务之一,广泛应用于图像匹配、目标跟踪、三维重建等领域。
1. 角点的定义
角点通常具有以下特征:
几何特征:图像中不同区域的交点
灰度特征:在任意方向上的灰度值变化都很明显
唯一性:角点在图像中具有唯一的位置
稳定性:角点在不同视角、光照条件下保持稳定
2. 角点检测的意义
角点检测在计算机视觉中具有重要意义:
图像匹配:角点是图像的显著特征,可用于图像之间的匹配
目标跟踪:角点可用于目标的跟踪和定位
三维重建:角点可用于从多幅图像重建三维场景
图像拼接:角点可用于图像的拼接和融合
机器人导航:角点可用于机器人的视觉导航
3. 常见的角点检测算法
Harris角点检测:基于图像灰度的二阶导数矩阵
ShiTomasi角点检测:Harris算法的改进版本
FAST角点检测:基于机器视觉的快速角点检测算法
SIFT角点检测:尺度不变特征变换
SURF角点检测:加速稳健特征
ORB角点检测:具有旋转不变性的快速特征
二、Harris角点检测算法
Harris角点检测算法由Harris和Stephens于1988年提出,是一种基于图像灰度二阶导数矩阵的角点检测方法。
1. 基本原理
Harris角点检测的基本思想是:角点是图像中局部区域的极值点,在这些点上,图像的灰度值在任意方向上都有显著的变化。
(1)图像灰度变化的测量
考虑一个图像窗口在x和y方向上的平移(u, v),窗口内的灰度变化可以表示为:
E(u, v) = Σ [ I(x+u, y+v) I(x, y) ]²
其中:
I(x, y):图像在点(x, y)处的灰度值
I(x+u, y+v):图像在平移后的点(x+u, y+v)处的灰度值
Σ:对窗口内所有像素求和
(2)泰勒展开
将I(x+u, y+v)在(x, y)处进行泰勒展开:
I(x+u, y+v) ≈ I(x, y) + uI_x(x, y) + vI_y(x, y)
其中:
I_x(x, y):图像在点(x, y)处的x方向导数
I_y(x, y):图像在点(x, y)处的y方向导数
将泰勒展开式代入灰度变化的测量公式:
E(u, v) ≈ Σ [ uI_x + vI_y ]²
可以整理为:
E(u, v) ≈ [u v] M [u v]^T
其中:
M = Σ [ [I_x² I_xI_y]
I_xI_y I_y²\]
M是一个2×2的矩阵,称为Harris矩阵,它反映了图像在局部区域内的灰度变化情况。
(3)角点响应函数
Harris角点检测使用以下角点响应函数来判断一个点是否为角点:
R = det(M) k(trace(M))²
其中:
det(M):矩阵M的行列式,det(M) = λ1λ2
trace(M):矩阵M的迹,trace(M) = λ1 + λ2
λ1, λ2:矩阵M的特征值
k:经验常数,通常取值为0.04,0.06
根据R的值,可以判断一个点是否为角点:
角点:R >> 0(λ1和λ2都很大)
边缘:R << 0(λ1很大,λ2很小,或反之)
平坦区域:|R|很小(λ1和λ2都很小)
2. 算法步骤
Harris角点检测的步骤如下:
-
计算图像的灰度值:将彩色图像转换为灰度图像
-
计算图像的x和y方向导数:使用Sobel算子(cv2.Sobel())计算
-
计算三个基本图像:I_x²、I_y²和I_xI_y
-
高斯滤波:对三个基本图像进行高斯滤波(cv2.GaussianBlur())
-
计算Harris矩阵M的行列式和迹
-
计算角点响应函数R
-
阈值处理:提取R值大于阈值的点
-
非极大值抑制:在局部区域内保留R值最大的点
3. OpenCV中的Harris实现
在OpenCV中,Harris角点检测通过cv2.cornerHarris()函数实现。
//python
python
import cv2
import numpy as np
from matplotlib import pyplot as plt
#读取图像
img = cv2.imread('chessboard.jpg')
#转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#将图像转换为浮点型
gray = np.float32(gray)
'''
计算Harris角点
参数说明:
gray:灰度图像
blockSize:邻域大小
ksize:Sobel算子的窗口大小
k:Harris角点检测的常数
'''
corners = cv2.cornerHarris(gray, 2, 3, 0.04)
#膨胀角点(可选)
corners = cv2.dilate(corners, None)
#阈值处理
threshold = 0.01 corners.max()
img[corners > threshold] = [0, 0, 255] 角点标记为红色
#显示结果
plt.figure(figsize=(12, 6))
plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('Harris Corners')
plt.subplot(122), plt.imshow(corners, cmap='gray'), plt.title('Corner Response')
plt.tight_layout()
plt.show()
- 参数说明
//python
cv2.cornerHarris(src, blockSize, ksize, k)
参数说明:
src:输入图像,必须是单通道8位或浮点型图像
blockSize:角点检测的邻域大小
ksize:Sobel算子的窗口大小
k:Harris角点检测的常数,通常取值为0.040.06
返回值:
dst:角点响应图像,与输入图像大小相同的浮点型图像
三、ShiTomasi角点检测算法
ShiTomasi角点检测算法由Shi和Tomasi于1994年提出,是Harris算法的改进版本。它使用不同的角点响应函数,提高了角点检测的稳定性和准确性。
1. 基本原理
ShiTomasi角点检测的基本思想与Harris算法类似,但使用了不同的角点响应函数。ShiTomasi算法使用以下角点响应函数:
R = min(λ1, λ2)
其中:
λ1, λ2:Harris矩阵M的特征值
根据R的值,可以判断一个点是否为角点:
角点:R > 阈值(λ1和λ2都大于阈值)
边缘:min(λ1, λ2) < 阈值(一个特征值大于阈值,另一个小于阈值)
平坦区域:R < 阈值(两个特征值都小于阈值)
ShiTomasi算法的角点响应函数比Harris算法更加直观,且在实际应用中表现更好。
2. 算法步骤
ShiTomasi角点检测的步骤与Harris算法类似:
-
计算图像的灰度值:将彩色图像转换为灰度图像
-
计算图像的x和y方向导数:使用Sobel算子计算
-
计算三个基本图像:I_x²、I_y²和I_xI_y
-
高斯滤波:对三个基本图像进行高斯滤波
-
计算Harris矩阵M的特征值λ1和λ2
-
计算角点响应函数R = min(λ1, λ2)
-
阈值处理:提取R值大于阈值的点
-
非极大值抑制:在局部区域内保留R值最大的点
3. OpenCV中的ShiTomasi实现
在OpenCV中,ShiTomasi角点检测通过cv2.goodFeaturesToTrack()函数实现。
//python
python
import cv2
import numpy as np
from matplotlib import pyplot as plt
#读取图像
img = cv2.imread('chessboard.jpg')
#转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
'''
检测ShiTomasi角点
参数说明:
gray:灰度图像
maxCorners:最多检测的角点数量
qualityLevel:角点的最低质量(01之间)
minDistance:角点之间的最小距离
corners = cv2.goodFeaturesToTrack(gray, 25, 0.01, 10)
corners = np.int0(corners) 转换为整数类型
'''
#绘制角点
for i in corners:
x, y = i.ravel()
cv2.circle(img, (x, y), 3, (0, 255, 0), 1) 角点标记为绿色
#显示结果
plt.figure(figsize=(12, 6))
plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('ShiTomasi Corners')
plt.subplot(122), plt.imshow(gray, cmap='gray'), plt.title('Gray Image')
plt.tight_layout()
plt.show()
- 参数说明
//python
cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance[, corners[, mask[, blockSize[, useHarrisDetector[, k]]]]])
参数说明:
image:输入图像,必须是单通道8位或浮点型图像
maxCorners:最多检测的角点数量
qualityLevel:角点的最低质量(01之间),表示只有质量分数高于此值的角点才会被保留
minDistance:角点之间的最小距离
corners:输出参数,检测到的角点坐标
mask:掩码图像,用于指定角点检测的区域
blockSize:邻域大小,默认为3
useHarrisDetector:是否使用Harris角点检测,默认为False(使用ShiTomasi算法)
k:Harris角点检测的常数,默认为0.04
返回值:
corners:检测到的角点坐标,形状为(N, 1, 2)的数组
四、Harris与ShiTomasi算法的比较


五、OpenCV中的角点检测实践
- Harris角点检测实践
//python
python
import cv2
import numpy as np
from matplotlib import pyplot as plt
#读取图像
img = cv2.imread('building.jpg')
#转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#将图像转换为浮点型
gray = np.float32(gray)
#计算Harris角点
corners = cv2.cornerHarris(gray, 2, 3, 0.04)
#膨胀角点
dilated = cv2.dilate(corners, None, iterations=2)
#阈值处理
threshold = 0.01 dilated.max()
#创建结果图像
result = img.copy()
result[dilated > threshold] = [0, 0, 255] 角点标记为红色
#显示结果
plt.figure(figsize=(15, 10))
plt.subplot(131), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('Original Image')
plt.subplot(132), plt.imshow(corners, cmap='gray'), plt.title('Corner Response')
plt.subplot(133), plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)), plt.title('Harris Corners')
plt.tight_layout()
plt.show()
2. ShiTomasi角点检测实践
//python
python
import cv2
import numpy as np
from matplotlib import pyplot as plt
#读取图像
img = cv2.imread('building.jpg')
#转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#检测ShiTomasi角点
corners = cv2.goodFeaturesToTrack(gray, 50, 0.01, 10)
corners = np.int0(corners)
#创建结果图像
result = img.copy()
#绘制角点
for i in corners:
x, y = i.ravel()
cv2.circle(result, (x, y), 3, (0, 255, 0), 1)
cv2.putText(result, f'({x}, {y})', (x+5, y5), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 0, 255), 1)
#显示结果
plt.figure(figsize=(15, 10))
plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('Original Image')
plt.subplot(122), plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)), plt.title('ShiTomasi Corners')
plt.tight_layout()
plt.show()
3. 比较两种算法的检测结果
//python
python
import cv2
import numpy as np
from matplotlib import pyplot as plt
#读取图像
img = cv2.imread('chessboard.jpg')
#转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Harris角点检测
harris_gray = np.float32(gray)
harris_corners = cv2.cornerHarris(harris_gray, 2, 3, 0.04)
harris_corners = cv2.dilate(harris_corners, None)
#创建Harris结果图像
harris_result = img.copy()
harris_threshold = 0.01 harris_corners.max()
harris_result[harris_corners > harris_threshold] = [0, 0, 255]
#ShiTomasi角点检测
sitomasi_corners = cv2.goodFeaturesToTrack(gray, 25, 0.01, 10)
sitomasi_corners = np.int0(sitomasi_corners)
#创建ShiTomasi结果图像
sitomasi_result = img.copy()
for i in sitomasi_corners:
x, y = i.ravel()
cv2.circle(sitomasi_result, (x, y), 3, (0, 255, 0), 1)
#显示结果
plt.figure(figsize=(15, 10))
plt.subplot(131), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('Original Image')
plt.subplot(132), plt.imshow(cv2.cvtColor(harris_result, cv2.COLOR_BGR2RGB)), plt.title('Harris Corners')
plt.subplot(133), plt.imshow(cv2.cvtColor(sitomasi_result, cv2.COLOR_BGR2RGB)), plt.title('ShiTomasi Corners')
plt.tight_layout()
plt.show()
4. 角点检测与SIFT特征匹配
//python
python
import cv2
import numpy as np
from matplotlib import pyplot as plt
#读取两张图像
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')
#转换为灰度图像
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
#使用ShiTomasi角点检测
good_corners1 = cv2.goodFeaturesToTrack(gray1, 100, 0.01, 10)
good_corners2 = cv2.goodFeaturesToTrack(gray2, 100, 0.01, 10)
#转换为整数类型
good_corners1 = np.int0(good_corners1)
good_corners2 = np.int0(good_corners2)
#提取SIFT特征
sift = cv2.SIFT_create()
#计算特征描述符
kp1, des1 = sift.compute(gray1, [cv2.KeyPoint(float(c[0][0]), float(c[0][1]), 10) for c in good_corners1])
kp2, des2 = sift.compute(gray2, [cv2.KeyPoint(float(c[0][0]), float(c[0][1]), 10) for c in good_corners2])
#使用FLANN匹配器
flann_index_kdtree = 1
index_params = dict(algorithm=flann_index_kdtree, trees=5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(des1, des2, k=2)
#筛选好的匹配点
good_matches = []
for m, n in matches:
if m.distance < 0.7 n.distance:
good_matches.append(m)
#绘制匹配结果
result = cv2.drawMatches(img1, kp1, img2, kp2, good_matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
#显示结果
plt.figure(figsize=(20, 10))
plt.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB)), plt.title('Feature Matching Result')
plt.tight_layout()
plt.show()
六、注意事项与技巧
1. 图像预处理
灰度转换:角点检测通常在灰度图像上进行
高斯滤波:使用高斯模糊(cv2.GaussianBlur())去除噪声
对比度增强:使用直方图均衡化(cv2.equalizeHist())增强图像对比度
2. 参数调整
(1)Harris角点检测
blockSize:邻域大小,通常取值为25
ksize:Sobel算子的窗口大小,通常取值为3(必须是奇数)
k:Harris角点检测的常数,通常取值为0.04,0.06
阈值:角点响应函数R的阈值,通常为0.010.1倍的R最大值
(2)ShiTomasi角点检测
maxCorners:最多检测的角点数量,根据图像大小和需求调整
qualityLevel:角点的最低质量,通常取值为0.010.1
minDistance:角点之间的最小距离,通常取值为520
3. 非极大值抑制
目的:在局部区域内只保留R值最大的点,避免角点聚集
实现方法:使用cv2.dilate()和比较操作
4. 性能优化
图像大小:对于大图像,可以先缩小图像尺寸,检测后再放大回原尺寸
ROI区域:使用掩码图像(mask)只检测感兴趣区域内的角点
算法选择:根据需求选择合适的角点检测算法
5. 应用场景选择
Harris角点检测:适用于一般的角点检测任务
ShiTomasi角点检测:适用于高精度角点检测、特征匹配等任务
FAST角点检测:适用于实时性要求高的任务
SIFT/SURF/ORB:适用于需要尺度不变性或旋转不变性的任务
七、总结
角点检测是计算机视觉中的基础任务之一,Harris和ShiTomasi算法是两种经典的角点检测方法。
Harris角点检测:基于图像灰度的二阶导数矩阵,使用det(M) k(trace(M))²作为角点响应函数
ShiTomasi角点检测:Harris算法的改进版本,使用min(λ1, λ2)作为角点响应函数,提高了角点检测的稳定性和准确性
在OpenCV中,Harris角点检测通过cv2.cornerHarris()函数实现,ShiTomasi角点检测通过cv2.goodFeaturesToTrack()函数实现。
主要内容回顾
角点检测概述:角点的定义、意义和常见算法
Harris角点检测:基本原理、算法步骤和OpenCV实现
ShiTomasi角点检测:基本原理、算法步骤和OpenCV实现
两种算法的比较:特性、优缺点和应用场景
实践应用:角点检测的实际应用和技巧
使用建议
根据需求选择合适的角点检测算法
调整参数以获得最佳的检测结果
结合其他特征提取算法(如SIFT、SURF、ORB)使用
对于实时性要求高的任务,考虑使用FAST角点检测算法
通过合理使用角点检测算法,可以在各种计算机视觉任务中获得良好的结果。角点检测是图像匹配、目标跟踪、三维重建等高级视觉任务的基础,掌握角点检测技术对于计算机视觉的学习和应用具有重要意义。