这一节我们来讨论一下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()
函数实现
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)
img.shape: (512, 512, 3)
dst.shape: (512, 512)
img[dst>0.01*dst.max()]=[0,0,255] #非极大值抑制,将边界点标红
cv2.imshow('dst',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
上图可以看出,我们将当中的角点都检测出来了
Harris角点检测算法的优点在于它对旋转、尺度和亮度的变化具有一定的鲁棒性,并且适用于不同类型的图像。该算法还相对简单,计算速度较快。然而,Harris角点检测算法也存在一些限制。例如,它对侧向边缘非常敏感,会将边缘点误判为角点。此外,该算法对于纹理较为平滑的区域可能无法准确地检测到角点。
Scale Invariant Feature Transform(SIFT) 是一种用于计算机视觉和图像处理中的特征检测和描述的算法,可以说是在计算机视觉一种非常流行和广泛使用的算法,它能够检测和描述图像中的关键点,并具有尺度、旋转和视角的不变性,适用于各种图像处理任务,例如目标识别、图像匹配、图像拼接等。SIFT算法主要包括:尺度空间检测、特征关键点检测、特征描述等,接下来我们来分别看一下这些概念
以下是对SIFT算法的详细介绍:
SIFT算法的关键优势在于其对尺度、旋转和视角的不变性,使得它能够在多种条件下鲁棒地检测和匹配图像中的特征点。此外,SIFT算法还具有以下特点:
,因此在目标识别、图像匹配和图像拼接等应用中具有重要的作用。
我们知道在一定的范围内,无论物体是大还是小,我们人眼都可以分辨出来,然而计算机要有相同的能力却很难,所以要让机器能够对物体在不同尺度下有一个统一的认知,就需要考虑图像在不同的尺度下都存在的特点。
图像尺度空间是指在不同尺度下对图像进行分析和处理的一种表示方式。在图像尺度空间中,同一物体或结构的特征在不同尺度下具有不同的尺度信息。这是因为图像中的物体和结构可能以不同的尺度出现,例如大小、边缘和纹理等。通过在不同尺度下分析图像,我们可以获取更全面和鲁棒的特征表示,以适应不同尺度上的目标检测、识别和描述任务。
尺度空间的获取通常使用高斯模糊来实现,
DOG定义:
DoG空间极值检测
为了寻找尺度空间的极值点,每个像素点要和其图像域(同一尺度空间)和尺度域(相邻的尺度空间)的所有相邻点进行比较,当其大于(或者小于)所有相邻点时,该点就是极值点。如下图所示,中间的检测点要和其所在图像的3×3
邻域8
个像素点,以及其相邻的上下两层的3×3
领域18
个像素点,共26
个像素点进行比较。
这些候选关键点是DOG空间的局部极值点,而且这些极值点均为离散的点,精确定位极值点的一种方法是:对尺度空间DoG函数进行曲线拟合,计算其极值点,从而实现关键点的精确定位。
我们使用泰勒展开来拟合,假设在0点展开,则具体表达式如下所示:
用矩阵形式表示如下:
接下来得到了这些极值点具体位置之后,我们还需要对位置进行一些过滤,这里有一个方法就是消除边界响应。因为之前我们通过高斯滤波器对图像进行各种操作,可能会增加一些边界的响应,此时我们需要将其消除掉。
在这里啊,修正方法和我们之前介绍边缘检测类似,当一个特征值大,一个特征值小的时候,它就是边界,这里我们定义了一个和一个。=较大特征值,=较小特征值,组成一个矩阵,具体如下:
当时,进行过滤操作。
下面我们看如何在opencv中实现SIFT特征变换
*注意:*新版本的opencv不能直接调用,需要降版本为3.4.1,安装命令如下;
pip install opencv-python==3.4.1.15
pip install opencv-contrib-python==3.4.1.15
下面我们来看具体代码:
首先读取图片,这里我们还是使用之前的小狗洋气图片
import cv2
import numpy as np
img = cv2.imread('yangqi.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#灰度图
得到关键点:
接下来调用xfeatures2d.SIFT_create()函数
初始化SIFT 检测器对象,然后使用detect()
函数检测关键点
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()
函数计算关键的及其对应的特征
kp, des = sift.compute(gray, kp)
kp
:关键点des
:每一个关键点对应的特征接下来我们来看一下他们的纬度
print(np.array(kp).shape) #kp是一个列表,需要转换成ndarray
print(des.shape)
(605,)
(605, 128)
结果表示我们一共得到了605个关键点,每个关键点是一个128维的向量。
阅读量:443
点赞量:0
收藏量:0