目录
2. 学习 “视觉词典(visual vocabulary)” (k-means)
4. 把输入图像,根据TF-IDF转化成视觉单词( visual words)的频率直方图
BOW简介
Bag of words,也叫做“词袋”,在信息检索中,Bag of words model假定对于一个文本,忽略其词序和语法,句法,将其仅仅看做是一个词集合,或者说是词的一个组合,文本中每个词的出现都是独立的,不依赖于其他词 是否出现,或者说当这篇文章的作者在任意一个位置选择一个词汇都不受前面句子的影响而独立选择的。
基于BOW的图像检索流程
- 1. 特征提取
- 2. 学习 “视觉词典(visual vocabulary)”
- 3. 针对输入特征集,根据视觉词典进行量化
- 4. 把输入图像,根据TF-IDF转化成视觉单词( visual words)的频率直方图
- 5. 构造特征到图像的倒排表,通过倒排表快速 索引相关图像
- 6. 根据索引结果进行直方图匹配
1. 特征提取 (SIFT)
过分割、密集或随机采集、关键点或稳定区域、显著区域等方式使图像形成不同的图像块,并获得各图像块处的特征。
特征必须具有较高的区分度,而且要满足旋转不变性以及尺寸不变性等,通常采用SIFT特征(也可以采用SUFT、Harrist等特征提取算法 )。SIFT会从图片上提取出很多特征点,每个特征点都是具有鲁棒性的128维向量,如果图片足够多的话,我们会提取出一个巨大的特征向量库。
2. 学习 “视觉词典(visual vocabulary)” (k-means)
在上面提取完SIFT特征的步骤后,利用K-means聚类算法将提取的SIFT特征聚类生成视觉词典。
K-means算法是度量样本间相似性的一种方法,该算法设置参数为K,把N个对象分成K个簇,簇内之间的相似度较高,而簇间的相似度较低。聚类中心有K个,视觉词典为K。构建视觉单词的过程如图所示。
提取完特征后,我们会采用一些 聚类算法对这些特征向量进行聚类。 最常用的聚类算法是k-means。
至于k-means中的k如何取,要根据具体情况来确定。另外,由于特征的数量可能非常庞大,这个聚类的过程也会非常漫长。聚类完成后,我们就得到了这k个向量组成的字曲,这k个向量有一个通 用的表达,叫visual word.
3. 针对输入特征集,根据视觉词典进行量化
就是对于输入特征集,量化的过程是将该特征映射到距离其最接近的 codevector ,并实现计数
4. 把输入图像,根据TF-IDF转化成视觉单词( visual words)的频率直方图
TF-IDF(Term frequency-Inverse document frequency)是一种统计方法,用来评估特征词的重要程度。根据TF-IDF公式,特征词的权重与在 语料库中出现的频率有关,也与在文档里出现的频率有关。传统的TF-IDF公式如下:
TF-IDF用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。字词的重要性随着它在文件中出现的次数成正比增加,但同时会随着它在语料库中出现的频率成反比下降。就目前来说,如果一个 关键词只在很少的网页中出现,我们通过它就 容易锁定搜索目标,它的 权重也就应该 大。反之如果一个词在大量网页中出现,我们看到它仍然 不是很清楚要找什么内容,因此它应该 小。
利用视觉词典中的词汇表示待分类图像。计算每幅图像中的SIFT特征到这K个视觉单词的距离,其中 距离最近的视觉单词为该SIFT特征对应的视觉单词。通过统计每个单词在图像中出现的次数,将图像表示成一个K维数值向量,
5. 构造特征到图像的倒排表,通过倒排表快速索引相关图像
倒排索引(英语:Inverted index),也常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。它是文档检索系统中最常用的数据结构。
举例说明倒排表:
文档1:what is it?
文档2:it is a banana.
则有
“what”: {1} 表示"what"出现在文档1中
“is”: {1,2} 表示"is“出现在文档1和文档2中
“it”: {1,2}
“a”: {2}
“banana”: {2}
经过倒排后,就是视觉单词:[视觉单词所出现的图像集合]。倒排表可以快速使用反转文件来计算新图像与数据库中所有图像之间的相似性,仅考虑其分档与查询图像重叠的数据库图像,大大减少了匹配次数,优化了算法。
6. 根据索引结果进行直方图匹配
代码实现
数据集准备
准备了五组不同的花的照片,每组20张
荷花
玫瑰 菊花
桃花
牵牛花
创建词汇
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift
#获取图像列表
imlist = get_imlist("D:\\flower")
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('D:\\study\\计算机视觉\\code\\code5\\image\\vocabulary.pkl', 'wb') as f:
pickle.dump(voc, f)#将生成的词汇保存到vocabulary.pkl(f)中
print ('vocabulary is:', voc.name, voc.nbr_words)
生成数据集的sift特征文件和词汇文件
创建索引
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("D:\\flower")
nbr_images = len(imlist)
#获取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
#载入词汇
with open('D:\\study\\计算机视觉\\code\\code5\\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)[:110]:
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())
运行生成数据库
索引测试
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('D:\\flower')
nbr_images = len(imlist)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
#载入词汇
with open('D:\\flower\\vocabulary.pkl', 'rb') as f:
voc = pickle.load(f)
src = imagesearch.Searcher('testImaAdd.db',voc)
#查询图像索引和查询返回的图像数
q_ind = 1
nbr_results = 5
# 常规查询(按欧式距离对结果排序)
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]) #重排后的结果
运行结果
检索的图像:
检索结果(按照匹配效果好到坏排序):
检索的图像:
检索结果(按照匹配效果好到坏排序):
总结
1.本次的图像查询我是建立在原本的图像库里面取出的查询图像和图像匹配,而我觉得我应该深一步做到的是,输入自己的照片(非图像库内图像),然后再与图像库图像进行查询和匹配。
2.本次我的图像集其实并不多,就是30多张,都是取自于自己的手机相册,BOF的一个主要缺点是在用视觉单词表示图像时不包含图像特征的位置信息,而图像特征的位置信息在人眼识别图像时起到了很好的作用,而我本次的实验结果并没有体现出这个缺点。
3.由于图像集数目不足和通用数据库的影响其实我的聚类影响并没有体现出现,在我自己的通用数据库基础上,我应该增加每个类别的图像数量,感觉最好一个类别20-30张最佳,然后再设置一个专用的数据库(即对于同一个对象)也是有充足的图像数量,以此来进行聚类影响的体现。