SIFT特征提取与检索
SIFT特征提取
Harris函数可以很好的检测角点,这与角点本身的特性有关,这些角点在图像旋转的情况下也能被检测到,但是如果减小(或增加)图像的大小,可能会丢失图像的某些部分,或者有可能增加角点的质量。
这种特征损失现象需要用一种与图像比例无关的角点检测方法来解决——尺度不变特征变换(Scale-Invariant Feature Transform , SIFT),该函数会对不同的图像尺度(尺度不变特征变换)输出相同的结果。SIFT 会通过一个特征向量来描述关键点周围区域情况,而不检测关键点,其核心问题是将同一目标在不同时间、不同分辨率、不同光照、不同方向的情况下所成的像对应起来。
SIFT特征检测的步骤
- 尺度空间的极值检测:搜索所有尺度空间上的图像,通过高斯微分函数来识别潜在的对尺度和旋转不变的兴趣点。
- 特征点定位:在每个候选的位置上,通过一个拟合精细模型来确定位置尺度,关键点的选取依据他们的稳定程度。
- 特征方向赋值: 基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向,后续的所有操作都是对于关键点的方向、尺度和位置进行变换,从而提供这些特征的不变性。
- 特征点描述: 在每个特征点周围的邻域内,在选定的尺度上测量图像的局部梯度,这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变换。
描述子
为了实现旋转不变性,基于每个点周围图像梯度的方向和大小,SIFT 描述子又引入了参考方向。SIFT 描述子使用主方向描述参考方向。主方向使用方向直方图(以大小为权重)来度量
检测兴趣点
使用开源工具包 VLFeat 提供的二进制文件来计算图像的 SIFT 特征
这里说明要安装VLFeat,否则是没法运行代码的,具体的安装方法我在网上找了一种:https://blog.csdn.net/weixin_44037639/article/details/88628253 描述的很详细,可以参照其进行安装,但是我下载vlfeat-0.9.21-bin.tar.gz 的安装包就无法解压,一直报错,所以我就下了9.20的。
需要注意的是括号后要有r 还有最后要有一个空格,否则还是无法运行代码的。
SIFT实验
构造出一个小的数据集
实现数据集中,每张图片的SIFT特征提取,并展示特征点
# -*- coding: utf-8 -*- from PIL import Image from pylab import * from PCV.localdescriptors import sift from PCV.localdescriptors import harris # 添加中文字体支持 from matplotlib.font_manager import FontProperties font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14) imname = 'E:/迅雷下载/test_pic/2/10.jpg' im = array(Image.open(imname).convert('L')) sift.process_image(imname, 'empire.sift') l1, d1 = sift.read_features_from_file('empire.sift') figure() gray() subplot(131) sift.plot_features(im, l1, circle=False) title(u'(a)SIFT特征', fontproperties=font) subplot(132) sift.plot_features(im, l1, circle=True) title(u'(b)用圆圈表示SIFT特征尺度', fontproperties=font) # 检测harris角点 harrisim = harris.compute_harris_response(im) subplot(133) filtered_coords = harris.get_harris_points(harrisim, 6, 0.1) imshow(im) plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*') axis('off') title(u'(c)Harris角点', fontproperties=font) show()
SIFT特征检测算法与Harris 角点检测算法所选择特征点的位置不同,SIFT检测算法检测的精确度比后者更加好,它会对每个关键点周围的区域计算特征向量,因此它主要包括两个操作:检测和计算,操作的返回值是关键点信息和描述符,最后在图像上绘制关键点
给定两张图片,计算其SIFT特征匹配结果
from PIL import Image from pylab import * import sys from PCV.localdescriptors import sift if len(sys.argv) >= 3: im1f, im2f = sys.argv[1], sys.argv[2] else: im1f = 'E:/迅雷下载/test_pic/2/4.jpg' im2f = 'E:/迅雷下载/test_pic/2/4.jpg' im1 = array(Image.open(im1f)) im2 = array(Image.open(im2f)) sift.process_image(im1f, 'out_sift_1.txt') l1, d1 = sift.read_features_from_file('out_sift_1.txt') figure() gray() subplot(121) sift.plot_features(im1, l1, circle=False) sift.process_image(im2f, 'out_sift_2.txt') l2, d2 = sift.read_features_from_file('out_sift_2.txt') subplot(122) sift.plot_features(im2, l2, circle=False) # matches = sift.match(d1, d2) matches = sift.match_twosided(d1, d2) print ('{} matches'.format(len(matches.nonzero()[0])) ) figure() gray() sift.plot_matches(im1, im2, l1, l2, matches, show_below=True) show()
SIFT算法的实质是在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。SIFT所查找到的关键点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。但是对于光滑的平面貌似就没有特别好的效果,检测的效果没有Harris角点检测算法好。
给定文件夹路径,检测图片之间的匹配程度
输入图片
输出图片
# -*- coding: utf-8 -*- import json import os import urllib # import urlparse import urllib.request from pylab import * from PIL import Image from PCV.localdescriptors import sift from PCV.tools import imtools import pydot download_path = "E:/迅雷下载/test_pic/2" path = "E:/迅雷下载/test_pic/2/" imlist = imtools.get_imlist(download_path) nbr_images = len(imlist) featlist = [imname[:-3] + 'sift' for imname in imlist] for i, imname in enumerate(imlist): sift.process_image(imname, featlist[i]) matchscores = zeros((nbr_images, nbr_images)) for i in range(nbr_images): for j in range(i, nbr_images): # only compute upper triangle print('comparing ', imlist[i], imlist[j]) l1, d1 = sift.read_features_from_file(featlist[i]) l2, d2 = sift.read_features_from_file(featlist[j]) matches = sift.match_twosided(d1, d2) nbr_matches = sum(matches > 0) print('number of matches = ', nbr_matches) matchscores[i, j] = nbr_matches # copy values for i in range(nbr_images): for j in range(i + 1, nbr_images): # no need to copy diagonal matchscores[j, i] = matchscores[i, j] # 可视化 threshold = 2 # min number of matches needed to create link g = pydot.Dot(graph_type='graph') # don't want the default directed graph for i in range(nbr_images): for j in range(i + 1, nbr_images): if matchscores[i, j] > threshold: # first image in pair im = Image.open(imlist[i]) im.thumbnail((200, 200)) filename = path + str(i) + '.jpg' im.save(filename) # need temporary files of the right size g.add_node(pydot.Node(str(i), fontcolor='transparent', shape='rectangle', image=filename)) # second image in pair im = Image.open(imlist[j]) im.thumbnail((200, 200)) filename = path + str(j) + '.jpg' im.save(filename) # need temporary files of the right size g.add_node(pydot.Node(str(j), fontcolor='transparent', shape='rectangle', image=filename)) g.add_edge(pydot.Edge(str(i), str(j))) g.write_jpg('E:/迅雷下载/test_pic/2/finally.jpg')
可以看出,SIFT特征检测对于建筑物这些图有很强的实用性,能够将远处、近处、侧面、光照不同的相似图片的共同点匹配出来,同时,对于信息量很大的图片依旧能较为准确的找到特征,就是运行代码的时候跑的时间有点久,运算的时间没有Harris角点检测算法快。
总结
SIFT特征优点:
-
尺度不变性
-
旋转不变性
-
光照不变性
-
鉴别性强,可识别的信息量丰富
SIFT特征的缺点
-
对于边缘光滑的目标无法准确提取特征点