基于OpenCV实现小型的图像数据库检索功能
程序员文章站
2022-06-22 16:48:28
本文对前面的几篇文章进行个总结,实现一个小型的图像检索应用。一个小型的图像检索应用可以分为两部分: train,构建图像集的特征数据库。 retrieval,检索,给定图像,从图像库中返回...
本文对前面的几篇文章进行个总结,实现一个小型的图像检索应用。
一个小型的图像检索应用可以分为两部分:
- train,构建图像集的特征数据库。
- retrieval,检索,给定图像,从图像库中返回最类似的图像
构建图像数据库的过程如下:
- 生成图像集的视觉词汇表(vocabulary)
提取图像集所有图像的sift特征
对得到的sifte特征集合进行聚类,聚类中心就是vocabulary
- 对图像集中的图像重新编码表示,可使用bow或者vlad,这里选择vlad.
- 将图像集中所有图像的vlad表示组合到一起得到一个vlad表,这就是查询图像的数据库。
得到图像集的查询数据后,对任一图像查找其在数据库中的最相似图像的流程如下:
- 提取图像的sift特征
- 加载vocabulary,使用vlad表示图像
- 在图像数据库中查找与该vlad最相似的向量
构建图像集的特征数据库的流程通常是offline的,查询的过程则需要是实时的,基本流程参见下图:
由两部分构成:offline的训练过程以及online的检索查找
各个功能模块的实现
下面就使用vlad表示图像,实现一个小型的图像数据库的检索程序。下面实现需要的功能模块
- 特征点提取
- 构建vocabulary
- 构建数据库
第一步,特征点的提取
不管是bow还是vlad,都是基于图像的局部特征的,本文选择的局部特征是sift,使用其扩展rootsift。提取到稳定的特征点尤为的重要,本文使用opencv体哦那个的siftdetecotr
,实例化如下:
auto fdetector = xfeatures2d::sift::create(0,3,0.2,10);
create
的声明如下:
static ptr<sift> cv::xfeatures2d::sift::create ( int nfeatures = 0, int noctavelayers = 3, double contrastthreshold = 0.04, double edgethreshold = 10, double sigma = 1.6 )
- nfeatures 设置提取到的特征点的个数,每个sift的特征点都根据其对比度(local contrast)计算出来一个分数。设置了该值后,会根据分数排序,只保留前nfeatures个返回
- noctavelayers 每个octave中的层数,该值可以根据图像的分辨率大小计算出来。d.lowe论文中该值为3
- contrastthreshold 过滤掉低对比度的不稳定特征点,该值越大,提取到的特征点越少
- edgethreshold 过滤边缘处的特征点,该值越大,提取到的特征点就越多
- sigma 高斯滤波器的参数,该滤波器应用于第0个octave
个人的一些见解。
设置参数时,主要是设置contrastthreshold
和edgethreshold
。contrastthreshold
是过滤掉平滑区域的一些不稳定的特征点,edgethreshold
是过虑类似边缘的不稳定关键点。设置参数时,应尽量保证提取的特征点个数适中,不易过多,也不要过少。另外,contrastthreshold
和edgethreshold
的平衡,应根据要提取的目标是比较平滑的区域还是纹理较多的区域,来平衡这两个参数的设置。
对于有些图像,可能设置的提取特征点的参数叫严格,提取特征点的个数过少,这时候可改变宽松一些的参数。
auto fdetector = xfeatures2d::sift::create(0,3,0.2,10); fdetector->detectandcompute(img,noarray(),kpts,feature); if(kpts.size() < 10){ fdetector = xfeatures2d::sift::create(); fdetector->detectandcompute(img,noarray(),kpts,feature); }
阈值10,可根据具体的情况进行调节。