Harris角点检测器

Harris角点检测算法是一个极为简单的角点检测算法。它主要用于检测图像中的角点,即图像中具有独特结构或高度变化的区域。角点通常是图像中非常重要的特征点,因为它们能够提供丰富的信息用于后续的图像匹配、跟踪以及其他高级视觉任务。

工作原理

1.计算梯度:首先计算图像在各个位置上的梯度,这可以通过对图像应用Sobel算子或其他梯度算子来实现。
2.构造自相关矩阵:在每个像素位置上,计算一个结构张量(Structure Tensor),该张量描述了该像素周围一个小区域内梯度的变化情况。结构张量通常是通过对梯度的外积进行积分得到的,公式如下: [ I x 2 I x I y I x I y I y 2 ] \begin{bmatrix} I_{x}^{2} &I_{x} I_{y} \\I_{x} I_{y} &I_{y}^{2} \end{bmatrix} [Ix2IxIyIxIyIy2],其中 I x I_{x} Ix I x I_{x} Ix分别代表图像在 x和y方向上的梯度。
3.角点响应函数:计算角点响应函数 R,它是结构张量的行列式的函数减去迹的平方的函数: R = d e t ( M ) − κ ( t r ( M ) ) 2 R=det\left ( M \right )-\kappa \left ( tr\left ( M \right ) \right ) ^{2} R=det(M)κ(tr(M))2
4.阈值处理与非极大值抑制:对 R 应用阈值,只保留那些响应值大于某个阈值的候选角点。然后进行非极大值抑制,确保每个局部最大值附近只有一个角点。

代码如下:

import cv2
import numpy as np

# 读取图像
image_path = 'E:\PycharmProjects\BookStudying\jmu.jpg'  # 替换为你的图像文件路径
img = cv2.imread(image_path)
if img is None:
    print("Error: 图像未正确加载")
    exit()

# 转换成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 应用Harris角点检测
corners = cv2.cornerHarris(np.float32(gray), blockSize=2, ksize=3, k=0.04)

# 结果是浮点数,对结果进行阈值处理
corners = cv2.dilate(corners, None)  # 扩展角点区域
img[corners > 0.01 * corners.max()] = [0, 0, 255]  # 在原图中标记角点

# 显示结果
cv2.imshow('Harris Corner Detection', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下:
在这里插入图片描述

在图像间寻找对应点

Harris 角点检测器仅仅能够检测出图像中的兴趣点,但是没有给出通过比较图像间的兴趣点来寻找匹配角点的方法。我们需要在每个点上加入描述子信息,并给出一个比较这些描述子的方法。
兴趣点描述子是分配给兴趣点的一个向量,描述该点附近的图像的表观信息。描述子越好,寻找到的对应点越好。我们用对应点或者点的对应来描述相同物体和场景点在不同图像上形成的像素点。
通常,两个(相同大小)像素块 I 1 ( x ) I_{1}\left ( x \right ) I1(x) I 2 ( x ) I_{2}\left ( x \right ) I2(x)的相关矩阵定义为 c ( I 1 , I 2 ) = ∑ x f ( I 1 ( x ) , I 2 ( x ) ) c\left ( I_{1} ,I_{2} \right ) =\sum_{x}^{} f\left ( I_{1}\left ( x \right ) , I_{2}\left ( x \right ) \right ) c(I1,I2)=xf(I1(x),I2(x))

SIFT(尺度不变特征变换)

SIFT特征包括兴趣点检测器和描述子。SIFT描述子具有非常强的稳健性,,SIFT描述符经常和许多不同的兴趣点检测器相结合使用(有些
情况下是区域检测器),有时甚至在整幅图像上密集地使用。SIFT特征对于尺度、旋转和亮度都具有不变性,因此,它可以用于三维视角和噪声的可靠匹配。

描述子

为了实现旋转不变性,基于每个点周围图像梯度的方向和大小,SIFT描述子又引入了参考方向。SIFT描述子使用主方向描述参考方向。主方向使用方向直方图(以大小为权重)来度量。

检测兴趣点

代码如下:

import cv2
import numpy as np

# 读取图像
image_path = 'E:\PycharmProjects\BookStudying\jmu.jpg'  # 替换为你的图像文件路径
img = cv2.imread(image_path)
if img is None:
    print("Error: 图像未正确加载")
    exit()

# 转换成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 初始化ORB特征检测器
orb = cv2.ORB_create(nfeatures=1000)  # 设置检测的最大特征点数量

# 检测兴趣点
keypoints, descriptors = orb.detectAndCompute(gray, None)

# 在原图中标记兴趣点
img_with_keypoints = cv2.drawKeypoints(image=img, keypoints=keypoints, outImage=np.array([]),
                                       color=(0, 255, 0), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

# 显示结果
cv2.imshow("ORB Interest Points", img_with_keypoints)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下:
在这里插入图片描述

匹配描述子

匹配描述子通常用于在不同图像之间找到对应的特征点。描述子是特征检测器提取出来的特征点的表示形式,通常是一串数值,用来描述该点周围的图像内容。匹配描述子的过程就是找到不同图像中对应特征点的过程。

代码如下:

import cv2
import numpy as np
from matplotlib import pyplot as plt

# 加载图像
img1 = cv2.imread('E:\PycharmProjects\BookStudying\jmu.jpg', cv2.IMREAD_GRAYSCALE)  # 查询图像
img2 = cv2.imread('E:\PycharmProjects\BookStudying\jmu2.jpg', cv2.IMREAD_GRAYSCALE)  # 训练图像

# 检查图像是否成功加载
if img1 is None:
    raise ValueError("无法读取图像文件 'img1.png'。请检查文件路径和文件名。")
if img2 is None:
    raise ValueError("无法读取图像文件 'img2.png'。请检查文件路径和文件名。")

# 创建 SIFT 检测器
sift = cv2.SIFT_create()

# 检测关键点和计算描述符
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

# 创建 BFMatcher 对象
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)

# 进行描述符匹配
matches = bf.match(des1, des2)

# 按照距离排序
matches = sorted(matches, key=lambda x: x.distance)

# 绘制匹配结果
img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:50], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

