Bag of features

一 实验背景

1.1 原理

要了解Bag of Features,首先要知道Bag of Words。
Bag of Words是文本分类中一种通俗易懂的策略。一般来讲,如果我们要了解一段文本的主要内容,最行之有效的策略是抓取文本中的关键词,根据关键词出现的频率确定这段文本的中心思想。
比如:如果一则新闻中经常出现「iraq」、「terrorists」,那么,我们可以认为这则新闻应该跟伊拉克的恐怖主义有关。而如果一则新闻中出现较多的关键词是「soviet」、「cuba」,我们又可以猜测这则新闻是关于冷战的(见下图)。
在这里插入图片描述Bag of features(Bof)一种是用于图像和视频检索的算法,此算法的神奇之处,就在于对于不同角度,光照的图像,基本都能在图像库中正确检索。
Bag of features,中文翻译为“词袋”,是一种用于图像或视频检索的技术。而检索就要进行比对。两幅不同的图像如何比对,比对什么,这就需要提炼出每幅图像中精练的东西出来进行比较。正如超市中的条形码,就能很好的反映出一件商品的所有特征。因此概括的来说,bof就是生成每幅图像的“条形码”来进行检索。

1.2 应用步骤

Bof可运用于图像分类,具体步骤如下:
(1)特征提取
在这里插入图片描述
特征必须具有较高的区分度,而且要满足旋转不变性以及尺寸不变性等,因此通常都会采用SIFT特征提取。SIFT会从图片上提取出很多特征点,每个特征点都是 128 维的向量。当图片足够多的话,会提取出一个巨大的特征向量库。

(2)学习“视觉词典”
在这里插入图片描述
采用聚类方式将所有特征向量归类。最常用的聚类算法是 k-means。至于 k-means 中的 k 如何取,要根据具体情况来确定。由于特征的数量可能非常庞大,这个聚类的过程也会非常漫长。
K-means算法流程:
• 随机初始化 K 个聚类中心。
• 重复下述步骤直至算法收敛:
• 对应每个特征,根据距离关系赋值给某个中心/类别。
• 对每个类别,根据其对应的特征集重新计算聚类中心。

(3)针对输入特征集,根据视觉词典进行量化
对于上一步训练得到的字典,是为了这一步对图像特征进行量化。对于一幅图像而言,我们可以提取出大量的SIFT特征点,但这些特征点缺乏代表性。因此,这一步,是根据字典重新提取图像的高层特征。

(4)把输入图像转化成视觉单词(visual words) 的频率直方图
在这里插入图片描述
对于图像中的每一个SIFT特征,都可以在字典中找到一个最相似的 visual word,这样,我们可以统计一个 k 维的直方图,代表该图像的SIFT特征在字典中的相似度频率。

(5)构造特征到图像的倒排表,通过倒排表快速索引相关图像
倒排表基本思想:直方图映射为特征向量
Ci :特征向量
Ii :数据库中的图片
假设现有一个集合(特征向量Ci分别在图片Ii中出现):
C1={I1,I101} C2={I2,I101} C50={I1,I5,I100} C3000={I1,I3,I101}
输入一张图Ix,这张图中分别有以下特征向量C1,C50,C3000
可以得出检索对象为I1,I3,I5,I100,I101
可以设置对阈值出现两次以上的图像进行检索,如本例中的I1,I101
使用倒排表可以避免一一比对的现象,降低计算时间

(6)根据索引结果进行直方图匹配

二 实验过程

2.1实验准备

1.基于自己家的环境拍摄100张图片作为数据集,如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.配置sift:打开PCV包里的sift.py文件,将sift.exe的路径添加到下图的位置。
在这里插入图片描述

2.2实验代码

(1)提取sift特征并建立视觉词典

# -*- 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('D:/zq/sjj100/')
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('D:/zq/sjj100/vocabulary.pkl', 'wb') as f:
    pickle.dump(voc, f)
print ('vocabulary is:', voc.name, voc.nbr_words)

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

# load vocabulary
#载入词汇
with open('D:/zq/sjj100/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)测试

# -*- 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('D:/zq/sjj100/')
nbr_images = len(imlist)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]

#载入词汇
with open('D:/zq/sjj100/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 = 6
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 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.第一次实验
测试图像:
在这里插入图片描述
测试结果:
在这里插入图片描述
2.第二次实验
测试图像:
在这里插入图片描述
测试结果:
在这里插入图片描述
3.第三次实验
测试图像:
在这里插入图片描述
测试结果:
在这里插入图片描述
4.第四次实验
测试图像:
在这里插入图片描述
测试结果:
在这里插入图片描述

分析:
①测试结果输出与测试图片最为匹配的前5张图片,上部分五张为常规查询的结果,即利用欧氏距离,下部分五张为RANSEC模型测试结果,但两部分结果是相同的。
②第1,2次实验的测试结果完全正确,找到了与测试图片为同一场景的五张图片。而第3,4次实验的测试结果出现了错误,出现了若干张与测试图片不是同一场景的图片。首先从数据集来看,第1,2次实验的测试图片的场景图准备了10张,而第3,4次实验只准备了5张。说明在相同图像的数据集较多的情况之下,图像的匹配效果就会比较好。其次从图像特征的角度出发,图像特征比较明显的,匹配效果也会更好。

三 遇到的问题及解决方案

1.出现错误:OSError: D:/zq/sjj100/ukbench00000.sift not found.
这个就是sift没有配置好的原因,按照上述实验准备中的方法配置即可。
2.出现错误:SyntaxError: Missing parentheses in call to ‘print’. Did you mean print(‘indexing’, imname)?
这个是老问题了,出现类似这种的问题只要加上括号即可。
3.出现错误:ModuleNotFoundError: No module named ‘pysqlite2’
这个问题是由于我使用的是python3,所以需要将from pysqlite2 import dbapi2 as sqlite改为from sqlite3 import dbapi2 as sqlite即可。
4.出现错误:NameError: name ‘sqlite’ is not defined
这个同样是 sqlite的问题,将sqlite改成sqlite3即可。
5.出现错误:TypeError: a bytes-like object is required, not ‘str’
这个好像也是python版本的问题,百度后将str去掉即可。
6.出现错误:TypeError: ‘cmp’ is an invalid keyword argument for sort()
百度后发现这个仍然是python2和3版本的问题,将tmp.sort(cmp=lambda x,y:cmp(x[1],y[1]))改成tmp.sort(key=cmp_to_key(lambda x,y:operator.gt(x[1],y[1])))即可。
7.出现问题:NameError: name ‘cmp_to_key’ is not defined
这是模块导入的问题,在imagesearch.py的开头加上from functools import cmp_to_key即可。

四 实验总结

1.常用参数设置:
视觉单词数量(K-means算法获取的聚类中心)一般为 K=3000-10000。即图像整体描述的直方图维度为 3000-10000。
求解近邻的方法一般采用L2-范数:即 Euclidean 距离。
目前普适的视觉单词采用 Lowe 的SIFT特征描述子. 特征点检测采用 DOG (Difference of Gaussians)。
2.对于词典/码本的规模,太少的话视觉单词无法覆盖所有可能出现的情况,太多的话计算量大,容易过拟合。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值