运用到的东西:
1、.关键点:提取到目标图像的特征后,通过与输入图像进行特征匹配,找到那些相同的区域或者像素点,就是上面所说的关键点。
2、兴趣点,又被称为点特征,指的是图像中具有特殊性质的像素点,是图像的重要特征。它具有旋转不变性和不随光照条件变化的优点。这类点被大量用于解决物体识别,图像匹配,视觉跟踪,三维重建等问题。
用于点特征提取的算子称为兴趣点算子,常用的有Harris角点检测、FAST特征检测、SIFT特征检测及SURF特征检测。
3、图像梯度:图像I的梯度定义为 ,其幅值为 ,也可以说是梯度的大小,另一个属性是梯度的方向(角度):
α=arctan2(Iy, Ix)
4、高斯模糊:SIFT算法是在不同的尺度空间上查找关键点,而尺度空间的获取需要使用高斯模糊来实现,Lindeberg等人已证明高斯卷积核是实现尺度变换的唯一变换核,并且是唯一的线性核。
5.高斯差分函数:即高斯差(英语:Difference of Gaussians,简称“DOG”)是一种将一个原始灰度图像的模糊图像从另一幅灰度图像进行增强的算法,通过DOG以降低模糊图像的模糊度。这个模糊图像是通过将原始灰度图像经过带有不同标准差的高斯核进行卷积得到的。用高斯核进行高斯模糊只能压制高频信息。从一幅图像中减去另一幅可以保持在两幅图像中所保持的频带中含有的空间信息。这样的话,DOG就相当于一个能够去除除了那些在原始图像中被保留下来的频率之外的所有其他频率信息的带通滤波器。
SIFT算法过程:
- 尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。
- 关键点定位:在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。
- 方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而提供对于这些变换的不变性。
- 关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变化。
具体过程:
1.构建尺度空间:图像的尺度空间表示成一个函数L(x, y, σ),它是由一个变化尺度的高斯函数G(x, y, σ)与图像I(x, y)卷积生成的。即
其中代表卷积操作,而G(x, y, σ)为:
2.*生成高斯差分金字塔:*利用高斯模糊对于一幅图像进行不同程度地处理和采样(第一个子八度的scale为原图大小,后面每个octave为上一个octave降采样的结果,即原图的1/4(长宽分别减半),构成下一个子八度(高一层金字塔))。然后使用高斯金字塔每组中相邻上下两层图像相减,得到高斯差分图像
左边 高斯金字塔, 右边 高斯差分金字塔
3.DOG算子:
为了寻找尺度空间的极值点,每一个采样点要和它所有的相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。如图所示,中间的检测点和它同尺度的8个相邻点和上下相邻尺度对应的9×2个点共26个点比较,以确保在尺度空间和二维图像空间都检测到极值点。 一个点如果在DOG尺度空间本层以及上下两层的26个领域中是最大或最小值时,就认为该点是图像在该尺度下的一个特征点,如图所示。
因为对比需要三层图片,假设进行极值比较的有2层图(size= 2),又因为每一组图像的首末两层是无法进行极值比较的。所以高斯差分金字塔每组需要S+2层图片,而高斯金字塔需要S+3层图片(在步骤2里面可以看出来)实际计算时S在3到5之间。
4.128维关键点描述子的生成:
- 确定描述子的区域:图像区域的半径计算为
2.将坐标轴旋转为关键点的方向,以确保旋转不变性,如图所示。
3.然后进行4*4子区域的截取 (4*4*8=128),每个子区域使用8 个小区间的方向直方图,会产生共128 个小区间的直方图。直方图中的峰值就是主方向,其他的达到最大值80%的方向可作为辅助方向,如图所示,
利用梯度方向和梯度的模,可以将其表示出来,例如
4.最后进行归一化处理,可以除去光照变化的影响。
5.匹配特征点:
当两幅图像的SIFT特征向量生成后,下一步我们采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量。取图像1中的某个关键点,并找出其与图像2中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离少于某个比例阈值,则接受这一对匹配点。降低这个比例阈值,SIFT匹配点数目会减少,但更加稳定。
# coding=utf-8
from PIL import Image
import numpy as np
import cv2
from matplotlib import pyplot as plt
from find_obj import filter_matches,explore_match
def matchsift():
'''
匹配sift特征
'''
img1 = cv2.imread('D:/python/python2/OpneCV/face1/0436.jpg', 0) # queryImage
img2 = cv2.imread('D:/python/python2/OpneCV/face1/0437.jpg', 0) # trainImage
sift = cv2.SIFT()
kp1, des1 = sift.detectAndCompute(img1, None)
print(len(kp1))
kp2, des2 = sift.detectAndCompute(img2, None)
# 蛮力匹配算法,有两个参数,距离度量(L2(default),L1),是否交叉匹配(默认false)
bf = cv2.BFMatcher()
# 返回k个最佳匹配
matches = bf.knnMatch(des1, des2, k=2)
# cv2.drawMatchesKnn expects list of lists as matches.
# opencv2.4.13没有drawMatchesKnn函数,需要将opencv2.4.13\sources\samples\python2下的common.py和find_obj文件放入当前目录,并导入
p1, p2, kp_pairs = filter_matches(kp1, kp2, matches)
explore_match('find_obj', img1, img2, kp_pairs) # 建立点与点之间的链接
cv2.waitKey()
cv2.destroyAllWindows()
if __name__ == '__main__':
matchsift()
图片效果:
//本人新手,大家多多包涵
from:https://blog.csdn.net/lyl771857509/article/details/79675137
https://blog.csdn.net/abcjennifer/article/details/7639681/?ticket=ST-64237-u9VDdWSajz2iJXCDI06E-passport.csdn.net
https://blog.csdn.net/yan456jie/article/details/52312253