OpenCV角点检测:Harris与ShiTomasi算法

一、角点检测概述

角点(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角点检测的步骤如下:

  1. 计算图像的灰度值:将彩色图像转换为灰度图像

  2. 计算图像的x和y方向导数:使用Sobel算子(cv2.Sobel())计算

  3. 计算三个基本图像:I_x²、I_y²和I_xI_y

  4. 高斯滤波:对三个基本图像进行高斯滤波(cv2.GaussianBlur())

  5. 计算Harris矩阵M的行列式和迹

  6. 计算角点响应函数R

  7. 阈值处理:提取R值大于阈值的点

  8. 非极大值抑制:在局部区域内保留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()
  1. 参数说明

//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算法类似:

  1. 计算图像的灰度值:将彩色图像转换为灰度图像

  2. 计算图像的x和y方向导数:使用Sobel算子计算

  3. 计算三个基本图像:I_x²、I_y²和I_xI_y

  4. 高斯滤波:对三个基本图像进行高斯滤波

  5. 计算Harris矩阵M的特征值λ1和λ2

  6. 计算角点响应函数R = min(λ1, λ2)

  7. 阈值处理:提取R值大于阈值的点

  8. 非极大值抑制:在局部区域内保留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()
  1. 参数说明

//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中的角点检测实践

  1. 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()函数实现。

主要内容回顾

  1. 角点检测概述:角点的定义、意义和常见算法

  2. Harris角点检测:基本原理、算法步骤和OpenCV实现

  3. ShiTomasi角点检测:基本原理、算法步骤和OpenCV实现

  4. 两种算法的比较:特性、优缺点和应用场景

  5. 实践应用:角点检测的实际应用和技巧

使用建议

根据需求选择合适的角点检测算法

调整参数以获得最佳的检测结果

结合其他特征提取算法(如SIFT、SURF、ORB)使用

对于实时性要求高的任务,考虑使用FAST角点检测算法

通过合理使用角点检测算法,可以在各种计算机视觉任务中获得良好的结果。角点检测是图像匹配、目标跟踪、三维重建等高级视觉任务的基础,掌握角点检测技术对于计算机视觉的学习和应用具有重要意义。

相关推荐
杨建允1 天前
杨建允:AI搜索优化对工业品行业的影响
人工智能·ai
RockHopper20251 天前
为何具身机械主义可以被视为一种工程第一性原则
人工智能·具身智能·世界模型·具身机械主义·具身认知
得贤招聘官1 天前
Agentic AI重构招聘:告别“凭感觉”,迈入精准决策新时代
人工智能
~央千澈~1 天前
卓伊凡 · 从技术底层拆解AI音乐检测各个参数的作用和意义以及检测原理
人工智能
WWZZ20251 天前
SLAM进阶——特征提取
人工智能·大模型·slam·orb·具身智能·特征提取
这张生成的图像能检测吗1 天前
(论文速读)Unified Modality Separation: 无监督领域自适应的视觉语言框架
人工智能·机器学习·无监督学习·视觉语言模型·域自适应·跨模态融合·模态差异
Hcoco_me1 天前
大模型面试题30:Padding 的 mask 操作
人工智能·rnn·深度学习·lstm·word2vec
鹿角片ljp1 天前
力扣283.移动零-双指针法
算法·leetcode·排序算法