您的位置:首页 > 教育 > 培训 > SIFT算法原理

SIFT算法原理

2024/10/5 19:13:17 来源:https://blog.csdn.net/Yf18005429102/article/details/141106998  浏览:    关键词:SIFT算法原理

1,算法简介

SIFT(ScaleInvariant Feature Transform),尺度不变特征转换。SIFT相对于一般的角点检测算法Harris和shi-tomas来说,具有角度和尺度不变性,不论平移旋转缩放亮度和噪音对特征点都没有影响,而且计算精准,速度快。通俗点来说,人看世界的事物都有近大远小的特点,而且远的事物还会产生模糊效果,但对于计算机来说就要需要使用SIFT算法来提取不同远近不同模糊程度的特征

如下,人眼很容易分辨以下两张图片,但对计算机来说就不容易,利用SIFT算法就可以实现这两张图片的匹配

2,尺度空间极值检测 

首先左边的是图像金字塔,可以看到金字塔的每一层有多张图片,这多张图片就是对同一大小的图片进行不同程度的高斯模糊(对图片进行卷积) 。金字塔第一层的图片大小相同,分别进行不同程度的高斯模糊后得到多张图片(第一张用σ卷积,第二张则用kσ卷积,第三张用k方倍的σ卷积,以此来得到不同模糊程度的图片);第二层金字塔则是第一层图片长宽大小的二分之一,然后再执行不通程度的高斯模糊(图片变为原来的二分之一的方法利用了向下采样法,在opencv中图像金字塔一节说过)。采用向下采样有一个好处,比如说在原始图像用的σ进行卷积,然后采用降采样将长宽都变为原来的二分之一后,再用σ进行卷积实际上是可以得到在原图上用2σ进行卷积的效果,这样可以简化运算

 

这里使用高斯核进行卷积也有一个好处:在每一个图片大小中我们用了很多组标准差σ经过多次卷积得到了多张图片 。高斯核的好处,以下图为例。一张图像经过σ1得到第一次卷积后的图像,再经过σ2得到第二次卷积后的图像,而这两次卷积就可以看作是原图像经过根号下σ1的平方+σ2的平方卷积后的得到的图像

,而卷积核的大小(即选取几乘几的区域对像素进行处理)和标准差σ成正比,标准差越大,卷积核尺寸就要越大 ,如下图所示为高斯分布,σ越大则图像分布越开阔(峰值低坡缓,看起来更胖),而对于σ大的要获取大部分数据那么x轴截取的区域就要更大,而对于σ小的要获取大部分数据那么x轴截取的区域就要更小。也就是说标准差越大意味着就要用更大的卷积核,更大的卷积核就会带来更大的运算量。而利用上述图片的卷积方式就可以把更大的卷积核拆分成几个小的卷积核进行卷积,对小的卷积核卷积后,利用卷积后的图片再进行卷积处理,以此来规避更大的卷积核处理

 

 每一层金字塔得到的多张模糊程度不同的图片,对每一层相邻的两张图片做差值运算(像素数据值),得到了最右边的高斯差值金字塔

 3,确定关键点位置

在差分金字塔中选择一个点并判断这个点是否为极值点。将该像素点与周围上下26个像素点进行比较,如果他是最大点就把他加入到备选点,如果不是就直接舍弃。如右图所示,找出来的极值点不一定为真正的极值点,所以下一步就要找出真正的极值点

 

对找出的众多极值点进行曲线拟合(三维空间x方向,y方向,σ方向) 再去找真正的极值点。这里用二维曲线进行计算便于理解。利用泰勒展开式进行曲线拟合,带入某个位置的像素点作为x0,f(x0)一阶导就用求导的定义式求出即可。如下所示为泰勒展开式展开2项(一般展开两项即可),求出拟合的f(x),f(x)一阶导等于0的位置就是极值点,然后解出x,如下。但是这样求出的x并不是很精确,因为泰勒展开式的后几项都省略了。为了更精确则用牛顿迭代.上述说过f'(x)等于0,就相当于等式右边f'(x0)+f''(x0)(x-x0)等于0,也就是方程F(x)=0 ,使用牛顿迭代,第一轮得到了x如下,然后再把此x往原来的式里面带,进行多次迭代,相当于通用公式如下

 如此迭代后就可以得到比较精确的x

 以下为三阶泰勒展开式

