【计算机视觉】基于BOW的图像检索

一、图像检索概述

简单的说便是从图片检索数据库中检索出满足条件的图片,图像检索技术的研究根据描述图像内容方式的不同可以分为两类:一类是基于文本的图像检索技术,一类为基于内容的图像检索技术。它最早用于对于文章内容的检索,原理是将文本看作是单词的集合,不考虑其中的语法,上下文等等。通过建立词典,对每个单词出现次数进行统计,以便得到文本内容的分类。计算机视觉的专家从中获得灵感,将其用于图像的检索中,就有了Bag Of Features。BOW(Bag of Feature)是一种图像特征提取方法,它借鉴了文本分类的思路(Bag of Words),从图像抽象出很多具有代表性的「关键词」,形成一个字典,再统计每张图片中出现的「关键词」数量,得到图片的特征向量。

二、Bag of Feature 算法

Bag-of-Features模型仿照文本检索领域的Bag-of-Words方法,把每幅图像描述为一个局部区域/关键点(Patches/Key Points)特征的无序集合。使用某种聚类算法(如K-means)将局部特征进行聚类,每个聚类中心被看作是词典中的一个视觉词汇(Visual Word),相当于文本检索中的词,视觉词汇由聚类中心对应特征形成的码字(code word)来表示(可看当为一种特征量化过程)。所有视觉词汇形成一个视觉词典(Visual Vocabulary),对应一个码书(code book),即码字的集合,词典中所含词的个数反映了词典的大小。图像中的每个特征都将被映射到视觉词典的某个词上,这种映射可以通过计算特征间的距离去实现,然后统计每个视觉词的出现与否或次数,图像可描述为一个维数相同的直方图向量,即Bag-of-Features。
总结来看,这种方式将文本表示成特征矢量。它的基本思想是假定对于一个文本,忽略其词序和语法、句法,仅仅将其看做是一些词汇的集合,而文本中的每个词汇都是独立的。
我们需要找到图像的特征,类似于词汇作为文本的特征,而这种特征必须得对光照,图片的是否旋转,图片畸变等不敏感,而sift特征提取能够较好的满足上述要求,因此,我们使用sift特征提取的方法形成一个词汇。
通过单词计数来构建文档直方图向量v,从而建立文档索引。通常,在单词计数时会忽略掉一些常用词,如 “这” “和” “是” 等,这些常用词称为停用词。由于每篇文档长度不同,因此除以直方图总和将向量归一化成单位长度。对于直方图向量中的每个元素,一般根据每个单词的重要性来赋予相应的权重。通常,数据集(或语料库)中一个单词的重要性与它在文档中出现的次数成正比,而与它在语料库中出现的次数成反比。
最常用的是权重是tf-idf(tern frequency-inverse document frequency,词频-逆向文档频率)
【计算机视觉】基于BOW的图像检索_第1张图片
在这里插入图片描述
则,逆向文件频率:
【计算机视觉】基于BOW的图像检索_第2张图片
在这里插入图片描述

三、图像检索流程

1.特征提取
2.学习 “视觉词典(visual vocabulary)”
3.针对输入特征集,根据视觉词典进行量化
4.把输入图像转化成视觉单词(visual words)的频率直方图
5.构造特征到图像的倒排表,通过倒排表快速索引相关图像
6.根据索引结果进行直方图匹配

特征提取

特征提取通常使用 SIFT局部描述子技术。视觉单词流程类似。
【计算机视觉】基于BOW的图像检索_第3张图片

学习特征词典

当我们提取完图像特征后,便开始了学习特征词典,利用一些聚类算法可以构建出视觉单词,最常用的是K−means算法。

K−means 算法
算法流程
1.随机初始化 K 个聚类中心;
2.重复下述步骤直至算法收敛:
对应每个特征,根据距离关系赋值给某个中心/类别;
对每个类别,根据其对应的特征集重新计算聚类中心。
【计算机视觉】基于BOW的图像检索_第4张图片

聚类后,就得到了这k 个向量组成的词典,称为visual words(视觉单词)。所有这些视觉单词构成的集合称为视觉词汇。

对输入特征集进行量化

对于图像中的每一个SIFT特征,都可以在字典中找到一个最相似的visual word,这样,我们可以统计一个k维的直方图,代表该图像的SIFT特征在字典中的相似度频率。统计出最相似的向量出现的次数,最后得到这幅图片的直方图向量。

【计算机视觉】基于BOW的图像检索_第5张图片

索引倒排表

通过TF-IDF过滤掉常见的词语,保留重要的词语后,我们便可以建立倒排索引表。
倒排索引表是一种逆向的索引方法,构造倒排表可以快速索引图像。倒排索引,通过搜索要查询的关键字,查询到跟该关键字相关的所有文档。倒排表可以获得是各视觉单词出现在图像库的哪些图像中。

直方图匹配

最后,根据索引的结果进行直方图匹配,就完成了图像索引。
【计算机视觉】基于BOW的图像检索_第6张图片

四、实验过程

1.收集数据集

本次实验准备了30张水果蔬菜类型的图片集。
【计算机视觉】基于BOW的图像检索_第7张图片

2.提取SIFT特征、生成视觉词典

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


#获取图像列表
imlist = get_imlist('./fruits/')
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, 30, 10) # 使用k-means算法在featurelist里边训练处一个词汇
#保存词汇
# saving vocabulary
with open('./BOW/vocabulary.pkl', 'wb') as f:
    pickle.dump(voc, f)
print ('vocabulary is:', voc.name, voc.nbr_words)

3.视觉词典进行量化生成数据库

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('./fruits/')
nbr_images = len(imlist)
#获取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]

# load vocabulary
#载入词汇
with open('./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)[:888]:
    print(featlist[i])
    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.图像检索

# -*- coding: utf-8 -*- 
#使用视觉单词表示图像时不包含图像特征的位置信息
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
#载入图像列表
imlist = get_imlist('./fruits/')
nbr_images = len(imlist)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]

#载入词汇
with open('./BOW/vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)

src = imagesearch.Searcher('testImaAdd.db',voc)# Searcher类读入图像的单词直方图执行查询

# index of query image and number of results to return
#查询图像索引和查询返回的图像数
q_ind = 4
nbr_results = 2

# regular query
# 常规查询(按欧式距离对结果排序)

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:]:
    try:
        locs, descr = sift.read_features_from_file(featlist[ndx])
    except:
        continue
    # 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[:6]) #常规查询
imagesearch.plot_results(src,res_geom[:6]) #重排后的结果

5、实验结果及分析

【计算机视觉】基于BOW的图像检索_第8张图片

【计算机视觉】基于BOW的图像检索_第9张图片
【计算机视觉】基于BOW的图像检索_第10张图片

【计算机视觉】基于BOW的图像检索_第11张图片

【计算机视觉】基于BOW的图像检索_第12张图片

五、实验总结

1、原先使用自己拍摄的图片数据集的时候,图片太大,生成sift特征平均每张图要运行2到3分钟左右,因此采用了网上搜索到的图片集进行实验。图片集每5张图片相似,6组共30张。图片像素为100×100,运行速度明显变快。
2、运行结果来看,BOW图像检索的效果相对较好,前四张为相似图片。
3、仍存在某些劣势:
a、Kmeans聚类时间长
b、词袋表的量化的过程,损失了匹配精度(本实验中采用网上的图,匹配效果相对较好)

你可能感兴趣的:(计算机视觉,计算机视觉,聚类,算法)