【Opencv入门到项目实战】(九):harris角点检测|SIFT|特征匹配

1.harris角点检测

这一节我们来讨论一下Harris角点检测,由Chris Harris和Mike Stephens于1988年提出。该算法通过计算图像的局部灰度变化来检测角点,并利用协方差矩阵的特征值来确定是否为角点。

它的基本思想是,对于图像I(x,y),当在点(x,y)处平移(​x,​y)后的灰度变化有多大。我们定义其变换后的自相似性为:

w(x, y)是以点(x,y)为中心的一个窗口,一般我们用高斯窗口函数,用于平滑梯度。

然后对右边利用泰勒展开:

其中,Ix和Iy分别表示图像在x和y方向上的梯度

代入后近似得到下列结果:

其中M为协方差矩阵:

接下来我们利用协方差的特征值来计算每个像素点的角点相响应值R

其中,det(M)表示协方差矩阵M的行列式,trace(M)表示协方差矩阵M的迹,​是一个常数,用于调整响应函数的灵敏度。

Opencv中,我们调用cv2.cornerHarris()函数实现

ini 复制代码
import cv2 
import numpy as np
​
# 导入图片
img = cv2.imread('test_1.jpg')
print ('img.shape:',img.shape)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)#转换为float32格式
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
print ('dst.shape:',dst.shape)
​
makefile 复制代码
img.shape: (512, 512, 3)
dst.shape: (512, 512)
scss 复制代码
img[dst>0.01*dst.max()]=[0,0,255] #非极大值抑制,将边界点标红
cv2.imshow('dst',img) 
cv2.waitKey(0) 
cv2.destroyAllWindows()

上图可以看出,我们将当中的角点都检测出来了

Harris角点检测算法的优点在于它对旋转、尺度和亮度的变化具有一定的鲁棒性,并且适用于不同类型的图像。该算法还相对简单,计算速度较快。然而,Harris角点检测算法也存在一些限制。例如,它对侧向边缘非常敏感,会将边缘点误判为角点。此外,该算法对于纹理较为平滑的区域可能无法准确地检测到角点。

2.尺度不变特征变换(SIFT)

Scale Invariant Feature Transform(SIFT) 是一种用于计算机视觉和图像处理中的特征检测和描述的算法,可以说是在计算机视觉一种非常流行和广泛使用的算法,它能够检测和描述图像中的关键点,并具有尺度、旋转和视角的不变性,适用于各种图像处理任务,例如目标识别、图像匹配、图像拼接等。SIFT算法主要包括:尺度空间检测、特征关键点检测、特征描述等,接下来我们来分别看一下这些概念

以下是对SIFT算法的详细介绍:

  1. 特征点检测:

    • 尺度空间极值检测:SIFT首先在不同尺度下使用高斯模糊滤波器构建尺度空间金字塔,然后通过比较每个像素与其周围像素及所处尺度上的像素进行检测,找到图像中的关键点。
    • 关键点精化:通过利用尺度空间的极值点,对关键点进行精化,计算其精确位置和尺度尺度,并根据梯度方向来确定主方向。
  2. 特征描述:

    • 局部图像描述子:以关键点为中心,在其周围的邻域内构建一个具有旋转不变性和尺度不变性的局部图像描述子。该描述子基于关键点附近的梯度方向和强度信息,通过生成一个特征向量来描述关键点周围的图像结构。
    • 方向直方图:在计算局部图像描述子之前,首先根据关键点周围的梯度方向计算一个方向直方图,用来确定主方向。
  3. 特征匹配:

    • 特征向量匹配:将两幅图像的特征向量进行匹配,通常使用最近邻匹配方法(如欧氏距离)来寻找每个特征点的最佳匹配。同时,还可以使用二次最近邻比率测试来过滤不可靠的匹配。
    • 鲁棒性和一致性:为了提高匹配的鲁棒性和一致性,可以使用诸如RANSAC(随机抽样一致性)等方法来剔除异常和错误的匹配点。

