文章目录
Bag Of Words模型
词序无关的文本表述: 根据文本中的词频分布,构造
文本描述子
Bag Of Words模型的应用:图像分类
Bag of features
基础流程
-
特征提取
-
学习 “视觉词典(visual vocabulary)”
-
针对输入特征集,根据视觉词典进行量化
-
把输入图像转化成视觉单词(visual words)的频率直方图
K-means 聚类算法
最小化每个特征 xi 与其相对应的聚类中心 mk之间的欧式距离
算法流程:
-
随机初始化 K 个聚类中心
-
重复下述步骤直至算法收敛:
• 对应每个特征,根据距离关系赋值给某个中心/类别
• 对每个类别,根据其对应的特征集重新计算聚类中心
学习特征词典
-
聚类是实现 visual vocabulary /codebook的关
键
• 无监督学习策略
• k-means 算法获取的聚类中心作为 codevector
• Codebook 可以通过不同的训练集协同训练获得
• 一旦训练集准备足够充分, 训练出来的码本( codebook)将具有普适性 -
码本/字典用于对输入图片的特征集进行量化
• 对于输入特征,量化的过程是将该特征映射到距离其最接近的 codevector ,并实现计数
• 码本 = 视觉词典
• Codevector = 视觉单词
视觉词典样例:
视觉词典存在的问题:
- 如何选择视觉词典/码本的规模?
•太少:视觉单词无法覆盖所有可能出现的情况
•太多: 计算量大,容易过拟合 - 如何提升计算效率?
•Vocabulary trees
Bag of features: 图像检索
- 给定输入图像的BOW直方图, 在数据库中查找 k 个最近邻的图像
- 对于图像分类问题,可以根据这k个近邻图像的分类标签,投票获得分类结果
- 当训练数据足以表述所有图像的时候,检索/分类效果良好
常用参数设置:
- 视觉单词数量(K-means算法获取的聚类中心)一般为K=3000~10000. 即图像整体描述的直方图维度为3000~10000.
- 求解近邻的方法一般采用L2-范数:即 Euclidean 距离.
- 目前普适的视觉单词采用 Lowe 的SIFT特征描述子. 特征点检测采用 DOG (Difference of Gaussians)
图像检索流程
- 特征提取
- 学习 “视觉词典(visual vocabulary)”
- 针对输入特征集,根据视觉词典进行量化
- 把输入图像,根据TF-IDF转化成视觉单词(visual words)的频率直方图
- 构造特征到图像的倒排表,通过倒排表快速索引相关图像
- 根据索引结果进行直方图匹配
实验过程
数据集
在该实验过程中,我构建了一百张jpg图像的数据集,共分为十种不同风格类型的图像,每种类型的图像为十张。
对图像进行SIFT特征提取
# -*- coding=utf-8 -*-
# name: nan chen
# date: 2021/6/1 11:06
# -*- coding: utf-8 -*-
from PCV.localdescriptors import sift
from PCV.tools.imtools import get_imlist
# 获取图像列表
imlist = get_imlist(r'D:\computerVision\bagpic')
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])
部分特征提取结果如图所示:
学习视觉词典
# -*- coding=utf-8 -*-
# name: nan chen
# date: 2021/6/1 11:13
# -*- coding: utf-8 -*-
import pickle
from PCV.imagesearch import vocabulary
from PCV.tools.imtools import get_imlist
# 获取图像列表
imlist = get_imlist(r'D:\computerVision\bagpic')
nbr_images = len(imlist)
# 获取特征列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]
# 生成词汇
voc = vocabulary.Vocabulary('bof_test')
voc.train(featlist, 50, 10)
# 保存词汇
with open(r'D:\computerVision\bagpic\vocabulary50.pkl', 'wb') as f:
pickle.dump(voc, f)
print('vocabulary is:', voc.name, voc.nbr_words)
生成的数据模型:
对输入的特征集进行量化
# -*- coding=utf-8 -*-
# name: nan chen
# date: 2021/6/1 11:16
# -*- coding: utf-8 -*-
import pickle
from PCV.imagesearch import imagesearch
from PCV.localdescriptors import sift
import sqlite3
from PCV.tools.imtools import get_imlist
# 获取图像列表
imlist = get_imlist(r'D:\computerVision\bagpic')
nbr_images = len(imlist)
# 获取特征列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]
# 载入词汇
with open(r'D:\computerVision\bagpic\vocabulary50.pkl', 'rb') as f:
voc = pickle.load(f)
# 创建索引
indx = imagesearch.Indexer('testImaAdd.db', voc)
indx.create_tables()
# 遍历所有的图像,并将它们的特征投影到词汇上
for i in range(nbr_images)[:120]:
locs, descr = sift.read_features_from_file(featlist[i])
indx.add_to_index(imlist[i], descr)
# 提交到数据库
indx.db_commit()
con = sqlite3.connect('testImaAdd.db')
print(con.execute('select count (filename) from imlist').fetchone())
print(con.execute('select * from imlist').fetchone())
图像检索
# -*- coding=utf-8 -*-
# name: nan chen
# date: 2021/6/1 11:23
import pickle
from PCV.imagesearch import imagesearch
from PCV.geometry import homography
from PCV.tools.imtools import get_imlist
from PCV.localdescriptors import sift
import warnings
warnings.filterwarnings("ignore")
# load image list and vocabulary
# 载入图像列表
imlist = get_imlist(r'D:\computerVision\bagpic')
nbr_images = len(imlist)
# 载入特征列表
featlist = [imlist[i][:-3] + 'sift' for i in range(nbr_images)]
# 载入词汇
with open(r'D:\computerVision\bagpic\vocabulary50.pkl', 'rb') as f:
voc = pickle.load(f, encoding='iso-8859-1')
src = imagesearch.Searcher('testImaAdd.db', voc) # Searcher类读入图像的单词直方图执行查询
# index of query image and number of results to return
# 查询图像索引和查询返回的图像数
q_ind = 1
nbr_results = 5
# 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:]:
try:
locs, descr = sift.read_features_from_file(featlist[ndx]) # because 'ndx' is a rowid of the DB that starts at 1
except:
continue
# 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]) # 重排后的结果
实验结果:
如图所示:我通过图像检索检索出与查询图像相似的五张图像,第一次是常规查询出的结果,第二次则是经过重排后的查询结果。
在该实验中通过生成不同的视觉词典会对查询结果造成不同程度的影响。在一定范围内,比如维度从10到100,会发现随着维度的增加,图像检索的效果越好,可若是维度增加太大的话,比如10000维度,会发现检索效果变差,这是过平滑的效果。