计算机视觉课后作业6——图像检索
图像检索
1.实验目的:
从内容检索CBIR。外部给定一张图片,能够从内部数据库中找到相似的数张图片。
2.实验原理:
图像检索过程:查询图像输入——>预处理(尺寸归一化)(图像数据库)——>特征提取(图像特征库)——>特征欧氏距离——>相似性搜索——>得到结果
图像检索的本质是特征提取和相似度计算的过程。
关键问题1.怎么抽取图像众多像素点中的有效特征?
2.如何进行相似度计算?
我们要提取局部特征而非全局特征,主要是以下原因:
图像局部特征:角点,关键点,N*128维,N为关键点数,针对不同图像可能提取到不同特征个数,SIFT算法,尺度不变性,转换角度特征不变
全局特征:整体,512维
局部特征优于全局特征
图像局部特征进行相似点计算,利用局部特征点的匹配个数,越多越相似,匹配繁杂,次数非常大,所以我们考虑聚类分析,构建词袋模型
词袋模型:提取所有图片的sift特征(全部是向量),统计在一起得到N*128维的矩阵,对该矩阵进行聚类(合并相近特征),得到的聚类矩阵(分为几类)的聚类中心就类似我们做文字统计的单词空间(所有单词)——拿图像二次分类的矩阵来对应简单例子的一次汇总。
这边涉及到两个主要算法:
首先是特征提取——SIFT算法,遍历检测数据集图片的角点。
其次是聚类分析——K_means算法,对于得到的特征的向量矩阵进行分类,相似特征归为一类,以聚类中心代替该类向量描述,得到的N个聚类中心相当于词典中的“字母”,简化匹配流程,构成视觉词典模型。
3.实验思路:
1、构造一个数据集
2、sift算子提取特征点及描述符
3、采用k-means算法对特征点进行训练生成聚类中心
4、计算每个视觉单词的权重生成直方图
5、对于输入的检索图像计算sift特征生成直方图
6、构造检索图像到数据库图像的倒排表,针对候选图像集与检索图像进行匹配
4.具体实验:
1、构造数据集并生成.sift文件:
sift算法在之前的实验已经写过,主要是对于图片角点的检测。
if __name__ == '__main__': download_path = "C:/Users/oulia/Pictures/TXJS" path = "C:/Users/oulia/Pictures/TXJS" imlist = imtools.get_imlist(download_path) nbr_images = len(imlist) featlist = [imname[:-3] + 'sift' for imname in imlist] for i, imname in enumerate(imlist): sift.process_image(imname, featlist[i]) matchscores = zeros((nbr_images, nbr_images)) for i in range(nbr_images): for j in range(i, nbr_images): # only compute upper triangle print('comparing ', imlist[i], imlist[j]) l1, d1 = sift.read_features_from_file(featlist[i]) l2, d2 = sift.read_features_from_file(featlist[j]) matches = sift.match_twosided(d1, d2) nbr_matches = sum(matches > 0) print('number of matches = ', nbr_matches) matchscores[i, j] = nbr_matches # copy values for i in range(nbr_images): for j in range(i + 1, nbr_images): # no need to copy diagonal matchscores[j, i] = matchscores[i, j] # 可视化 threshold = 20 # min number of matches needed to create link 创建链接所需匹配的最小数量 g = pydot.Dot(graph_type='graph') # don't want the default directed graph for i in range(nbr_images): for j in range(i + 1, nbr_images): if matchscores[i, j] > threshold: # first image in pair im = Image.open(imlist[i]) im.thumbnail((100, 100)) filename = path + str(i) + '.jpg' im.save(filename) # need temporary files of the right size g.add_node(pydot.Node(str(i), fontcolor='transparent', shape='rectangle', image=filename)) # second image in pair im = Image.open(imlist[j]) im.thumbnail((100, 100)) filename = path + str(j) + '.jpg' im.save(filename) # need temporary files of the right size g.add_node(pydot.Node(str(j), fontcolor='transparent', shape='rectangle', image=filename)) g.add_edge(pydot.Edge(str(i), str(j)))
数据集以及运行结果
2、提取特征点并生成视觉词汇词典:
k_means算法 创建直方图 生成视觉词汇词典
import pickle from PCV.imagesearch import vocabulary from PCV.tools.imtools import get_imlist from PCV.localdescriptors import sift #获取图像列表 imlist = get_imlist('C:/Users/oulia/Pictures/TXJS/') nbr_images = len(imlist) #获取特征列表 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('ukbenchtest') voc.train(featlist, 18, 3) # 使用k-means算法在featurelist里边训练处一个词汇 # 注意这里使用了下采样的操作加快训练速度 # 将描述子投影到词汇上,以便创建直方图 #保存词汇 # saving vocabulary with open('C:/Users/oulia/PycharmProjects/untitled/BagOfFeature/BOW/vocabulary.pkl', 'wb') as f: pickle.dump(voc, f) print ('vocabulary is:', voc.name, voc.nbr_words)
运行截图:
生成码本:
3、遍历特征投影到词汇上存入数据库 建立数据库 testImaAdd
建立数据库:有了视觉单词和对应的直方图后,就可以保存为一个数据库,当需要检索的时候输入图像在数据库中进行查询,返回一个匹配的搜索结果。
import pickle from PCV.imagesearch import vocabulary from PCV.tools.imtools import get_imlist from PCV.localdescriptors import sift from PCV.imagesearch import imagesearch from PCV.geometry import homography from sqlite3 import dbapi2 as sqlite # 使用sqlite作为数据库 #获取图像列表 imlist = get_imlist('C:/Users/oulia/Pictures/TXJS/') nbr_images = len(imlist) #获取特征列表 featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)] # load vocabulary #载入词汇 with open('C:/Users/oulia/PycharmProjects/untitled/BagOfFeature/BOW/vocabulary.pkl', 'rb') as f: voc = pickle.load(f) #创建索引 indx = imagesearch.Indexer('testImaAdd.db',voc) # 在Indexer这个类中创建表、索引,将图像数据写入数据库 indx.create_tables() # 创建表 # go through all images, project features on vocabulary and insert #遍历所有的图像,并将它们的特征投影到词汇上 for i in range(nbr_images)[:18]: locs,descr = sift.read_features_from_file(featlist[i]) indx.add_to_index(imlist[i],descr) # 使用add_to_index获取带有特征描述子的图像,投影到词汇上 # 将图像的单词直方图编码存储 # commit to database #提交到数据库 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 # load image list and vocabulary #载入图像列表 from BagOfFeature.PCV.imagesearch import vocabulary imlist = get_imlist('C:/Users/oulia/Pictures/TXJS/') nbr_images = len(imlist) print(nbr_images) #载入特征列表 featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)] #载入词汇 with open('C:/Users/oulia/PycharmProjects/untitled/BagOfFeature/BOW/vocabulary.pkl', 'rb') as f: voc = pickle.load(f) src = imagesearch.Searcher('testImaAdd.db',voc) # index of query image and number of results to return #查询图像索引和查询返回的图像数 q_ind = 7 nbr_results = 5 # regular query # 常规查询(按欧式距离对结果排序) res_reg = [w[1] for w in src.query(imlist[q_ind])[:nbr_results]] print('top matches (regular):', res_reg) imagesearch.plot_results(src,res_reg[:5]) #常规查询
运行截图:
5.实验中遇到的问题:
实验要求外部输入图像进行数据库检索部分尚未实现,由于数据库图片数量的局限性,在聚类方面的划分还可以进一步优化。