# 显示匹配结果
plt.imshow(img_matches)
plt.title('Feature Matches')
plt.axis('off')

# 保存匹配结果图像
plt.savefig('feature_matches.png', dpi=300, bbox_inches='tight')

plt.show()

结果如下:
在这里插入图片描述

匹配地理标记图像

使用局部描述子匹配

代码如下:

import cv2
import numpy as np

#读取图像
image_path_1 = 'E:\PycharmProjects\BookStudying\jmu2.jpg'  # 第一幅图像的路径
image_path_2 = 'E:\PycharmProjects\BookStudying\jmu2.jpg'  # 第二幅图像的路径

img1 = cv2.imread(image_path_1)
img2 = cv2.imread(image_path_2)

if img1 is None or img2 is None:
    print("Error: 至少有一张图像未正确加载")
    exit()

#转换成灰度图像
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

#初始化ORB特征检测器
orb = cv2.ORB_create(nfeatures=1000)  # 设置检测的最大特征点数量

#检测兴趣点并计算描述子
keypoints1, descriptors1 = orb.detectAndCompute(gray1, None)
keypoints2, descriptors2 = orb.detectAndCompute(gray2, None)

#使用BFMatcher进行匹配
matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = matcher.match(descriptors1, descriptors2)

#排序匹配结果
matches = sorted(matches, key=lambda x: x.distance)

#绘制匹配结果
match_img = cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches[:50], None,
                            flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

#显示匹配结果
cv2.imshow("ORB Matches", match_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果如图:
在这里插入图片描述

可视化连接的图像

我们首先通过图像间是否具有匹配的局部描述子来定义图像间的连接,然后可视化这些连接情况。为了完成可视化,我们可以在图中显示这些图像,图的边代表连接。

代码如下:

import cv2
import numpy as np

#读取图像
image_path_1 = 'E:\PycharmProjects\BookStudying\R-C.png'  # 第一幅图像的路径
image_path_2 = 'E:\PycharmProjects\BookStudying\jmu.jpg'  # 第二幅图像的路径

img1 = cv2.imread(image_path_1)
img2 = cv2.imread(image_path_2)

if img1 is None or img2 is None:
    print("Error: 至少有一张图像未正确加载")
    exit()

#转换成灰度图像
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

#初始化ORB特征检测器
orb = cv2.ORB_create(nfeatures=1000)  # 设置检测的最大特征点数量

#检测兴趣点并计算描述子
keypoints1, descriptors1 = orb.detectAndCompute(gray1, None)
keypoints2, descriptors2 = orb.detectAndCompute(gray2, None)

#使用BFMatcher进行匹配
matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = matcher.match(descriptors1, descriptors2)

#排序匹配结果
matches = sorted(matches, key=lambda x: x.distance)

#绘制匹配结果
match_img = cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches[:50], None,
                            flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

#显示匹配结果
cv2.imshow("ORB Matches", match_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下:
在这里插入图片描述

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部