图像搜索
基于内容的图像检索
CBIR原理
利用文本标注的方式对图像中的内容进行描述,从而为每幅图像形成描述这幅图像内容的关键词,比如图像中的物体,或者景深更大的场景,在进行检索时,使用者可以根据自己的兴趣提供查询关键字,检索系统用使用者提供的查询关键字找出那些标注有该查询关键字对应的图片,最后将查询的结果返回给使用者。
主要流程为:
1、图像预处理.
2、特征提取(SIFT)
.3、对图像数据库建立图像特征索引
.4、抽取检索(Query)图像特征,构建特征向量.
5、设计检索模块(相似度设置准则)
6、返回相似性较高的结果
矢量空间模型
首先,我们需要一种方式让这些图片形成一种键值关系。
矢量空间模型是一个用于表示和搜索文本文档的模型,它基本可以应用于任何对象类型,包括图像。这些矢量是由文本词频直方图构成的,换句话说,矢量包含了每个单词出现的次数, 而且在其他别的地方包含很多0元素。由于其忽略了单词出现的顺序及位置,该模型也被称为BOW表示模型。
总结来看,这种方式将文本表示成特征矢量。它的基本思想是假定对于一个文本,忽略其词序和语法、句法,仅仅将其看做是一些词汇的集合,而文本中的每个词汇都是独立的。
我们需要找到图像的特征,类似于词汇作为文本的特征,而这种特征必须得对光照,图片的是否旋转,图片畸变等不敏感,而sift特征提取能够较好的满足上述要求,因此,我们使用sift特征提取的方法形成一个词汇
权重的设置
最常用的是权重是tf-idf(tern frequency-inverse document frequency,词频-逆向文档频率)
如何计算权重:
-
计算词频
用公式表示为
-
计算逆文档频率
用公式表示为:
-
计算tf-idf
可以看出该值与一个词在文档中的出现次数成正比,与该词在整个语言中的出现次数成反比。
那么,算法关键流程是计算出文档的每个词的tf-idf值,然后按降序排列,取排在最前面的几个词。
视觉单词
将文本的关键词提取技术应用于图像检索中,需要建立一个类似于关键词的包含图像信息的单词,那么,可以通过sift特征提取出的特征作为视觉单词。
这个过程可进一步描述,将描述子空间量化成一些典型实例,并将图像中的每个描述子指派到其中的某个实例中。这些典型实例可以通过分析训练图像集确定,并被视为视觉单词。所有这些视觉单词构成的集合称为视觉词汇,有时也称为视觉码本。
BOW模型
从一个很大的训练图像提取特征描述子,利用一些聚类算法可以构建出视觉单词。聚类算法最常用的是K-means,这里也采用K-means。视觉单词并不抽象,它只是在给定特殊描述子空间中的一组向量集,在采用K-means进行聚类时得到的视觉单词时聚类质心。用视觉单词直方图来表示图像,则该模型称为BOW模型。
视觉词袋(BoVW,Bag of Visual Words)模型,是“词袋”(BoW,ag of Words)模型从自然语言处理与分析领域向图像处理与分析领域的一次自然推广。对于任意一幅图像,BoVW模型提取该图像中的基本元素,并统计该图像中这些基本元素出现的频率,用直方图的形式来表示。通常使用“图像局部特征”来类比BoW模型中的单词,如SIFT、SURF、HOG等特征,所以也称视觉词袋模型。
创建词汇
为创建视觉单词词汇,首先需要提取特征描述子。这里,我们使用 SIFT 特征描述子。imlist 包含的是图像的文件名。运行下面的代码,可以得到每幅图像提取出的描述子,并将每幅图像的描述子保存在一个文件中:
nbr_images = len(imlist)
featlist = [ imlist[i][:-3]+'sift' for i in range(nbr_images)]
for i in range(nbr_images):
sift.process_image(imlist[i],featlist[i])
创建名为 vocabulary.py 的文件,将下面代码添加进去。该代码创建了一个词汇类,以及在训练图像数据集上训练出一个词汇的方法:
from numpy import *
from scipy.cluster.vq import *
from PCV.localdescriptors import sift
class Vocabulary(object):
def __init__(self,name):
self.name = name
self.voc = []
self.idf = []
self.trainingdata = []
self.nbr_words = 0
def train(self,featurefiles,k=100,subsampling=10):
""" 用含有k个单词的 K-means 列出在 featurefiles 中的特征文件训练出一个词汇。对训练数据下采样可以加快训练速度 """
nbr_images = len(featurefiles)
# 从文件中读取特征
descr = []
descr.append(sift.read_features_from_file(featurefiles[0])[1])
# 将所有的特征并在一起,以便后面进行 K-means 聚类
descriptors = descr[0]
for i in arange(1,nbr_images):
descr.append(sift.read_features_from_file(featurefiles[i])[1])
descriptors = vstack((descriptors,descr[i]))
#K-means: 最后一个参数决定运行次数
self.voc,distortion = kmeans(descriptors[::subsampling,:],k,1)
self.nbr_words = self.voc.shape[0]
# 遍历所有的训练图像,并投影到词汇上
imwords = zeros((nbr_images,self.nbr_words))
for i in range( nbr_images ):
imwords[i] = self.project(descr[i])
nbr_occurences = sum( (imwords > 0)*1 ,axis=0)
self.idf = log( (1.0*nbr_images) / (1.0*nbr_occurences+1) )
self.trainingdata = featurefiles
def project(self,descriptors):
""" 将描述子投影到词汇上,以创建单词直方图 """
# 图像单词直方图
imhist = zeros((self.nbr_words))
words,distance = vq(descriptors,self.voc)
for w in words:
imhist[w] += 1
return imhist
Vocabulary 类包含了一个由单词聚类中心 VOC 与每个单词对应的逆向文档频率构成的向量,为了在某些图像集上训练词汇,train() 方法获取包含有
.sift 描后缀的述子文件列表和词汇单词数 k 。在 K-means 聚类阶段可以对训练数据下采样,因为如果使用过多特征,会耗费很长时间。
现在保存了图像及提取出来的 sift 特征文件,下面的代码会创建一个长为 k ≈ 1000 的词汇表。这里,再次假设 imlist 是一个包含了图像文件名的列表:
import pickle
from PCV.imagesearch import vocabulary
voc = vocabulary.Vocabulary('ukbenchtest')
voc.train(featlist, 888, 10) # 使用k-means算法在featurelist里边训练处一个词汇
#