Python计算机视觉(五)——基于BOW的图像检索


一、图像搜索

图像搜索,是通过搜索图像文本或视觉特征,为用户提供互联网上相关图形图像资料检索服务的专业搜索引擎系统,是搜索引擎的一种细分。一种是通过输入与图片名称或内容相似的关键字来进行检索,另一种通过上传与搜索结果相似的图片或图片URL进行搜索。

由于图像不同于文本,需要人们按照各自的理解来说明其蕴含的意义,需要人工干预找出图像并进行分类,因此图像检索比起文本的查询和匹配要困难得多。图像搜索引擎大多支持关键词检索和分类浏览两种检索方式,主要的检索途径有三种:①基于图像外部信息,即根据图像的文件名或目录名、路径名、链路、ALT标签以及图像周围的文本信息等外部信息进行检索;②基于图像内容特征描述,即人工对图像的内容(如物体、背景、构成、颜色特征等)进行描述并分类,给出描述词,检索时主要在这些描述词中搜索检索词;③基于图像形式特征的抽取,由图像分析软件自动抽取图像的颜色、形状、纹理等特征,建立特征索引库,只需将要查找的图像的大致特征描述出来,就可以找出与之具有相近特征的图像。

二、BOW模型图像检索

1.BOW(Bag-of-words)

Bag-of-words 简称BOW,也叫做“词袋”,最初是为解决文档建模问题而提出的,在信息检索中,BOW模型假定对于一个文本,忽略其词序和语法、句法,将其仅看做是一个词集合,或者说是词的一个组合,文本中每个词的出现都是独立的,不依赖于其他词是否出现。

通过单词计数构建词袋,将文档转化为各个单词元素作为横坐标,以单词出现的次数作为纵坐标的直方图,从而建立文档索引,然后进行归一化处理,将每个词出现的频数作为文档的特征。

由于每篇文档长度不同,故除以直方图总和将向量归一化成单位长度。对于直方图向量中的每个元素,一般根据每个单词的重要性来赋予相应的权重。通常,数据集中一个单词的重要性与它在文档中出现的次数成正比,而与它在数据集中出现的次数成反比。最常用的权重是TF-IDF(词频-逆向文档频率)。

2.Bag-of-features

将BOW引入到计算机视觉中,将一幅图像看成文本对象,图像中的不同特征可以看着构成图像的不同词汇,类似于文本的BoW模型,将图片分成若干个图像块,构建“词库”,就可以使用图像特征在图像中出现的频率,使用一个一维的向量来描述图像,这就是Bag-of-features

三、算法流程

1.特征提取

特征提取及描述主要是将一些具有代表性区分性较强全局或局部特征从图像中进行抽取,这些特征一般是类别之间差距比较明显的特征,可以将其与其他类别区分开,其次,这些特征还要求具有较好的稳定性,并对这些特征进行描述。
通常会使用SIFT算法从图片上提取出很多特征点,每个特征点都是128维的向量,因此,如果图片足够多的话,我们会提取出一个巨大的特征向量库。
在这里插入图片描述

2.学习“视觉词典”(visual vocabulary)

在上面提取完SIFT特征的步骤后,利用K-means聚类算法将提取的SIFT特征聚类生成视觉词典。
K-means算法是度量样本间相似性的一种方法,该算法设置参数为K,把N个对象分成K个簇,簇内之间的相似度较高,而簇间的相似度较低。聚类中心有K个,视觉词典为K。构建视觉单词的过程如图所示。
在这里插入图片描述

K-means 聚类算法:最小化每个特征与其对应的聚类中心之间的欧式距离 算法流程:

  • 随机初始化K个聚类中心
  • 重复下述步骤直至算法收敛
    1 对应每个特征,根据距离关系赋值给某个中心/类别
    2 对每个类别,根据其对应的特征集重新计算聚类中心

3.针对输入特征集,根据视觉词典进行量化

码本/字典用于对输入图片的特征集进行量化:
对于输入特征集,量化的过程是将该特征映射到距离其最接近的 codevector ,并实现计数

4.把输入图像,根据TF-IDF转化成视觉单词的频率直方图

TF-IDF(Term frequency-Inverse document frequency)是一种统计方法,用来评估特征词的重要程度。根据TF-IDF公式,特征词的权重与在 语料库中出现的频率有关,也与在文档里出现的频率有关。
在这里插入图片描述

TF-IDF用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。就目前来说,如果一个 关键词只在很少的网页中出现,我们通过它就 容易锁定搜索目标,它的 权重也就应该 大。反之如果一个词在大量网页中出现,我们看到它仍然 不是很清楚要找什么内容,因此它应该小。

5.构造特征到图像的倒排表,通过倒排表快速索引相关图像

在这里插入图片描述
倒排表记录 <视觉单词,具有该视觉单词的图像集合>, 倒排表可以快速使用反转文件来计算新图像与数据库中所有图像之间的相似性,仅考虑其分档与查询图像重叠的数据库图像,大大减少了匹配次数,优化了算法。

6.根据索引结果进行直方图匹配

根据索引结果进行直方图匹配,得到匹配结果。

四、代码实现

1.数据集

该数据集一共有120张图像,包含建筑、动物、花卉、手机的4个种类图片,每个种类图片30张。
在这里插入图片描述

2.创建词汇

import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift

