Bag of features图像检索

一、原理

1、Bag-of-words

Bag-of-words用于图像和视频的检索,其来源于文本分类技术。在信息检索中,给定一个文本,根据文本中的词频分布,构造文本描述子。文本中每个词的出现都是独立的,与其出现的位置和顺序无关。 因此,图像检索可以从每张图片中提取关键特征,使用某种聚类算法将局部特征进行聚类,每个聚类中心被看作是词典中的一个视觉词汇,所有视觉词汇形成一个视觉词典。图像中的每个特征映射到视觉词典中的某个词上,统计每个视觉词汇出现的次数,形成一个直方图。
在这里插入图片描述

2、步骤

2.1 特征提取

采用SIFT方法提取所有图片的关键特征,
在这里插入图片描述

2.2 学习 “视觉词典(visual vocabulary)

采用K-means进行聚类,假设输入的图片经特征提取后,有n个特征点,由聚合得到k个集合,每个集合的聚类中心就构成了视觉词典。
步骤:

  • 随机初始化 K 个聚类中心
  • 重复下述步骤直至算法收敛:
  • 对应每个特征,根据欧氏距离计算每个特征 xi 与其相对应的聚类中心 mk 之间的欧式距离,找到最小的那个聚类中心,将该特征点放入此聚类质心集合中。
  • 对每个集合,根据其对应的特征集重新计算聚类中心

如图表示:

在这里插入图片描述
如何选择视觉词典/码本的规模?

  • 太少:视觉单词无法覆盖所有可能出现的情况
  • 太多: 计算量大,容易过拟合

常见设置:视觉单词数量(K-means算法获取的聚类中心)一般为K=3000~10000. 即图像整体描述的直方图维度为3000~10000.

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

量化的过程就是计算每个特征到所有的视觉单词的距离,映射到距离最近的,并将对应视觉单词的频数加1

2.4 把输入图像,根据TF-IDF(词频-逆向文档频率)转化成视觉单词(visual words)的频率直方图
2.4.1TF-IDF

在文本检索中,不同单词对文本检索的贡献有差异,
一个单词出现在文档中的比例越大,它对匹配的用处就越小,比如“的”,每篇文章中出现的概率很大,区别不大。

  • TF:词频,指的是一个给定的词语在该文件中出现的次数
  • IDF:逆文档频率,描述了某一个特定词语的普遍重要性,如果某词语在许多文档中都出现过,表明它对文档的区分力不强,则赋予较小的权重,IDF越小;反之IDF越大。
    在这里插入图片描述
2.4.2 构建频率直方图

在这里插入图片描述
将投票值(TF)与“视觉单词”(IDF)权重相乘,得到频率直方图。
在这里插入图片描述

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

倒排表就是逆向的检索方法,在前面几步查找出来的词汇,反向查找出现这些词汇的文章,如图,查找多个词汇,就形成了一个倒排表
在这里插入图片描述
BOF通过对视觉词汇的反向查找,得到拥有同一视觉词汇的图像集合,反复多次就得到一张倒排表。这样根据倒排表就可以快速地在图像库中找到与新图像相似的图像。

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

输入一张图片进行图像的检索,用K邻近算法,给出前面图像集的直方图,在数据库中查找K个最近邻的图像。

二、实验

1、步骤

  1. 构造不小于100张图片的数据集
  2. 针对数据集,做SIFT特征提取
  3. 根据SIFT特征提取结果,采用k-means算法学习“视觉词典(visual vocabulary)”,其中维度至少满足4个量级(比如10,50,100,1000,5000)
  4. 根据IDF原理,计算每个视觉单词的权
  5. 针对数据库中每张图片的特征集,根据视觉词典进行量化 ,以及TF-IDF解算。每张图片转化成特征向量
  6. 对于输入的检索图像(非数据库中图片),计算SIFT特征,并根据TF-IDF转化成频率直方图/特征向量
  7. 构造检索图像特征到数据库图像的倒排表,快速索引相关候选匹配图像集
  8. 针对候选匹配图像集与检索图像进行直方图/特征匹配

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
import sift
#获取图像列表
#imlist = get_imlist('E:/Vision/sift/BagOfFeature/u')

imlist = get_imlist('E:/Vision/sift/BagOfFeature/datas/jpg')
nbr_images = len(imlist)
print(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('test77_test')
voc.train(featlist, 1000, 10)
    
#保存词汇

with open('E:/Vision/sift/BagOfFeature/BOW/vocabulary.pkl', 'wb') as f:
    pickle.dump(voc, f)
print ('vocabulary is:', voc.name, voc.nbr_words)

词汇保存在.pkl文件中,voc.train(featlist, 1000, 10)中的第二个参数对应维度K,不同的K值生成的词汇数量不同,分别存储在不同的文件件中,以下分别对应K=50,100,500,1000的词汇
在这里插入图片描述

2、建立图像索引和数据库

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('E:/Vision/sift/BagOfFeature/u')
imlist = get_imlist('E:/Vision/sift/BagOfFeature/datas/jpg')
nbr_images = len(imlist)
#获取特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]

# load vocabulary
#载入词汇
with open('E:/Vision/sift/BagOfFeature/BOW/vocabulary.pkl', 'rb') as f:
    voc = pickle.load(f)
#创建索引
indx = imagesearch.Indexer('testImaAdd1000.db',voc) # 在Indexer这个类中创建表、索引,将图像数据写入数据库
indx.create_tables() # 创建表
# go through all images, project features on vocabulary and insert
#遍历所有的图像,并将它们的特征投影到词汇上
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获取带有特征描述子的图像,投影到词汇上
                                       # 将图像的单词直方图编码存储
# commit to database
#提交到数据库
indx.db_commit()

con = sqlite.connect('testImaAdd1000.db')
print (con.execute('select count (filename) from imlist').fetchone())
print (con.execute('select * from imlist').fetchone())

不同的维度K生成不同的数据库,所以数据库名字要和前面的不一样
在这里插入图片描述

3、图像检索

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('E:/Vision/sift/BagOfFeature/datas/jpg')
nbr_images = len(imlist)
print(nbr_images)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]

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

src = imagesearch.Searcher('testImaAdd1000.db',voc)

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

# 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[1:8]) #常规查询
imagesearch.plot_results(src,res_geom[1:8]) #重排后的结果

4、结果:
使用的图片集一共有10种类型,每种类型大概30多张,共315张图片
数据集下载
在这里插入图片描述

查询的图片:
在这里插入图片描述
kmeans聚类时选取维度K不同得到的结果也不同,下列分别输出匹配前七的图片:

50维
常规查询
在这里插入图片描述
重排后的结果:
在这里插入图片描述
100维常规查询:
在这里插入图片描述
100维重排后:
在这里插入图片描述
500维常规查询:
在这里插入图片描述
500维重排后:
在这里插入图片描述
1000维常规查询:
在这里插入图片描述
1000维重排后:
在这里插入图片描述
总结:
总体来看,匹配效果并不是很好,可能 是由于图片集只有300多张,数据量不够,特征点不够多。
测试的图片其实是一只狗,但发现匹配的结果很多是猫,而且随着维度的增加,匹配到猫的数量越多,可能是因为测试图片的动物和猫的颜色纹理特征都有很大的相似,所以匹配错误。
但是相对前几维来说,随着维度增加,查询的效果越好。重排后的结果和常规查询一模一样,可能还是图片集数量少,图片特征不明显,匹配的点少。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值