一、原理

参考:BOF——Bag-of-Featrures

图像可以视为一种文档对象,图像中不同的局部区域或其特征可看做构成图像的词汇,其中相近的区域或其特征可以视作为一个词。这样,就能够把文本检索及分类的方法用到图像分类及检索中去。

Bag-of-Features模型仿照文本检索领域的Bag-of-Words方法,把每幅图像描述为一个局部区域/关键点(Patches/Key Points)特征的无序集合。使用某种聚类算法(如K-means)将局部特征进行聚类,每个聚类中心被看作是词典中的一个视觉词汇(Visual Word),相当于文本检索中的词,视觉词汇由聚类中心对应特征形成的码字(code word)来表示(可看当为一种特征量化过程,可理解为:码字表示聚类中心的特征矢量,如该类的平均矢量等)。所有视觉词汇形成一个视觉词典(Visual Vocabulary),对应一个码书(code book)(可理解为:码书是所有聚类中心特征矢量的集合),即码字的集合,词典中所含词的个数反映了词典的大小。

图像中的每个特征都将被映射到视觉词典的某个词上,这种映射可以通过计算特征间的距离去实现,然后统计每个视觉词的出现次数或频率,图像可描述为一个维数相同的直方图向量,即Bag-of-Features,如下图所示,可用直方图向量来表示或表达图像:

由上图可知,对同一词典,不同图像得到的直方图不同,因此可以用直方图向量来表示图像。

视觉词汇计算示意图:

理解:

1)视觉词汇的确定:

计算训练图像中所有图像的关键点和描述,然后在特征空间对关键点聚类,生成类心,每个类心为一个视觉词汇,类心的数目即视觉词典中视觉词汇的个数(训练和聚类过程与图像库中图像的种类无关,只是为了得到一个能表述所有图像特征的视觉词典,该过程类似文档分类中,对相同或相似词汇进行合并,得到一个单词字典)。

2)视觉词汇个数的影响:

视觉词汇的个数即视觉词典的大小,词典大小的选择也是问题,词典过大,单词缺乏一般性,对噪声敏感,计算量大,图象直方图向量的维数高;词典太小,单词区分性能差,对相似的目标特征无法表示。

3)词汇个数的确定问题:
    使用k-means聚类,除了其K和初始聚类中心选择的问题外,对于海量数据,输入矩阵的巨大将使得内存溢出及效率低下。有方法是在海量图片中抽取部分训练集分类,使用朴素贝叶斯分类的方法对图库中其余图片进行自动分类。另外,由于图片爬虫在不断更新后台图像集,重新聚类的代价显而易见。

二、算法步骤:

2.1、字典学习训练(train a codebook)

首先我们构造一个字典(也称visual vocabulary),方法如下:

1、特征提取(对所有的训练图像提取SIFT特征):利用SIFT等局部描述子(SIFT方法最为常用,OpponentSIFT在各类SIFT改进方式综合表现最为优秀)提取图像的特征点,这个过程一般会生成非常多的特征点。

2、特征聚类:由于一般提取的特征点实在太多(每张训练图片上都会提取到成千上万的特征点),不太适合分析和操作,所以一般会利用K-Means聚类等方法将所以特征点分成K类,这里每个类,我们就称为一个词(codeword/Visual Word),(对提取的所有图的SIFT特征使用kmeans算法得到k个聚类中心

K-means聚类算法流程:

  • 随机初始化 K 个聚类中心
  • 重复下述2个步骤直至算法收敛
    • (1)对应每个特征,根据距离关系赋值给某个中心/类别
    • (2)对每个类别,根据其对应的特征集重新计算聚类中心

3、形成字典:所有的类(词codeword/Visual Word)就构成字典(codebook/visual vocabulary)

2.2、图像特征集投影(这个过程也叫Feature Pooling)(量化)

对于每个输入图像的特征,根据视觉词典进行量化,量化的过程是将该特征映射到距离其最接近的视觉单词,并实现计数。这里要注意选择视觉词典的规模。太少:视觉单词无法覆盖所有可能出现的情况;太多:计算量大,容易过拟合。

(1)特征提取:利用SIFT提取每个训练图像中所有的特征点

(2)查找对应词:就是在字典中找每个特征点对应的词

(3)构成图像特征词表:将字典内每个词出现频率构成这个训练图像特征向量(显然是K维向量)(初步的无权BOF(直方图向量))

通过tf-idf对频数表加上权重,生成最终的bof。(因为每个类心对图像的影响不同。比如超市里条形码中的第一位总是6,它对辨别产品毫无作用,因此权重要减小)。

将每张训练图像的SIFT特征通过1.1(2)得到的kmeans模型K个聚类中心进行聚类,将每一张图像SIFT特征分为k个簇,即根据视觉词典进行量化,根据TF-IDF转化成视觉单词(visual words)的频率直方图)