SIFT算法的关键优势在于其对尺度、旋转和视角的不变性,使得它能够在多种条件下鲁棒地检测和匹配图像中的特征点。此外,SIFT算法还具有以下特点:

  • 独特性:SIFT特征是在图像中独一无二的,它们可以用来区分不同的图像区域。
  • 不变性:SIFT特征对于有限的视角变化、尺度变化以及轻微的仿射变换都具有较好的不变性。
  • 高鲁棒性:SIFT算法对于光照变化、噪声和部分遮挡等情况下仍能产生准确的匹配结果。
  • 可扩展性:SIFT算法可以应用于各种图像尺寸和分辨率的图像,并且在大规模图像数据库中进行高效匹配。

,因此在目标识别、图像匹配和图像拼接等应用中具有重要的作用。

2.1图像尺度空间

我们知道在一定的范围内,无论物体是大还是小,我们人眼都可以分辨出来,然而计算机要有相同的能力却很难,所以要让机器能够对物体在不同尺度下有一个统一的认知,就需要考虑图像在不同的尺度下都存在的特点。

图像尺度空间是指在不同尺度下对图像进行分析和处理的一种表示方式。在图像尺度空间中,同一物体或结构的特征在不同尺度下具有不同的尺度信息。这是因为图像中的物体和结构可能以不同的尺度出现,例如大小、边缘和纹理等。通过在不同尺度下分析图像,我们可以获取更全面和鲁棒的特征表示,以适应不同尺度上的目标检测、识别和描述任务。

尺度空间的获取通常使用高斯模糊来实现,

  • 高斯金字塔: 高斯金字塔是一种通过对图像进行连续的高斯滤波和下采样操作来构建图像尺度空间的方法。具体步骤如下:

    • 先对原始图像应用一个初始尺度的高斯滤波器。
    • 对滤波后的图像进行下采样(通常是进行二次减半),得到下一层金字塔图像。
    • 重复以上步骤,直到达到预定的尺度层数。
  • 多分辨率金字塔,它是通过将原始图像进行分解,得到一系列具有不同分辨率的图像层级,从而实现对图像的多尺度分析和处理通常采用逐步降采样(downsampling)和上采样(upsampling)的方法。

    • 首先,原始图像通过降采样操作被缩小为较低分辨率的图像,然后这个较低分辨率的图像再次进行降采样,直到达到所需的分辨率层级。
    • 这样就形成了一个金字塔状的层级结构,其中每个层级的图像都比上一层级的图像具有更低的分辨率。
    • 在每层进行高斯滤波器操作

    多分辨率金字塔的主要优势之一是可以在不同尺度下对图像进行分析。高层级的图像层级具有较低的分辨率,但能够捕捉到图像的整体特征和结构信息;而低层级的图像层级具有较高的分辨率,能够提供更多的细节信息。因此,通过在不同层级上对图像进行处理,可以获得更全面和准确的分析结果。

  • 尺度空间差分金字塔: 尺度空间差分金字塔是基于高斯金字塔的构建方法。它通过计算高斯金字塔相邻层之间的差分图像来获取尺度空间的特征。这样做可以捕捉到图像中的细节信息,而较高尺度的层级可以揭示出图像中的整体结构。通过在不同层级上进行差分操作,可以凸显出图像中的边缘、角点等局部结构。具体步骤如下:

    • 构建高斯金字塔,并对每一层进行高斯平滑。
    • 对相邻两层图像进行差分操作,得到差分图像。
    • 重复以上步骤,直到达到预定的尺度层数。

DOG定义:

DoG空间极值检测

为了寻找尺度空间的极值点,每个像素点要和其图像域(同一尺度空间)和尺度域(相邻的尺度空间)的所有相邻点进行比较,当其大于(或者小于)所有相邻点时,该点就是极值点。如下图所示,中间的检测点要和其所在图像的3×3邻域8个像素点,以及其相邻的上下两层的3×3领域18个像素点,共26个像素点进行比较。