#获取图像列表
imlist = get_imlist('image')
nbr_images = len(imlist)
print('nbr_images:',nbr_images)
#获取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
#提取文件夹下图像的sift特征
for i in range(nbr_images):
    sift.process_image(imlist[i], featlist[i])
#生成词汇
voc = vocabulary.Vocabulary('Image')
voc.train(featlist, 200, 10)#调用了PCV的vocabulary.py中的train函数
#保存词汇
with open('image\\vocabulary.pkl', 'wb') as f:
    pickle.dump(voc, f)#将生成的词汇保存到vocabulary.pkl(f)中
print ('vocabulary is:', voc.name, voc.nbr_words)

运行结果:SIFT特征匹配为每个图像得到一个相应的.sift文件,生成vocabulary.pkl,用pickle模块保存了整个词汇对象。
在这里插入图片描述
在这里插入图片描述

3.创建索引

import pickle
from PCV.imagesearch import imagesearch
from PCV.localdescriptors import sift
from sqlite3 import dbapi2 as sqlite
from PCV.tools.imtools import get_imlist
#获取图像列表
imlist = get_imlist("image")
nbr_images = len(imlist)
#获取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
#载入词汇
with open('image\\vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)
#创建索引
indx = imagesearch.Indexer('testImaAdd.db',voc)
indx.create_tables()
#遍历所有的图像,并将它们的特征投影到词汇上
for i in range(nbr_images)[:1000]:
    locs,descr = sift.read_features_from_file(featlist[i])
    indx.add_to_index(imlist[i],descr)
#提交到数据库
indx.db_commit()
con = sqlite.connect('testImaAdd.db')
print (con.execute('select count (filename) from imlist').fetchone())
print (con.execute('select * from imlist').fetchone())

运行结果:
在这里插入图片描述

4.检索测试

import pickle
from PCV.localdescriptors import sift
from PCV.imagesearch import imagesearch
from PCV.geometry import homography
from PCV.tools.imtools import get_imlist
#载入图像列表
imlist = get_imlist("image")
nbr_images = len(imlist)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
#载入词汇
with open('image\\vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)
src = imagesearch.Searcher('testImaAdd.db',voc)
#查询图像索引和查询返回的图像数
q_ind = 29
nbr_results = 20
# 常规查询(按欧式距离对结果排序)
res_reg = [w[1] for w in src.query(imlist[q_ind])[:nbr_results]]
print ('top matches (regular):', res_reg)
# load image features for query image
#载入查询图像特征
q_locs,q_descr = sift.read_features_from_file(featlist[q_ind])
fp = homography.make_homog(q_locs[:,:2].T)
# RANSAC model for homography fitting
#用单应性进行拟合建立RANSAC模型
model = homography.RansacModel()
rank = {}
# load image features for result
#载入候选图像的特征
for ndx in res_reg[1:]:
    locs,descr = sift.read_features_from_file(featlist[ndx])  # because 'ndx' is a rowid of the DB that starts at 1
    # get matches
    matches = sift.match(q_descr,descr)
    ind = matches.nonzero()[0]
    ind2 = matches[ind]
    tp = homography.make_homog(locs[:,:2].T)
    # compute homography, count inliers. if not enough matches return empty list
    try:
        H,inliers = homography.H_from_ransac(fp[:,ind],tp[:,ind2],model,match_theshold=4)
    except:
        inliers = []
    # store inlier count
    rank[ndx] = len(inliers)
# sort dictionary to get the most inliers first
sorted_rank = sorted(rank.items(), key=lambda t: t[1], reverse=True)
res_geom = [res_reg[0]]+[s[0] for s in sorted_rank]
print ('top matches (homography):', res_geom)
# 显示查询结果
imagesearch.plot_results(src,res_reg[:5]) #常规查询
imagesearch.plot_results(src,res_geom[:5]) #重排后的结果

运行结果:第一张图片为检索图片,后四张是匹配到的图片(按照匹配效果好到坏排序)
常规查询结果:
在这里插入图片描述
重排后的查询结果:
在这里插入图片描述


四、总结

建立图像数据库,对图像进行索引就是从这些图像中提取描述子,利用词汇将描述子转换成视觉单词,并保存视觉单词及对应图像的单词直方图,从而可以利用图像对数据库进行查询,并返回相似的图像作为搜索结果。

如果图像数据库很大,逐一比较整个数据库中的所有直方图往往是不可行的,我们需要找到一个大小合理的候选集(这里的“合理”是通过搜索响应时间、所需内存等确定的),单词索引的作用便在于此:我们可以利用单词索引获得候选集,然后只需在候选集上进行逐一比较。

利用一些考虑到特征几何关系的准则重排搜索到的靠前结果,可以提高准确率。最常用的方法是在查询图像与靠前图像的特征位置间拟合单应性。为了提高效率,可以将特征位置存储在数据库中,并有特征的单词id决定它们之间的关联,要注意的是,只有在词汇足够大,使单词id包含很多准确匹配时,它才起作用。

在倒排表中,视觉单词包含的图像集合元素多,而且视觉单词数量多,因而在最后形成的直方图中,与其完全不相关的图像会因为视觉单词重合度大,而被排在前面,造成了输入和检测出的结果有偏差。

实验出现出现偏差的根本原因是数据库图像数目不够多,因而类间差距不够大,类内联系不够紧密,如果扩大图像库规模,会效果更好。

Bow模型的一个主要缺点是:在用视觉单词表示图像时,不包含图像特征的位置信息,这是为获取速度和可伸缩性而付出的代价。

  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值