给定输入图像的BOW直方图, 在数据库中查找 k 个最近邻的图像
对于图像分类问题,可以根据这k个近邻图像的分类标签,投票获得分类结果
当训练数据足以表述所有图像的时候,检索/分类效果良好

在Bag-of-Features方法的基础上,Andrew Zisserman进一步借鉴文本检索中TF-IDF模型(Term Frequency一Inverse Document Frequency)来计算Bag-of-Features特征向量。接下来便可以使用文本搜索引擎中的反向索引技术对图像建立索引,高效的进行图像检索。

说明:

1.TF-IDF是一种用于信息检索的常用加权技术,在文本检索中,用以评估词语对于一个文件数据库中的其中一份文件的重要程度。词语的重要性随着它在文件中出现的频率成正比增加,但同时会随着它在文件数据库中出现的频率成反比下降:

TF的主要思想是:如果某个关键词在一篇文章中出现的频率高,说明该词语能够表征文章的内容,该关键词在其它文章中很少出现,则认为此词语具有很好的类别区分度,对分类有很大的贡献。

IDF的主要思想是:如果文件数据库中包含词语A的文件越少,则IDF越大,则说明词语A具有很好的类别区分能力。
词频(Term Frequency,TF)指的是一个给定的词语在该文件中出现的次数。如:tf = 0.030 ( 3/100 )表示在包括100个词语的文档中, 词语'A'出现了3次。
逆文档频率(Inverse Document Frequency,IDF)是描述了某一个特定词语的普遍重要性,如果某词语在许多文档中都出现过,表明它对文档的区分力不强,则赋予较小的权重;反之亦然。如:idf = 13.287 ( log (10,000,000/1,000) )表示在总的10,000,000个文档中,有1,000个包含词语'A'。最终的TF-IDF权值为词频与逆文档频率的乘积。

2.3、分类:

现在每张图像我们都可以得到一个K维特征向量(反映了字典各词的出现频率),现在就是传统的分类问题了,最常用的方法是SVM:)

分类过程:对于待测图像,提取局部特征或关键点描述,计算待测图像特征与词典中每个码字(视觉词汇)的特征距离,即将每个特征都将被映射到视觉词典中点的某个词上,统计每个视觉词汇的频率,得到的直方图向量即为待测图像的Bag-of-Features特征;把待测图像特征输入分类器,判定其类别。如下图所示:

三、代码实现

参考 Bag of features 图像特征词典原理及实现_邓程维的博客-CSDN博客

3.1 生成视觉词典

# -*- coding: utf-8 -*-
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift
##要记得将PCV放置在对应的路径下
#获取图像列表
imlist = get_imlist('D:/Visual_Studio_Code/data/first1000/') ###要记得改成自己的路径
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, 1000, 10)
#保存词汇
# saving vocabulary
with open(r'D:\Visual_Studio_Code\data\first1000\vocabulary.pkl', 'wb') as f:pickle.dump(voc, f)
print ('vocabulary is:', voc.name, voc.nbr_words)

对应1000张图像生成了1000个sift文件,并且生成了视觉词典

3.2 导入数据库

在python\Lib文件夹之下可以看到一个sqlite3的包,说明python3自带数据库包,不需要安装pysqlite库,所以需要更改PCV\imagesearch中的imagesearch.py文件第三行为from sqlite3 import dbapi2 as sqlite