2.2 关键点定位

这些候选关键点是DOG空间的局部极值点,而且这些极值点均为离散的点,精确定位极值点的一种方法是:对尺度空间DoG函数进行曲线拟合,计算其极值点,从而实现关键点的精确定位。

我们使用泰勒展开来拟合,假设在0点展开,则具体表达式如下所示:

用矩阵形式表示如下:

2.3 消除边界响应

接下来得到了这些极值点具体位置之后,我们还需要对位置进行一些过滤,这里有一个方法就是消除边界响应。因为之前我们通过高斯滤波器对图像进行各种操作,可能会增加一些边界的响应,此时我们需要将其消除掉。

在这里啊,修正方法和我们之前介绍边缘检测类似,当一个特征值大,一个特征值小的时候,它就是边界,这里我们定义了一个​和一个​。​=较大特征值,​=较小特征值,组成一个​矩阵,具体如下:

当​时,进行过滤操作。

2.4 代码示例

下面我们看如何在opencv中实现SIFT特征变换

*注意:*新版本的opencv不能直接调用,需要降版本为3.4.1,安装命令如下;

pip install opencv-python==3.4.1.15

pip install opencv-contrib-python==3.4.1.15

下面我们来看具体代码:

首先读取图片,这里我们还是使用之前的小狗洋气图片

ini 复制代码
import cv2
import numpy as np
​
img = cv2.imread('yangqi.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#灰度图

得到关键点:

接下来调用xfeatures2d.SIFT_create()函数初始化SIFT 检测器对象,然后使用detect()函数检测关键点

ini 复制代码
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None)#得到特征点
​
img = cv2.drawKeypoints(gray, kp, img) #绘制特征点
​
cv2.imshow('drawKeypoints', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

计算特征:

接下来使用sift.compute()函数计算关键的及其对应的特征

ini 复制代码
kp, des = sift.compute(gray, kp)
  • kp:关键点
  • des:每一个关键点对应的特征

接下来我们来看一下他们的纬度

php 复制代码
print(np.array(kp).shape) #kp是一个列表,需要转换成ndarray
print(des.shape)
scss 复制代码
(605,)
(605, 128)

结果表示我们一共得到了605个关键点,每个关键点是一个128维的向量。

相关推荐
千天夜38 分钟前
激活函数解析:神经网络背后的“驱动力”
人工智能·深度学习·神经网络
大数据面试宝典40 分钟前
用AI来写SQL:让ChatGPT成为你的数据库助手
数据库·人工智能·chatgpt
封步宇AIGC1 小时前
量化交易系统开发-实时行情自动化交易-3.4.1.2.A股交易数据
人工智能·python·机器学习·数据挖掘
m0_523674211 小时前
技术前沿:从强化学习到Prompt Engineering,业务流程管理的创新之路
人工智能·深度学习·目标检测·机器学习·语言模型·自然语言处理·数据挖掘
HappyAcmen1 小时前
IDEA部署AI代写插件
java·人工智能·intellij-idea
噜噜噜噜鲁先森1 小时前
看懂本文,入门神经网络Neural Network
人工智能
InheritGuo2 小时前
It’s All About Your Sketch: Democratising Sketch Control in Diffusion Models
人工智能·计算机视觉·sketch
weixin_307779132 小时前
证明存在常数c, C > 0,使得在一系列特定条件下,某个特定投资时刻出现的概率与天数的对数成反比
人工智能·算法·机器学习
封步宇AIGC2 小时前
量化交易系统开发-实时行情自动化交易-3.4.1.6.A股宏观经济数据
人工智能·python·机器学习·数据挖掘
Jack黄从零学c++2 小时前
opencv(c++)图像的灰度转换
c++·人工智能·opencv