CPR的最邻图片搜索

CPR找相似图片的核心思想

一句话概括:把每张图片的特征转换成一个”条形统计图”,然后对比统计图的形状,形状越像,图片就越相似。

此博客是由ai整理得到 并非本人手写!仅做临时复习使用!


具体步骤(三步走)

第一步:把特征变成”篮子”(Codebook)

想象你有一堆水果,你想统计每种水果有多少个。但你不知道有多少种水果,所以你先准备几个”篮子”,比如100个篮子。

  • Codebook就是这100个篮子
  • 每个篮子代表一种”特征模式”(比如某种纹理、某种形状)
  • 所有训练图片的特征会被分配到这100个篮子里,每个篮子会聚集相似的特征

类比:就像你去超市,货架上预先摆放了100类商品,所有新来的商品都要归类到这100类里。


第二步:把图片分成小块,每个块统计篮子里的数量(BlockWiseHistogramEncoder)

现在有一张图片,你不能只看整张,要把它切成小块(比如8×8=64块)。

对每一小块:

  1. 提取这块的特征
  2. 看这个特征最像哪个篮子,就把它放进那个篮子
  3. 统计这个小块里每个篮子有多少个特征

结果:每小块得到一个”条形统计图”,图上有100根柱子,每根柱子代表一个篮子的特征数量。

举例

  • 第1小块:篮子1有5个特征,篮子2有3个特征,篮子3有0个…
  • 第2小块:篮子1有2个特征,篮子2有7个特征…
  • …以此类推64个小块

最终:整张图片 = 64个小块 × 100根柱子 = 一个三维的统计图(64×100的矩阵)


第三步:对比统计图找相似图片(检索)

现在你有:

  • 训练集里每张图片都有一个64×100的统计图
  • 新来一张测试图片,也算出它的64×100统计图

怎么找最相似的?

方法有两种:

方法1:KL散度(CPR主要用这个)

  • 对比两个统计图的”形状差异”
  • KL散度越小,说明两个统计图越像
  • 就像对比两张柱状图,哪个柱子高哪个柱子低,越接近就越相似

方法2:欧氏距离

  • 简单粗暴,直接计算两个统计图上每个点的距离
  • 距离越近,越相似

CPR的小技巧

  • 不是所有64个块都用来对比,只对比其中80%最相似的块(l_ratio=4/5)
  • 这样可以忽略掉那些差异太大的块,避免噪声干扰

为什么要这样做?

优点1:更鲁棒

  • 统计图看的是”整体分布”,不是单个特征的具体数值
  • 即使图片有点光照变化、小干扰,统计图形状也不会变太大

优点2:保留空间信息

  • 把图片分块,每个块单独统计
  • 所以能知道”哪一块像哪一块”,而不是整张图片混在一起

优点3:计算高效

  • 统计图(64×100)比原始特征(可能几万维)小很多
  • 对比统计图很快

整个流程图解

1
2
3
4
5
6
7
8
9
10
11
12
13
原始图片

[Backbone] 提取特征(很多维)

[Codebook] 把特征归类到100个篮子

[分块] 切成8×8=64小块

[统计] 每块算出100根柱子 → 得到64×100统计图

[对比] 和训练集的统计图对比(用KL散度)

[结果] 找到统计图最像的那张图片 → 就是最相似的图片

关键参数解释

参数 含义 作用
n_clusters 篮子数量(100) 决定统计图的细致程度
S 分块数量(8×8) 决定空间信息的保留程度
d_method 对比方法(’kl’或’euc’) 决定相似度计算方式
l_ratio 对比比例(4/5) 过滤掉不相似的块

和你的想法的关系

你的想法是”找最相似的整张图片”,CPR做的就是这件事,只是它用统计图来表示整张图片,而不是直接用原始特征。

区别

  • 简单方法:直接用特征向量对比(比如用FAISS)
  • CPR方法:用统计图对比(更鲁棒,但复杂一点)

如果你用CPR的方法,你需要:

  1. 先用训练集训练出Codebook(聚类中心)
  2. 为每张训练图片算出统计图,存起来
  3. 测试时,算出测试图片的统计图,和训练集的统计图对比

这样理解清楚了吗?还有哪一步想让我再详细解释?