热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python计算机视觉基于BOW模型的图像检索

文章目录原理解析1.BOW模型2.基于BOW的图像检索2.1.用SIFT算法进行特征提取2.2用K-means得出视觉词典2.3.针对输入的特征集,根据视觉词典进行量

文章目录

  • 原理解析
    • 1.BOW模型
    • 2.基于BOW的图像检索
      • 2.1.用SIFT算法进行特征提取
      • 2.2用K-means得出视觉词典
      • 2.3.针对输入的特征集,根据视觉词典进行量化
      • 2.4.把输入图像转化成视觉单词(visual words)的频率直方图
      • 2.5.构造特征到图像的倒排表,通过倒排表快速索引相关图像
      • 2.6.根据索引结果进行直方图匹配
  • 相关代码
    • 1.特征提取和学习“视觉词典”
    • 2.创建索引,建立数据库
    • 3 利用索引在数据库中搜索图像
    • 实验结果
    • 总结
  • 附 期末复习整理资料
    • sift harris
    • 全景拼接
    • 相机标定
    • bow
    • 图像分割




原理解析

1.BOW模型

BOW其实是Bag of words的缩写,也叫做词袋。BOW模型最早出现在自然语言处理和文本检索领域。该模型忽略掉文本的语法、语序等要素,吧文档看做若干词汇的集合,文档中的单词是独立出现的,使用一组无序的单词(words)表达一个文档,根据文档中单词的统计信息完成对文本的分类。

比如,有如下两个文档:

1:Bob likes to play basketball, Jim likes too.2:Bob also likes to play football games.

根据这两个文档,我们可以构造一个词典:

Dictionary = {1:”Bob”, 2. “like”, 3. “to”, 4. “play”, 5. “basketball”, 6. “also”, 7. “football”, 8. “games”, 9. “Jim”, 10. “too”}。

这个词典中包含10个不同的单词,利用单词的索引号,我们可以将上面的每个文档都用一个10维向量表示(用0~n表示某个单词在文档中出现的次数,其中n为正整数):

1:[1, 2, 1, 1, 1, 0, 0, 0, 1, 1]2:[1, 1, 1, 1 ,0, 1, 1, 1, 0, 0]

该向量的维度是单词的个数,值是每个单词在文本中出现的频率。以上的向量也可以用单词的直方图表示,词表相当于直方图的基,要表述的是文档向这个基上映射。

并非所有的单词都用来构建词表,相似的单词用一个单词表示。例如“walk, walking,walks” 都用 “walk” 表示。一个单词如果在所有文档中出现,比如is,a,an等词,那么个单词其实对区分文档就没有那么重要了。反之,如果一个单词只在一个文档值出现,那么只要输入的文档有这个单词,那么一定是属于这个单词所在的文档,就是唯一的,这对于区分文档非常重要。单词对区分文档的重要性通过计算单词TF-IDF(term frequency–inverse document frequency, 词频-逆向文档频率)实现。

单词w在文档d中出现的词频是:
在这里插入图片描述
n_w是单词w在文档d中出现的次数。为了归一化,将n_w除以整个文档中单词的总数。

逆向文档频率为:
在这里插入图片描述
|D|是在语料库D中的文档数目,分母是语料库中包含单词w在文档数d
就是单词w的TF-IDF权重了,用这个来表示单词对区分文档的重要性。因为有时候the、a这种的就很不重要。

BOW模型用于文本分类包括词表的建立、样本训练、新来样本识别三个步骤。

2.基于BOW的图像检索

对于两张图片,我们可以利用sift算法来进行特征匹配。但是面对大规模图像特征匹配,我们不可能一个个特征匹配,因为这样计算量是在过于庞大。比如,25000张图像约有310亿个图相对,即使每个图匹配只需要两秒,也需要500台并行计算机工作一年才可以完成,所以我们不能使用这种一个个特征匹配的暴力匹配法,需要寻找其他更快速有效的方法。

我们发现,面对大场景数据集,其实只有少于0.1%的图像具有匹配关系,所以我们可用图像整体特征实现匹配/检索,而非局部特征点。所以,我们找到那个快速有效的方法——BOW模型。将BOW模型应用于图像领域,即把图像视为与位置无关的局部特征集合,局部特征就相当于文本中的单词,称为“视觉单词”,视觉单词的集合称为“视觉词典”(也叫码本)。

