两种常用的图像检索算法

背景知识

Mat类型数据结构

一个图像的通道数是N,就表明每个像素点处有N个数,一个a×b的N通道图像,其图像矩阵实际上是b行N×a列的数字矩阵。
p = img.ptr<uchar>(i); 图像第i行的头指针,通过这个指针结合列的位置(就是你代码中的j)可以很轻松操作图像改行的每一列,即p[j]
samples.at<Vec3f>(k,0)[0] = float(p[j*3]); at <类型> (行,列) [通道(如果有通道的话)],获取某点像素值

kmeans

总体目标是最小化聚类中心与每个样本的欧式距离,先随机初始化K个聚类中心,根据欧式距离进行划分,更新聚类中心,不断重复,直到达到指定的聚类次数或者收敛为止。缺点是需要指定K类,以及初始点对划分结果影响很大

kNN

有监督的分类算法,K个最相似(欧式距离)的样本中的大多数属于某个类别,则该样本也属于该类

欧式距离

指的是两个向量的距离相似度,欧式距离越小代表向量越趋于相似(二、三维空间中就是点的实际距离),公式如下$$\rho = \sqrt{\sum_{i=1}^{n}(x_{i}-y_{i})^{2}}$$

余弦距离

指的是两个向量的方向相似度,余弦值越大(归一化后点乘),代表向量越相似。

图像相似度匹配算法

BOF(Bag of Features)算法

  • 视觉单词提取:提取所有图片的ORB特征并concat到一起[M, N, D]
  • 视觉词典构建:采用K-Means算法,聚成K个类,每个聚类有一个类心,那么这K个类心就相当于词袋中的K个基本词汇。
  • 图像表示:统计每张图片在每个聚类中的特征个数,这样每个图片就可以由一个分布直方图表示,或者说用一个K维的向量表示,向量第i维的值为该图片在第i个聚类中的特征个数。那么每个图像都可以由基本词汇表示。
  • 图像检索:对于一个待检索的图像,我们先提取该图像的图像特征,并产生该图像的分布直方图(K维向量)。然后进行图像向量的余弦相似度度量便可以了

VALD算法:

  • ORB对每张图像提取特征[N, D]
  • 聚类[K,D]
  • 以每个center为中心,进行残差计算并累加(每个N和其对应的center(label))[K, D]
  • 将矩阵拉成一个[K, D]的长向量,对该向量的每一个分量进行幂律归一化(需保持符号不变),公式如下:$$v_{j} := \left | v_{j} \right |^{\alpha } \times sign(v_{j}), j = 1,2, … D$$幂律归一化的目的是主要为了减少某些特征出现次数特别多带来的影响,这是因为出现次数特别多时聚类中心就在它附近,相应的残差就很小,这样便可以抑制数值大的数同时提升数值小的数
  • 对每个分量进行L2范数归一化 normalize(Vlad,Vlad,-1.0,1.0,NORM_L2)
  • 采用PCA进行降维,得到该图像的VALD特征向量,之后进行图像向量的余弦相似度度量便可以了