图像检索:Bag of features

1、原理

1.1 Bag of Words 表示模型

Bag of features是从文本挖掘的矢量空间模型(即 Bag of Words 表示模型)中获取的灵感,因此这里先讲矢量空间模型。

矢量空间模型是一个用于表示和搜索文本文档的模型。它基本上可以应用于任何对象类型,包括图像。该名字来源于用矢量来表示文本文档,这些矢量是由文本词频直方图构成的。换句话说,矢量包含了每个单词出现的次数,而且在其他别的地方包含很多 0 元素。由于其忽略了单词出现的顺序及位置,该模型也被称为 BOW 表示模型。

通常,在单词计数时会忽略掉一些常用词,如“这”“和”“是”等,这些常用词称为停用词。由于每篇文档长度不同,故除以直方图总和将向量归一化成单位长度。对于直方图向量中的每个元素,一般根据每个单词的重要性来赋予相应的权重。通常,数据集(或语料库)中一个单词的重要性与它在文档中出现的次数成正比,而与它在语料库中出现的次数成反比。
最常用的权重是 tf-idf(term frequency-inverse document frequency,词频 - 逆向文档频率 ),单词 w 在文档 d 中的词频是:
t f w , d = n w ∑ j n j tf_{w,d}=\frac{n_{w}}{\sum _{j}n_{j}} tfw,d=jnjnw
n w n_{w} nw 是单词w在文档d中出现的次数。为了归一化,将 n w n_{w} nw 除以整个文档中单词的总数。

逆向文档频率为:
i d f w , d = l o g ∣ ( D ) ∣ { d : w ϵ d } idf_{w,d}=log\frac{\left | (D) \right |}{\{d:w\epsilon d\}} idfw,d=log{d:wϵd}(D)
∣ D ∣ \left | D \right | D 是在语料库 D 中文档的数目,分母是语料库中包含单词 w 的文档数 d。将两者相乘可以得到矢量 v 中对应元素的 tf-idf 权重。

1.2 Bag of features

将Bag of Words技术应用到图像中,即为Bag of features。

1.2.1 视觉单词

通常采用 SIFT 局部描述子建立视觉等效单词。它的思想是将描述子空间量化成一些典型实例,并将图像中的每个描述子指派到其中的某个实例中。这些典型实例可以通过分析训练图像集确定,并被视为视觉单词。所有这些视觉单词构成的集合称为视觉词汇,有时也称为视觉码本。对于给定的问题、图像类型,或在通常情况下仅需呈现视觉内容,可以创建特定的词汇。

从一个(很大的训练图像)集提取特征描述子,利用一些聚类算法可以构建出视觉单词。聚类算法中最常用的是 K-means。视觉单词并不高端,只是在给定特征描述子空间中的一组向量集,在采用 K-means 进行聚类时得到的视觉单词是聚类质心。

1.2.2 创建词汇

首先使用SIFT 特征描述子提取特征描述子,再在训练图像数据集上训练出一个词汇。

1.2.3 图像索引

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

可以使用 SQLite 作为数据库。SQLite 将所有信息都保存到一个文件,是一个易于安装和使用的数据库。SQLite 使用 SQL 查询语言,所以如果想用别的数据库,这个转换过程非常简单。

有了数据库表单,我们便可以在索引中添加图像。建立好图像的索引,我们就可以在数据库中搜索相似的图像了。用 BoW(Bag-of-Word,词袋模型)来表示整个图像,不过这里介绍的过程是通用的,可以应用于寻找相似的物体、相似的脸、相似的颜色等,它完全取决于图像及所用的描述子。

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

1.2.4 利用索引获取候选图像

可以利用建立起来的索引找到包含特定单词的所有图像,这不过是对数据库做一次简单的查询。例如一个单词直方图中的全部非零元素,我们在每个单词上进行遍历,得到包含该单词的图像,并合并这些列表;如果不想使用所有单词,你可以根据其倒排文档频率权重进行排序,并使用那些权重最高的单词。

此外,可以取出该列表中任意数量的元素并比较它们的直方图。你将会看到,这可以极大地提高检索效率。

2、Python实现

2.1 数据集

在这里插入图片描述
上图中的.sift文件是在实验过程中产生的。

2.2 代码

2.2.1 创建词汇并保存

# -*- coding: utf-8 -*-
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift

#获取图像列表
imlist = get_imlist('F:\\PycharmProjects\\Test\\ch07_ImageSearch\\data7\\')
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('F:\\PycharmProjects\\Test\\ch07_ImageSearch\\data7\\vocabulary.pkl', 'wb') as f:
    pickle.dump(voc, f)#将生成的词汇保存到vocabulary.pkl(f)中
print ('vocabulary is:', voc.name, voc.nbr_words)

2.2.2 添加图像并创建图像索引

# -*- coding: utf-8 -*-
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('F:\\PycharmProjects\\Test\\ch07_ImageSearch\\data7\\')
nbr_images = len(imlist)

#获取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]

#载入词汇
with open('F:\\PycharmProjects\\Test\\ch07_ImageSearch\\data7\\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())

2.2.3 检索

# -*- 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

#载入图像列表
imlist = get_imlist('F:\\PycharmProjects\\Test\\ch07_ImageSearch\\data7\\')
nbr_images = len(imlist)

#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]

#载入词汇
with open('F:\\PycharmProjects\\Test\\ch07_ImageSearch\\data7\\vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)
src = imagesearch.Searcher('testImaAdd.db',voc)

#查询图像索引和查询返回的图像数
q_ind = 42
nbr_results = 10

# 常规查询(按欧式距离对结果排序)
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]) #重排后的结果

2.3 运行结果

输入图片:
在这里插入图片描述
(1)K=50时:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)K=100时:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
(3)K=200时:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(4)K=500时:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
分析:第一张是常规的图,第二张是重排后的图,第三张是两种情况下的匹配度最高的前10张照片的索引。

2.4 小结

  • 生成特征sift时间较慢,查询结果可以接受。
  • K相同时,常规和重排后的结果相等。这说明在K位于50~500范围之间,重排对于匹配没有影响。
  • K不同时,运行结果也不同,但观察可发现:每种K值取得的结果(每种10个索引),总的只有12种不同的索引。这说明,在K位于50~500范围之间,结果的波动并不大。
  • 维度K越大匹配越精确。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值