图像检索的基本流程是:

①特征提取(SIFT算法)

②学习“视觉词典(visual vocabulary)”(k-means算法)

③针对输入的特征集,根据视觉词典进行量化

④把输入图像转化成视觉单词(visual words)的频率直方图

⑤构造特征到图像的倒排表,通过倒排表快速索引相关图像

⑥根据索引结果进行直方图匹配

2.1.用SIFT算法进行特征提取

特征提取就是从图像中提取出关键点(或特征点、角点)等,我们在这里采用的SIFT算法。SIFT算法用来侦测与描述影像中的局部特征,它在空间尺度中寻找极值点,并提取出其位置、尺度、旋转不变量。此算法由David Lowe 在1999 年所发表,2004 年完善总结。SIFT 算法的实质是在不同的尺度空间上查找关键点( 特征点),并计算出关键点的方向。SIFT 所查找到的关键点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。SIFT 算法在构建好的尺度空间的基础上搜索尺度空间中的极值点( 特征点),然后确定极值点的尺度信息以及位置,再确定极值点的方向( 其邻域梯度的主方向),最终可以得到具有鲁棒性的128 维(448) 的特征向量。
利用SIFT算法提取出训练图片的示意图如下:
在这里插入图片描述
在这里插入图片描述
举个例子,假如现在有3 张训练图片:人脸、自行车、小提琴,如下图所示:
在这里插入图片描述
对每一张训练图片都提取SIFT 的128 维特征,那么最终可以得到 M = N1+N2+N3 个128 维的特征,Ni 代表第i 张图特征点的个数,如下图所示:

在这里插入图片描述

2.2用K-means得出视觉词典

前面已经说过了,面对大场景数据集,只凭特征匹配,由于计算时间过长,是不可能实现图像检索的。所以我们想到了将相似的特征向量聚到一起,用一个视觉单词来表示这些特征,就像文本中用“walk”来表示“walk, walking,walks” 一样。我们采用的算法是K-means算法。

k-means算法是一种基于样本间相似性度量的间接聚类方法,属于非监督学习方法。

输入:聚类个数k,图像的特征集合。输出:满足方差最小标准的k个聚类。

在这里插入图片描述
k-means算法的流程示意图如下:

在这里插入图片描述
k-means算法是实现视觉词典(码本)的关键,我们将K-means 算法获取的聚类中心作为视觉单词(码本向量)。当训练集准备足够充分是,训练出的码本将具有普适性。

需要注意的是如何选择视觉词典/码本的规模,太少会出现视觉单词无法覆盖所有可能出现的情况;太多又会计算量大,容易过拟合。

就之前的例子而言就是将下述这特征向量进行聚类,将之前的特征向量转化为4个视觉单词,以此来作为视觉词典。
在这里插入图片描述

2.3.针对输入的特征集,根据视觉词典进行量化

对于文本而言,当一个单词在所有文本都出现那么这个单词就不能区分文本。同理,如果一个视觉单词在每个图像中都出现,那么这个视觉单词就不能区分图像了。类比文本,我们这里也采用TF-IDF权重来表示视觉单词对区分图像的重要程度。

2.4.把输入图像转化成视觉单词(visual words)的频率直方图

统计词表中每个单词在图像中出现的次数,将图像表示为K 维数值向量。上例中,可以将图像表示成为一个K=4 维数值向量:

人脸:[3,30,3,20]

自行车:[20,3,3,2]

小提琴:[8,12,32,7]
每幅图的视觉单词与词频直方图如图下图所示:

在这里插入图片描述

2.5.构造特征到图像的倒排表,通过倒排表快速索引相关图像

前几步是通过图像来提取视觉单词,用视觉单词的词频直方图来表示图像,是通过图像映射视觉单词。而倒排表是通过视觉单词映射图像。

比如,对于下述两个文本而言:

1:Bob likes to play basketball, Jim likes too.2:Bob also likes to play football games.

之前是:

1:[ “Jim”, “too”]2:[“also”, “football”, “games”,]

经过倒排后是:

“Jim”:[1]“too”:[1]“also”:[2]“football”:[2]“games”:[2]