# -*- 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
##要记得将PCV放置在对应的路径下
#获取图像列表
imlist = get_imlist('D:/Visual_Studio_Code/data/first1000/')##记得改成自己的路径
nbr_images = len(imlist)
#获取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
# load vocabulary
#载入词汇
with open(r'D:\Visual_Studio_Code\data\first1000\vocabulary.pkl', 'rb') as f:voc = pickle.load(f)
#创建索引
indx = imagesearch.Indexer('testImaAdd.db',voc)
indx.create_tables()
# go through all images, project features on vocabulary and insert
#遍历所有的图像,并将它们的特征投影到词汇上
for i in range(nbr_images)[:1000]:locs,descr = sift.read_features_from_file(featlist[i])indx.add_to_index(imlist[i],descr)
# 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())

运行后发现在代码文件夹之下生成了一个数据库文件

3.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# load image list and vocabulary
#载入图像列表
imlist = get_imlist('first1000/')
nbr_images = len(imlist)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]#载入词汇
with open('first1000/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 = 0
nbr_results = 20# 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:]:locs,descr = sift.read_features_from_file(featlist[ndx])  # because 'ndx' is a rowid of the DB that starts at 1# get matchesmatches = 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 listtry:H,inliers = homography.H_from_ransac(fp[:,ind],tp[:,ind2],model,match_theshold=4)except:inliers = []# store inlier countrank[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[:8]) #常规查询
imagesearch.plot_results(src,res_geom[:8]) #重排后的结果

这里主要是对比两种查询方式:

  1. 常规查询
  2. 用单应性进行拟合建立RANSAC模型

在这一实验下两种方式的结果一致,都成功找到了和第一张图片内容一个类型的数据集:

四、特征袋分类的举例说明

对于一个的静态手势,可以看作是由多个视觉单词组成。例如需要对1、 2这两个不同的静态手势进行分类。那么首先需要知道1这个手势是由哪些单词组成,2这个手势由哪些单词组成,而这些单词用的是英文单词还是中文单词,这就需要构建视觉词典。构建完视觉词典后我们就开始对1这个这手势进行查字典,设字典只有26个字母,手势1一查1个O、1个N、一个E。手势2一查1个T、1个W、1个O。好的,现在我有两个类在这了。假如你搞一个手势和1比较相似的手势,我就按字母个数分布与哪个相似这个标准来分类判断。比如搞个手势由1个O、1个N、一个T组成,你看,有两个单词和1完全吻合,一个单词和2完全吻合,那肯定和1比较像。我就判断这个手势是手势1。

五、BoF图像分类问题也存在问题

(1)SIFT局部描述子能较好的描述图像纹理信息(描述方向梯度),但是也有可能造成其他方面信息的丢失,所以一般解决方法是利用多描述子混合的思路。

(2)这种一个特征点对应于一个词的方法显然忽略图像空间上下文(Spatial Context Modeling),这很容易造成词语义的模糊,所以我们需要构建空间结构,更好的Feature Pooling :)

最为成功的尝试就是SPM(Spatial Pyramid Matching 空间金字塔匹配),这个方法就是将图像分成多个尺度小块,这里图像每个尺度内的小分块都会得到一个特征词表,所以特征词表串联起来就得到整个图像特征词表,这样做好处是保留了图像空间信息,另外一种思路是在方向梯度空间内操作。

另一种方法是引入词组(phrases),在由词(low-level)到主题(high-level)中引入中间层(mid-level),比如LLC引入特征点的位置约束。

下面这种GPP的方法也很类似,其将特征点周围最近的K个特征点共同组成了一个词组(Phrase),此时整个Feature Pooling过程变为word-phrase-theme

在BoF图像分类问题上,这方面(Better coding + pooling)的研究是重点,上面关于SPM和LLC,我只是简要说了一些目的和原理,不过网上有很多关于SPM及稀疏编码的文章可以参考,特别是这篇http://blog.csdn.net/jwh_bupt/article/details/9837555,转载也挺多的。

