目录
一、Bag of features算法
1、算法原理
Bag of features算法一种是用于图像和视频检索的算法,该算法对于不同角度、光照的图像,基本都能在图像库中正确检索。
2、算法步骤
(1)收集图片,用sift算法生成图像库中没附图的特征及描述符。
(2)用K-means算法对图像库中的特征点进行训练,生成类聚中心。
(3)通过判断图像的每个特征点与那个类心最近,最近则放入该类心,最后生成一列频数表,生成每幅图像的BOF。
(4)对需要查询的图片不断进行(3)操作,生成一列查询图片的BOF。
(5) 将得到的BOF向量与图像库中每幅图的BOF向量求夹脚,夹脚最小的即为匹配对象。
3、补充:K-means算法
K-means算法是一种类聚算法,即根据相似性原则,将具有较高相似度的数据对象划分至同一类簇,将具有较高相异度的数据对象划分至不同类簇。
K-means算法步骤:
(1)从数据中选择K个对象作为初始类聚中心。
(2)计算每个类聚对象到类心的距离。
(3)计算标准测度函数,直到达到最大迭代次数,停止。
二、实验分析
1、收集图片
2、实验源码
(1)提取每张图片的sifi特征,生成词汇表。
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift
# 要记得将PCV放置在对应的路径下
# 获取图像列表
imlist = get_imlist('E:/BOF/img1/') # 存放数据集的路径
nbr_images = len(imlist) # 获取数据集的长度
# nbr_images = 300 # 可以是自己选择用多少张图片作为训练数据集
# 获取特征列表
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('imglltest')
voc.train(featlist, 300, 10)
# 保存词汇
with open('E:/BOF/vocabulary.pkl', 'wb') as f:
pickle.dump(voc, f)
print ('vocabulary is:', voc.name, voc.nbr_words)
(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
# 要记得将PCV放置在对应的路径下
# 获取图像列表
imlist = get_imlist('E:/BOF/img1/') # 存放数据集的路径
nbr_images = len(imlist)
# nbr_images = 300
# 获取特征列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]
# 载入词汇
with open('E:/BOF/vocabulary.pkl', 'rb') as f: # 读取再上一步中保存的.pkl文件
voc = pickle.load(f)
# 创建索引
index = imagesearch.Indexer('testImaAdd.db', voc) # 创建数据库
index.create_tables() # 创建数据库表单
# 遍历所有的图像,并将它们的特征投影到词汇上
for i in range(nbr_images)[:300]:
locs, descr = sift.read_features_from_file(featlist[i])
index.add_to_index(imlist[i], descr)
# 提交到数据库
index.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('E:/Python37_course/test7/first1000/')
imlist = get_imlist('E:/BOF/img1/')
nbr_images = len(imlist)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]
#载入词汇
with open('E:/BOF/vocabulary.pkl', 'rb') as f:
voc = pickle.load(f)
src = imagesearch.Searcher('testImaAdd.db',voc)# Searcher类读入图像的单词直方图执行查询
# index of query image and number of results to return
#查询图像索引和查询返回的图像数
q_ind = 15
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[:6]) #常规查询
imagesearch.plot_results(src,res_geom[:6]) #重排后的结果
2、运行结果
输入图片:
输出结果:
常规查询:
重排后结果:
3、实验小结
根据上述实验结果可以看出,由于选取的图像集数量有限及其他各种因素,还是存在较大的误差,因此还需要进一步的探讨以及实验。
实验中遇到的一些小问题与解决方案:
(1)由于我们python的版本为3.6,所以pysqlite2不能使用,将其改为from sqlite3 import dbapi2 as sqlite.
(2)一定要记得将PCV放置在对应的路径下。