对于图像来说,经过倒排后,就是视觉单词:[视觉单词所出现的图像集合]。倒排表可以快速使用反转文件来计算新图像与数据库中所有图像之间的相似性,仅考虑其分档与查询图像重叠的数据库图像,大大减少了匹配次数,优化了算法。

2.6.根据索引结果进行直方图匹配

根据索引结果建立直方图,就可以得出最后的匹配结果了。

相关代码

1.特征提取和学习“视觉词典”

import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift# 获取图像列表
imlist = get_imlist('datasets/')
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, 122, 10)# 保存词汇
with open('BOW/vocabulary.pkl', 'wb') as f:pickle.dump(voc, f)
print('vocabulary is:', voc.name, voc.nbr_words)

运行结果:

生成对应的sift文件:
在这里插入图片描述
构造词典:
在这里插入图片描述

2.创建索引,建立数据库

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('datasets/')
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)# 创建索引
indx = imagesearch.Indexer('testImaAdd.db', voc) # 在Indexer这个类中创建表、索引,将图像数据写入数据库
indx.create_tables() # 创建表# 遍历所有的图像,并将它们的特征投影到词汇上
for i in range(nbr_images)[:888]:locs, descr = sift.read_features_from_file(featlist[i])indx.add_to_index(imlist[i], descr) # 使用add_to_index获取带有特征描述子的图像,投影到词汇上# 将图像的单词直方图编码存储# 提交到数据库
indx.db_commit()con = sqlite.connect('testImaAdd.db')
print(con.execute('select count (filename) from imlist').fetchone())
print(con.execute('select * from imlist').fetchone())

运行结果:
生成数据库:
在这里插入图片描述

3 利用索引在数据库中搜索图像

import pickle
from PCV.geometry import homography
from PCV.imagesearch import imagesearch
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift# 载入图像列表
# imlist = get_imlist('test/')
imlist = get_imlist('datasets/')
nbr_images = len(imlist)# 载入特征列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]
# print(imlist)
# print(featlist)# # 提取文件夹下图像的sift特征
# for i in range(nbr_images):
# sift.process_image(imlist[i], featlist[i])# 载入词汇
with open('BOW/vocabulary.pkl', 'rb') as f:voc = pickle.load(f)# Searcher类读入图像的单词直方图执行查询
src = imagesearch.Searcher('testImaAdd.db', voc)
# print(src)# 查询图像索引和查询返回的图像数
q_ind = 6
nbr_results = 5# 常规查询(按欧式距离对结果排序)
res = [w[1] for w in src.query(imlist[q_ind])[:nbr_results]]
imagesearch.plot_results(src,res)

这里我们用常规查询和优化查询进行对比。

实验结果

测试1:
在这里插入图片描述
在这里插入图片描述

测试2:
在这里插入图片描述
在这里插入图片描述
测试3:
在这里插入图片描述
在这里插入图片描述
测试4:
在这里插入图片描述
在这里插入图片描述

总结

从上面的测试结果来看,检索出的图片相似度还算挺高的,一般会匹配出轮廓或者颜色相近的图片。在图像特征比较明显,或者数据集中图片相似的很多(同一个物品不同角度的拍摄),则图像的匹配效果越好。
  但如果图像比较复杂或者没有明显的特点的话,就不能提取到比较重要的特征点,从而影响检索的效果。
  (以上是在用在原本数据集的基础上进行的检索测试,用数据集以外的图片测试还存在问题,暂时没有解决。)

附 期末复习整理资料

sift harris

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

全景拼接

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

相机标定

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

bow

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

图像分割

在这里插入图片描述

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


推荐阅读
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • importjava.util.ArrayList;publicclassPageIndex{privateintpageSize;每页要显示的行privateintpageNum ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 不同优化算法的比较分析及实验验证
    本文介绍了神经网络优化中常用的优化方法,包括学习率调整和梯度估计修正,并通过实验验证了不同优化算法的效果。实验结果表明,Adam算法在综合考虑学习率调整和梯度估计修正方面表现较好。该研究对于优化神经网络的训练过程具有指导意义。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了如何使用python从列表中删除所有的零,并将结果以列表形式输出,同时提供了示例格式。 ... [详细]
author-avatar
SaraCody_174
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有