(3)图像中一般都存在同主题无关的内容,会影响分类的结果,改进方法是检测兴趣区域(detection of regions-of-interest(ROI))并给不同的权重。

ORB-SLAM中的词袋树

六、拓展

1. 直方图相似性度量

每个图像可以用直方图向量来表示,两幅图像是否相同或相似,以及它们的相似程度,可以用直方图相似性度量函数来确定,度量函数有多种,可以选择不同的核函数来表示,如:线型核,塌方距离测度核,直方图交叉核(The Pyramid Match Kernel)等的选择。

2.空间信息
   将图像表示成一个无序局部特征集的特征包方法,丢掉了所有的关于空间特征布局的信息,在描述性上具有一定的有限性。为此, Schmid[2]提出了基于空间金字塔的Bag-of-Features(Spatial Pyramid Matching)。

3.用分量差进行图像描述

Jégou[7]提出VLAD(vector of locally aggregated descriptors),其方法是如同BOF先建立出含有k个visual word的codebook,而不同于BOF将一个local descriptor用NN分类到最近的visual word中,VLAD所采用的是计算出local descriptor和每个visual word(ci)在每个分量上的差距,将每个分量的差距形成一个新的向量来代表图片。

七、资源

Two bag-of-words classifiers(Matlab)
Code for Vocabulary tree based image search(C++)
matlab+VC 实现Bag of features 
Bag of Words/Bag of Features的Matlab源码
一个用BoW|Pyramid BoW+SVM进行图像分类的Matlab Demo
Bag-Of-Words中K-Means聚类的效率优化
aMMAI BLOG
Visual Wordsを用いた類似画像検索
bayonを使って画像からbag-of-keypointsを求める

Paper

1.Bag of words models(.ppt )  byLi Fei-Fei(Stanford)

2.  Spatial Pyramid Matching:

  • Beyond Bags of Features: Spatial Pyramid Matching for Recognizing Natural Scene Categories
    S. Lazebnik, C. Schmid, and J. Ponce, CVPR 2006
     Slides, MATLAB code, scene category dataset

3. Improving bag-of-features for large scale image search

  • Improving bag-of-features for large scale image search.
    Hervé Jégou, Matthijs Douze, Cordelia Schmid.International Journal of Computer Vision, Volume 87, Number 3 - feb 2010.[pdf]
    Demo:bigimbaz image search engine

4. Hamming embedding and weak geometric consistency for large scale image search. Hervé Jégou, Matthijs Douze, Cordelia Schmid
European Conference on Computer Vision - oct 2008.[pdf][slides]

5. Bag-of-colors for improved image search. Christian Wengert, Matthijs Douze, Hervé Jégou,ACM Multimedia (2011).[pdf]

6. Video Google: A Text Retrieval Approach to Object Matching in Videos  .  J. Sivic, A. Zisserman.  IEEE International Conference on Computer Vision, Volume 2, page 1470--1477, 2003.[PDF ]

7.Aggregating local descriptors into a compact image representation. Hervé Jégou, Matthijs Douze, Cordelia Schmid, Patrick Pérez. IEEE Conference on Computer Vision & Pattern Recognition - jun 2010. [pdf][sildes]

浅析 Bag of Feature - 大白话AI - 博客园

Bag of Features (BOF)图像检索算法_loadstar_kun的博客-CSDN博客_bof模型

