文本挖掘技术
矢量空间模型是一个用于表示和搜索文本文档的模型,它基本上可以用于任何对象类型,包括图像。该名字来源于用矢量来表示文本文档,这些矢量是由文本词频直方图构成的,矢量包含了每个单词出现的次数。由于其忽略了单词出现的顺序及位置,该模型也被称为BOW(Bag-Of-Words)模型。
通过单词计数来构建文档直方图向量v,从而简历文档索引。对于直方图向量中的每个元素,一般根据每个单词的重要性来赋予相应的权重。通常,数据集中一个单词的重要性和它在文档中出现的次数成正比,而与它在语料库中出现的次数成反比。
最常用的权重是tf-idf(term frequency-inverse document frequency,词频-逆向文档频率)
视觉单词
为了将文本挖掘技术应用到图像中,我们首先要建立视觉等效单词,这通常可以用SIFT做到。它的思想是将描述子空间量化成一些典型实例,并将图像中的每个描述子指派到其中的某个实例中。这些典型实例可以通过分析训练图像集确定,并被视为视觉单词,视觉单词的集合称为视觉词汇。
BoF(Bag Of Feature)借鉴文本处理的词袋(BoW,Bag Of Bag)算法,将图像表示成视觉关键词的统计直方图。
从一个很大的图像训练集中提取特征描述子,利用一些聚类算法可以构建出视觉单词,在这里采用最常用的K-means。
创建词汇
特征提取
为创建视觉单词词汇,首先需要提取特征描述子,采用SIFT特征描述子。
学习“视觉字典”
采用K-means来对这些向量进行聚类,聚类后得到这k个向量组成的视觉词典。
视觉词典的量化
对于图像中的每一个SIFT特征,可以找到一个最相似的视觉单词,这样,我们可以统计一个k维的直方图来代表该图像的ISFT特征在字典中的相似度频率
依据tf-idf生成频率直方图
依据BOW中单词的重要性不一致,可见图像中特征的重要性也不一样,应该降低每张图片都具有的共性特征的权重。
代码实现
数据集
duck、雨伞、鞋子、鸡
代码
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift
#获取图像列表
imlist = get_imlist(r'C:\Users\lenovo\Desktop\Code-resource\ImageSet')
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(r'C:\Users\lenovo\Desktop\Code-resource\ImageSet\vocabulary.pkl', 'wb') as f:
pickle.dump(voc, f)#将生成的词汇保存到vocabulary.pkl(f)中
print ('vocabulary is:', voc.name, voc.nbr_words)
运行之后生成了.sift文件和.pkl文件
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(r'C:\Users\lenovo\Desktop\Code-resource\ImageSet')
nbr_images = len(imlist)
#获取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
#载入词汇
with open(r'C:\Users\lenovo\Desktop\Code-resource\ImageSet\vocabulary.pkl', 'rb') as f:
voc = pickle.load(f)
#创建索引
indx = imagesearch.Indexer('testImaAdd1.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('testImaAdd1.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(r'C:\Users\lenovo\Desktop\Code-resource\ImageSet')
nbr_images = len(imlist)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
#载入词汇
with open(r'C:\Users\lenovo\Desktop\Code-resource\ImageSet\vocabulary.pkl', 'rb') as f:
voc = pickle.load(f)
src = imagesearch.Searcher('testImaAdd1.db',voc)
#查询图像索引和查询返回的图像数
q_ind = 47
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]) #重排后的结果
检索测试后匹配结果偶有偏差,但大体上能匹配正确
错匹配出现的情况很多,譬如鸡匹配鞋,雨伞匹配duck……
鸡匹配鞋我还能稍稍理解,毕竟鞋子的纹路和鸡的羽毛的特征相近,至于雨伞匹配duck嘛……留后再议。