MSER+SIFT 图像的特征向量提取 python
在做图像检索时,需要提取图像的特征向量。传统的局部特征描述子如SIFT、SURF等,如果不做别的处理,往往会得到大量的特征向量,虽然特征向量的数目越多,对图像的描述越精确,检索的准确率较高,但是这也会增加硬件成本同时也会耗费大量的计算时间。
从博主的试验结果来看,单张图384×256大小,提取出的SIFT平均有200个,如果直接和库中的数据进行相似度计算,大概要1分钟的时间。对于时间要求很高的产业,这是不能接受的。所以,在不进行压缩图像损失信息的前提下,大大减少SIFT的数目是很有必要,也是很有价值的。
在查阅了大量的资料后,博主发现在做keypoint的compute之前,用MSER 检测出的keypoint代替SIFT检测出的keypoint,可以大大减少SIFT 的数目。对MSER 有疑问的,可以在找几篇相关的博客看一看,不是很复杂。
简单的说一下MSER(最大稳定值检测),基于分水岭的概念,对图像进行二值化,阈值范围[0,255],然后不断变化阈值,变化量可以自己设置,二值图像就会经历一个从全黑0到全白255的过程,就像水位不断上升时陆地和海平面的俯瞰图。在这个过程中,有些连通区域面积随着阈值的变化量很小或基本不变,这些区域就叫MSER 。关于MSER的算法细节和具体实现就不在这说了,有兴趣的可以自己研究一下。
当用MSER检测出keypoint之后,就可以利用SIFT的方式计算这些keypoint的描述子了。
import cv2
import numpy as np
import skimage.io as io
import matplotlib.pyplot as plt
filename="/home/mysj/文档/testpicture"
str=filename+"/*.jpg"
mat=io.ImageCollection(str)
img=mat[0]
##创建一个MSER检测器,并检测图像的MSER区域
##kpkp保存检测到的keypoint
mser=cv2.MSER_create()
regions,boxes=mser.detectRegions(img)
kpkp=mser.detect(img)
print len(mser.detect(img))
##用红框框出检测到的MSER区域,boxes保存这些区域的左上角的坐标和区域的宽和高
for i in range(len(boxes)):
x,y,w,h=boxes[i]
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
#创建一个SIFT特征提取器
siftt=cv2.xfeatures2d.SIFT_create()
print len(regions)
print len(boxes)
kp=siftt.detect(img,None)
##计算kpkp的局部描述子
des=siftt.compute(img,kpkp)
print len(des[0])
##在图像上画出这些keypoint
cv2.drawKeypoints(img,kpkp,mat[0])
plt.imshow(mat[0])
SIFT-SIFT方式提取的特征点有243个,MSER-SIFT提取的特征点有57个,虽然精度会有些下降,但是带来的时间上的提升是很客观的。时间缩短为原来的1/4,相当于原来跑一张的时间现在可以跑4张图。红框是MSER区域。
图一 SIFT-SIFT
图二 MSER-SIFT