深度学习之学习(1-3)Bag of Features (BOF)图像检索算法相关推荐

  1. Bag of Features (BOF)图像检索算法

    FROM:http://blog.csdn.net/loadstar_kun/article/details/39450137 1.首先,我们用surf算法生成图像库中每幅图的特征点及描述符. 2.再 ...

  2. OpenCV精进之路(二十三):实例——Bag of Features(BoF)图像分类实践

    在深度学习在图像识别任务上大放异彩之前,词袋模型Bag of Features一直是各类比赛的首选方法.首先我们先来回顾一下PASCAL VOC竞赛历年来的最好成绩来介绍物体分类算法的发展. 从上表我 ...

  3. Bag of Features (BoF) 简介

           最初的Bag of words,也叫做"词袋",在信息检索中,Bag of words model假定对于一个文本,忽略其词序和语法,句法,将其仅仅看做是一个词集合, ...

  4. 《动手学深度学习》—学习笔记

    文章目录 深度学习简介 起源 特点 小结 预备知识 获取和运行本书的代码 pytorch环境安装 方式一 方式二 数据操作 创建 运算 广播机制 索引 运算的内存开销 NDArray和NumPy相互变 ...

  5. DSML:深度子空间相互学习模型(用于癌症亚型预测)

    目录 背景描述 模型架构 数据表示 Single level omics data representation learning model(单级组学数据表示学习模型) Multi-level om ...

  6. 深度学习多变量时间序列预测:卷积神经网络(CNN)算法构建时间序列多变量模型预测交通流量+代码实战

    深度学习多变量时间序列预测:卷积神经网络(CNN)算法构建时间序列多变量模型预测交通流量+代码实战 卷积神经网络,听起来像是计算机科学.生物学和数学的诡异组合,但它们已经成为计算机视觉领域中最具影响力 ...

  7. 2020人工智能课程超级大列表:深度学习-强化学习-图神经网络-自然语言处理等...

    关注上方"深度学习技术前沿",选择"星标公众号", 资源干货,第一时间送达! 本篇博文主要为大家介绍一个课程网站,汇集了机器学习,深度学习.强化学习的各个方面, ...

  8. 深度强化元学习教程---元学习概述

    深度强化元学习是近期深度学习技术的一个另人瞩目的新兴领域,其利用元学习,解决了深度学习需要大数据集的问题,以及强化学习收敛慢的问题.同时元学习还可以适用于环境不断改变的应用场景,具有巨大的应用前景. ...

  9. Deep Learning(深度学习)学习笔记整理系列之(五)

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  10. reddit高赞资源:20h系统性深度学习强化学习课程,视频、PPT、代码全都有 | 免费...

    子豪 发自 凹非寺 量子位 报道 | 公众号 QbitAI 告别"拼图式"学习! 最近,一套深度学习和强化学习的免费课程在reddit上引起网友关注,获赞690+. 只因其不仅形式 ...

最新文章

  1. Linux系统中重启tomcat的一般步骤
  2. Android权限【大全】 .
  3. postfix报错postfix: fatal: parameter inet_interfaces: no local interface found for ::1
  4. C++ puts函数 打印字符串很方便
  5. mybatis-01
  6. 跨域问题时的Filter无效
  7. Opencv+pycharm+anaconda配置
  8. 《结对-航空购票系统-开发环境搭建过程》
  9. 网页关注微信服务号登录
  10. Chinese-Whisper聚类算法
  11. fedora20 安装nvidia独立显卡驱动
  12. WordPress评论摘要标签:comment_excerpt
  13. conda 克隆环境
  14. Android短信备份案例
  15. 七升七降调号_降7是什么调?
  16. 只会Python可造不出iPhone
  17. C语言bound函数,C++中lower_bound函数和upper_bound函数
  18. 电脑桌面云便签怎么设置字体字号大小?
  19. 通过自定义android键盘实现车牌号输入法
  20. 从appstore快速安装Xcode 8.0_如何解决xcode8安装慢的问题

热门文章

  1. 香港理工大学计算机专业课程,香港理工大学计算机系包括哪些专业
  2. 关于XDR的这些问题你都了解吗?
  3. 短视频“音频化”,音乐“视频化”
  4. 台北故宫博物院收藏:气势开张,米芾行草书法真迹《真酥帖》赏析
  5. prng伪随机数生成器_Java伪随机数生成器(PRNG)中的弱点
  6. 邮箱校验以及电话号码校验
  7. 在阿里云里怎么样可以连接阿里云数据库
  8. Linux TCP Timestamps 没鸟用
  9. 解决 Ubuntu-MATE 系统中出现 System policy prevents Wi-Fi scans 的问题
  10. MapReduce: Simplified Data Processing on Large Clusters