4,去边缘效应

用到二阶Hessian矩阵,二阶矩阵有两个特征值,这两个特征值和它在x,y方向的曲率分别成正比,所以此矩阵可以表示x和y方向的曲率,因为算特征值比较麻烦,所以我们可以用矩阵的迹(一个n×n矩阵A的主对角线(从左上方至右下方的对角线)上各个元素的总和被称为矩阵A(或迹数),一般记作tr(A))和行列式|H|来表示,矩阵的迹等于对角线元素之和也就是特征值α和β相加,矩阵的行列式等于特征值α和β相乘,如下,利用这两个方程就可以求出特征值。我们不希望x和y方向曲率差别太大,因为差别太大相当于一条直线。

将得到的极值点带入这个矩阵,如果得到的矩阵行列式|H|<0,意味着一正一负,特征值差别比较大,需要舍弃。α=γβ γ越大,说明α和β差别越大

 

5,特征方向赋值

得到极值点后,要描述这些极值点的特征信息。找极值点是在高斯差分图像中,而描述特征是在高斯金字塔对应的同尺度图像中。上一步得到的极值点可能它的纵坐标σ不在σ和2σ之间,这时就要看离那一层近,离2σ那层近就放在2σ层,离σ那层近就放在σ层。

在xy位置画一个圆,被圆所包裹在内的像素对它做一个梯度直方图统计(包括方向和幅值),再进行一个高斯的加权,靠近圆心的权重大。统计加权后幅值最高的方向叫做主方向,也就是圆心的特征点所描述的方向。如果有比较高的幅值(大于主方向的80%),则作为特征点的副方向,这个特征点作为两个特征点来算

 6,特征描述

要匹配两个图像中对应的点,计算出每幅图像的关键点和方向之后,就要有一个东西来描述这个关键点。有了关键点的位置和方向之后,对他周围一个范围的像素梯度进行统计。首先将要对照的两张图像进行旋转,使主方向均对应x轴,相当于对所有方向做了一个统一。将如下区域分为16个区域,对每个区域进行梯度统计,一个区域有8个方向,所以共有16X8共128个维的向量来描述关键点的信息。有了这16组统计数据就可以描述关键点特征了,然后对两张图片进行匹配就可以了

7,opencv sift函数

1. sift = cv2.xfeatures2d.SIFT_create() 实例化

参数说明:sift为实例化的sift函数

2. kp = sift.detect(gray, None)  找出图像中的关键点

参数说明: kp表示生成的关键点,gray表示输入的灰度图,

3. ret = cv2.drawKeypoints(gray, kp, img) 在图中画出关键点

参数说明:gray表示输入图片, kp表示关键点,img表示输出的图片

4.kp, dst = sift.compute(kp) 计算关键点对应的sift特征向量

参数说明:kp表示输入的关键点,dst表示输出的sift特征向量,通常是128维的

import cv2
import numpy as np
img = cv2.imread('test_1.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#得到特征点
sift = cv2.xfeatures2d.SIFT_create()#实例化对象
kp = sift.detect(gray,None)
img = cv2.drawKeypoints(gray, kp, img)#可以把关键点绘制出来,结果如下图1
#计算特征
kp, des = sift.compute(gray, kp)#返回两个结果,第一个结果kp还是关键点,第二个参数是每个关键#点对应的特征向量,des.shape输出结果为(关键点数量,128)即每个关键点特征向量为128维
print(np.array(kp).shape)#可以查看关键点数量

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com