兴趣点描述子

上一章讨论了如何在图像中检测关键点并确定它们的尺度——得到一组 (x,y,σ)(x, y, \sigma) 三元组。但光知道「哪里有特别的点」还不够,我们还需要回答:这个点长什么样?本章讨论匹配流程中的后续步骤——如何从关键点周围提取一个紧凑而独特的描述子(Descriptor),使得同一个物理点在不同图像中的描述子尽量接近,不同点的描述子尽量不同。

区域归一化

在构建描述子之前,首先需要解决一个前置问题:同一个物理点在两张图像中,由于拍摄角度和距离不同,对应的图像区域可能在旋转、缩放甚至仿射变形上完全不同。如果直接从原始图像块提取描述子,两个描述子会因为这些几何差异而不匹配。

解决方案是归一化——在提取描述子之前,将图像区域变换到一个标准姿态,消除几何变化的影响。

方向归一化

上一章已经确定了关键点的位置 (x,y)(x, y) 和尺度 σ\sigma。接下来需要确定一个主方向(Dominant Orientation),使得即使图像发生旋转,同一个关键点也总是被旋转到相同的标准朝向。

具体做法:在关键点周围 σ\sigma 对应的区域内,计算每个像素的梯度方向,建立一个方向直方图(Orientation Histogram,将 [0,2π)[0, 2\pi) 分为若干个 bin),以梯度幅值作为权重。直方图的峰值方向就是该关键点的主方向。然后将整个图像区域旋转到主方向朝上——这样,无论原始图像旋转了多少,归一化后的图像块都是一样的。

多个主方向

如果方向直方图有多个显著的峰值(例如一个 T 形路口),可以为同一个关键点生成多个描述子,每个对应一个主方向。这增加了匹配的鲁棒性,但也增加了描述子的数量。

仿射归一化

旋转和缩放的归一化还不够——如果两张图像的视角差异较大,同一个物体上的圆形区域在一张图中可能变成了椭圆。这是因为视角变化近似于仿射变换(Affine Transformation)。

仿射归一化的思路是:利用二阶矩矩阵 M\bm{M}(上一章 Harris 检测器中用到的结构张量)的特征向量和特征值来估计局部区域的椭圆形状,然后将这个椭圆「拉」回成圆形。

具体流程是迭代的:

  1. 以圆形窗口计算 M\bm{M}
  2. 根据 M\bm{M} 的特征值调整窗口形状为椭圆
  3. 用新的椭圆窗口重新计算 M\bm{M},继续调整
  4. 迭代直到收敛(M\bm{M} 接近单位阵,即窗口已经适配了局部仿射变形)
  5. 最终将椭圆区域归一化为圆形:先旋转使长轴水平,再沿短轴拉伸使之等长

归一化后,两张不同视角图像中对应的区域被映射到了相同的标准形状,可以公平地比较它们的外观。

不变性 vs 协变性

检测器需要的是协变性(Covariance):图像变换后,检测到的区域也跟着变换——features(transform(image))=transform(features(image))\text{features}(\text{transform}(\text{image})) = \text{transform}(\text{features}(\text{image}))。描述子需要的是不变性(Invariance):图像变换后,描述子保持不变——descriptor(transform(image))=descriptor(image)\text{descriptor}(\text{transform}(\text{image})) = \text{descriptor}(\text{image})。协变检测 + 归一化 = 不变描述。

从像素到描述子

归一化之后,每个关键点对应一个大小和朝向统一的图像块。最朴素的描述子就是把图像块的所有像素值排成一个向量——这在理论上是最有区分力的,但对任何微小的变化都极其敏感。一个像素的微小偏移就会导致两个向量之间的距离大幅增加。

更好的策略是提取像素值的统计特征——丢弃精确的空间位置信息,换取对小幅变化的鲁棒性。梯度方向直方图就是这样一种特征:它描述了「这个区域内梯度朝各个方向的分布」,而不是「每个像素的精确梯度值」。这引出了 SIFT 描述子。

SIFT 描述子

SIFT(Scale-Invariant Feature Transform)是计算机视觉历史上引用次数最多的论文(超过 70000 次),它定义了从检测到描述的完整流程。上一章讨论了 SIFT 的检测部分(DoG 关键点检测),这里聚焦于描述子的构建。

构建过程

SIFT 描述子的构建分为四步:

  1. 确定区域:以关键点的 (x,y,σ)(x, y, \sigma) 确定一个归一化的正方形区域,旋转到主方向
  2. 划分子区域:将该区域分成 4×4=164 \times 4 = 16 个子区域(cell)
  3. 计算梯度直方图:在每个子区域内,统计所有像素的梯度方向直方图(8 个方向 bin),以梯度幅值作为权重
  4. 拼接:将 16 个子区域的 8 维直方图拼接成一个 4×4×8=1284 \times 4 \times 8 = 128 维的向量

最后对向量做归一化(除以 L2 范数)和截断(将大于 0.2 的分量截断到 0.2 后再归一化),以减少光照变化的影响。

实际实现中还有一个重要的细节:三线性插值(Trilinear Interpolation)。每个像素的梯度贡献不是简单地只分配给它所在的那一个子区域和方向 bin,而是按距离比例分配到相邻的子区域(xxyy 两个维度)和相邻的方向 bin(方向维度)。这样做的好处是消除了量化边界效应——如果一个梯度恰好落在两个 bin 的边界上,硬分配会导致微小的位移引起描述子的突变,而软分配则平滑了这种过渡。

为什么用梯度方向直方图

直觉上,梯度方向直方图编码了「这片区域里主要有哪些朝向的边缘和纹理」。将空间分成 4×44 \times 4 的网格保留了粗略的空间布局(左上角有什么、右下角有什么),但在每个子区域内通过直方图统计丢弃了精确的像素位置——这在保留区分力的同时获得了对微小位移的容忍度。

8 个方向 bin 将方向空间量化到约 45°45° 的分辨率,足以区分水平、垂直、对角线等主要结构。

SIFT 的输出

对一张图像运行完整 SIFT 流程后,得到的输出是:

  • nn 个关键点的位置 [n×2][n \times 2]
  • nn 个尺度参数 [n×1][n \times 1]
  • nn 个方向参数 [n×1][n \times 1]
  • nn 个 128 维描述子 [n×128][n \times 128]

匹配时,只需要计算两张图像描述子之间的欧氏距离,距离最近的(且通过比值测试的)配对就是匹配。

SIFT 的鲁棒性

SIFT 的匹配能力非常强大:能够处理高达约 60°60° 的视角变化和显著的光照变化(甚至日间 vs 夜间),同时速度足够快可以实时运行。这使得它在很长时间里都是图像匹配的默认选择。

SURF 描述子

SURF(Speeded Up Robust Features)是 SIFT 的快速近似版本,核心思想是用简单的数学操作近似 SIFT 中耗时的计算,在几乎不损失匹配质量的前提下获得约 6 倍的速度提升。

积分图像

SURF 的加速秘诀之一是积分图像(Integral Image)。积分图像 A(x,y)A(x, y) 存储的是原图中 (x,y)(x, y) 左上角所有像素的累加和:

A(x,y)=xx,yyI(x,y)A(x, y) = \sum_{x' \le x,\, y' \le y} I(x', y')

有了积分图像,任意矩形区域的像素和只需要 3 次加减法即可计算——与矩形大小无关:

A(x1,y1,x2,y2)=A(x2,y2)A(x1,y2)A(x2,y1)+A(x1,y1)A(x_1, y_1, x_2, y_2) = A(x_2, y_2) - A(x_1, y_2) - A(x_2, y_1) + A(x_1, y_1)

这意味着用盒式滤波器(box filter)做卷积的代价不随滤波器大小增长——不管盒子多大,每个像素只需要常数次操作。

检测与方向

SURF 的检测器用 Hessian 矩阵的行列式,但将二阶高斯导数用盒式滤波器近似:R(x,σ)DxxDyy(0.9Dxy)2R(x, \sigma) \approx D_{xx} D_{yy} - (0.9 D_{xy})^2,利用积分图像快速计算。

SIFT 在图像金字塔中缩小图像不同,SURF 固定图像大小,增大滤波器的尺寸来实现多尺度检测——这也是利用了积分图像的常数时间计算特性。

方向估计用 Haar 小波响应:在半径 r=6sr = 6sss 为关键点尺度)的圆形区域内计算 xxyy 方向的 Haar 小波响应,将它们作为向量表示在极坐标图上,用 60°60° 的滑动窗口求向量和,最长的向量和方向即为主方向。

描述子构建

  1. 将归一化后的兴趣区域(20s×20s20s \times 20s)分成 4×44 \times 4 个子区域
  2. 在每个子区域内计算 Haar 小波响应 dxdx(水平)和 dydy(垂直),用高斯核加权
  3. 每个子区域汇总 4 个统计量:dx\sum dxdx\sum |dx|dy\sum dydy\sum |dy|
  4. 拼接 4×4×4=644 \times 4 \times 4 = 64 维描述子

dx\sum dxdy\sum dy 编码了梯度的主方向,dx\sum |dx|dy\sum |dy| 则反映了区域的纹理粗糙程度——平坦区域所有值都接近零,强纹理区域绝对值之和很大。

GIST 描述子

GIST 是一种描述整个图像或较大区域「整体氛围」的描述子,不是用于关键点匹配,而是用于场景分类。

  1. 对图像应用一组 Gabor 滤波器(不同尺度和方向)
  2. 将图像划分为 4×44 \times 4 个单元格
  3. 在每个单元格内计算所有滤波器响应的均值
  4. 拼接得到 4×4×N4 \times 4 \times N 维描述子(NN 为滤波器数量)

GIST 编码的是图像梯度的粗略空间分布——它回答的是「这张图是户外场景还是室内?是城市街道还是自然风景?」而非「这个角点在哪里」。

二值描述子

SIFTSURF 的描述子是浮点向量,存储和比较都需要浮点运算。对于移动设备或需要极高速度的应用,二值描述子(Binary Descriptor)是一种更轻量的选择:描述子是一个比特串,匹配用 Hamming 距离(异或后数 1 的个数),比浮点欧氏距离快得多。

LBP

局部二值模式(Local Binary Pattern, LBP)是最早的二值描述子之一。对每个像素,比较它与周围 8 个邻居的亮度大小,大于中心为 1,否则为 0,得到一个 8 位二进制编码:

LBP=k=07sign(IkIc)2k\text{LBP} = \sum_{k=0}^{7} \text{sign}(I_k - I_c) \cdot 2^k

LBP 对光照整体偏移完全不变(因为只比较相对大小)。

CS-LBP(Center-Symmetric LBP)是一个变体:不再比较邻居与中心,而是比较对称位置的一对邻居,并引入一个阈值 tt

CS-LBP=k=03sign(IkIk+4t)2k\text{CS-LBP} = \sum_{k=0}^{3} \text{sign}(I_k - I_{k+4} - t) \cdot 2^k

例如比较 I0I_0I4I_4I1I_1I5I_5 等,得到 4 位编码。阈值 tt 的作用是忽略微小的亮度差异,进一步增强了对噪声的鲁棒性。

BRIEF

BRIEF(Binary Robust Independent Elementary Features)更加激进:在图像块内随机选取 nn 对像素点,对每对比较亮度大小,得到 nn 位二值串:

fn(P)=[τ(P;x1,y1),,τ(P;xn,yn)]{0,1}nf_n(P) = [\tau(P; x_1, y_1), \ldots, \tau(P; x_n, y_n)] \in \{0, 1\}^n

其中 τ(P;x,y)={1if P(x)>P(y)0otherwise\tau(P; x, y) = \begin{cases} 1 & \text{if } P(x) > P(y) \\ 0 & \text{otherwise} \end{cases}

随机点对的分布从高斯采样:xG(0,S2/25)x \sim G(0, S^2/25)BRIEF 简单、快速,匹配只需异或和 popcount 操作,是第一个专为图像块匹配设计的二值描述子。

采样策略的选择

BRIEF 的性能很大程度上取决于点对的采样方式。原论文测试了 5 种几何分布:

策略 采样方式 特点
G I (x,y)(x, y) 均匀随机 基准,点对分布杂乱
G II (x,y)(x, y) 均从 G(0,S2/25)G(0, S^2/25) 采样 点对集中在中心附近
G III xG(0,S2/25)x \sim G(0, S^2/25)yG(x,S2/100)y \sim G(x, S^2/100) yyxx 附近采样,点对较短
G IV 从粗量化的极坐标网格中随机选取 空间均匀但离散化
G V xx 固定为中心,yG(0,S2/25)y \sim G(0, S^2/25) 所有比较都以中心为参照

实验表明 G II(各向同性高斯)在大多数场景下表现最好——它既不像 G V 那样过于集中(丢失外围信息),也不像 G I 那样完全随机(缺乏结构)。随着视角变化增大,所有策略的识别率都下降,但 G V 下降最快,说明过于依赖中心像素的策略泛化能力较差。

ORB:旋转不变的 BRIEF

BRIEF 的一个关键缺陷是缺乏旋转不变性——图像旋转后,固定的点对位置不再对应相同的空间关系。ORB(Oriented FAST and Rotated BRIEF)通过以下方式解决这个问题:先用 FAST 检测关键点并利用灰度质心法(Intensity Centroid)估计方向,然后将 BRIEF 的点对坐标按该方向旋转后再进行比较。ORB 是开源的(SIFTSURF 曾长期受专利保护),在移动端应用中非常流行。

基于 CNN 的描述子

传统描述子(SIFTSURFLBPBRIEF)都是手工设计的——人为决定了用什么特征(梯度方向、像素比较)以及如何组织(直方图、随机采样)。深度学习时代的思路是:让神经网络从数据中学习最优的描述子。

SIFT 论文的引用量超过 70000 次,是计算机视觉史上被引最多的论文。但它还是最好的吗?深度学习能否打败这个 20 年前的手工方法?这个问题驱动了一系列 CNN 描述子的研究。

MatchNet:统一特征与度量学习

MatchNet 的核心想法是同时学习描述子和比较度量,而不是像传统方法那样分别设计。

架构上,MatchNet 由两部分组成:

  1. 特征网络(Feature Network):一个深层 CNN(Conv0 → Pool0 → Conv1 → Pool1 → Conv2 → Conv3 → Conv4 → Pool4 → Bottleneck),以 Siamese 方式处理两个图像块,输出两个特征向量
  2. 度量网络(Metric Network):三个全连接层(FC1 → FC2 → FC3 + Softmax),接收两个特征向量的拼接,输出匹配/不匹配的概率

关键设计是将匹配问题转化为分类问题,使用交叉熵损失训练:

E=1ni=1n[yilog(y^i)+(1yi)log(1y^i)]E = -\frac{1}{n} \sum_{i=1}^{n} \bigl[y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i)\bigr]

其中 yi{0,1}y_i \in \{0, 1\} 是真实标签,y^i\hat{y}_i 是网络预测的匹配概率。训练用 SGD 优化,负样本通过储备采样器(Reservoir Sampler)采集,以解决正负样本不均衡的问题。

测试时分两阶段进行:先用特征网络为所有图像块生成描述子,再将描述子配对输入度量网络计算匹配分数。特征网络的输出可以缓存复用,但度量网络仍需对每一对做前向传播。

DeepCompare:多种架构探索

DeepCompare 系统地探索了 CNN 比较图像块的三种架构:

2-Channel:直接将两个图像块叠为 2 通道输入,送入一个 CNN 后接判决层。这种架构中不存在显式的「描述子」概念——网络直接从原始像素对中学习比较。

Siamese:两个共享权重的 CNN 分支分别处理两个图像块,输出的特征在判决网络中比较。

2-Channel 2-Stream:最有意思的变体。它包含两个并行的 2-channel 流——中心流(Central)和外围流(Surround),分别处理图像块的中心区域和完整区域,允许网络在两个不同分辨率上进行比较。最终两个流的特征拼接后送入判决层。

DeepCompare 的主要缺点是:所有架构都是成对操作,无法独立地为单个图像块生成可复用的描述子。每次新的比较都需要完整的前向传播,这在大规模检索场景中效率很低。

DeepDesc:SIFT 的直接替代

DeepDesc 的目标很明确:训练一个 Siamese CNN,使其输出的 128 维向量可以用 L2 距离直接比较——作为 SIFT 描述子的即插即用替代品。

网络只有 3 层卷积,结构简洁:

卷积核 通道数 后处理
1 7×77 \times 7 32 Tanh → L2 Pool
2 5×55 \times 5 64 减法归一化 → Pool
3 3×33 \times 3 128 Pool → 128-D 输出

输入为 64×6464 \times 64 的图像块。训练使用配对铰链损失(Pairwise Hinge Loss):

l(x1,x2)={D(x1)D(x2)2p1=p2max(0,CD(x1)D(x2)2)p1p2l(\bm{x}_1, \bm{x}_2) = \begin{cases} \|D(\bm{x}_1) - D(\bm{x}_2)\|_2 & p_1 = p_2 \\ \max(0,\, C - \|D(\bm{x}_1) - D(\bm{x}_2)\|_2) & p_1 \ne p_2 \end{cases}

匹配对的损失直接最小化距离;不匹配对只在距离小于阈值 CC 时才产生梯度,将它们推开到至少 CC 远。

DeepDesc 的一个关键发现是:难负样本挖掘(Hard Negative Mining)对性能至关重要。正负样本天然不均衡(不匹配的配对远多于匹配的),如果随机采样负样本,网络很容易只学会区分「明显不同」的图像块。通过专门挑选那些距离很近但实际不匹配的「难」负样本来训练,描述子的区分力大幅提升。

PN-Net / TFeat:三元组学习

PN-Net 和 TFeat 使用三元组网络(Triplet Network):同时输入锚点 p1p_1、正样本 p2p_2(与锚点匹配)和负样本 nn(不匹配),三者共享同一个 CNN

训练目标是让三元组内最小的负距离仍然大于正距离:

Loss=f(D(p1)D(p2)2,  D(p1)D(n)2,  D(p2)D(n)2)\text{Loss} = f\bigl(\|D(p_1) - D(p_2)\|_2,\; \|D(p_1) - D(n)\|_2,\; \|D(p_2) - D(n)\|_2\bigr)

其中 ff 优化正距离与负距离之间的比值。CNN 结构为 6 层:

操作
1 Spatial Convolution(7,7)32(7,7) \to 32
2 Tanh
3 MaxPooling(2,2)(2,2)
4 Spatial Convolution(6,6)64(6,6) \to 64
5 Linear {128,256}\to \{128, 256\}
6 Tanh

与 DeepDesc 的配对方法相比,三元组方法更高效地利用了训练数据——一个三元组同时提供了正负两种约束。

描述子受关键点与方向的影响

一个容易被忽视的事实是:描述子的性能不仅取决于描述子本身,还取决于配合使用的关键点检测器和方向估计器。在 Strecha、DTU 和 Webcam 三个数据集上的实验表明,同一个描述子搭配不同的关键点,性能差异显著。这暗示了一个重要的方向:如果能将检测和描述联合优化,应该能获得更好的整体性能。

LIFT:端到端学习的完整流程

LIFT(Learned Invariant Feature Transform)将这个直觉推向极致——将检测、方向估计和描述子构建统一到一个端到端可微的网络中:

ImageDETScore MapsoftargmaxCropORIRotDESC描述向量\text{Image} \xrightarrow{\text{DET}} \text{Score Map} \xrightarrow{\text{softargmax}} \text{Crop} \xrightarrow{\text{ORI}} \text{Rot} \xrightarrow{\text{DESC}} \text{描述向量}

每个模块(DET、ORI、DESC)都是一个 CNN。模块之间通过 Spatial Transformer Network 和 softargmax 等可微操作连接——这些「胶水」层的关键作用是保持可微性,使梯度可以从描述子一直回传到检测器。

训练使用四元组 (P1,P2,P3,P4)(P_1, P_2, P_3, P_4)P1,P2P_1, P_2 是对应关键点,P3P_3 是不对应的关键点,P4P_4 是非关键点。全局损失函数包含两项:

min{fμ,gϕ,hρ}γLclass(P1,P2,P3,P4)+Lpair(P1,P2)\min_{\{f_\mu, g_\phi, h_\rho\}} \sum \gamma \mathcal{L}_\text{class}(\bm{P}^1, \bm{P}^2, \bm{P}^3, \bm{P}^4) + \mathcal{L}_\text{pair}(\bm{P}^1, \bm{P}^2)

  • Lclass\mathcal{L}_\text{class}:分类损失,通过 softmax 驱动检测器 fμf_\mu 正确区分关键点 vs 非关键点
  • Lpair\mathcal{L}_\text{pair}:配对损失,最小化对应关键点经过完整 pipeline(检测 → 裁剪 → 旋转 → 描述)后输出描述子之间的 L2 距离

三个可学习模块——检测器 fμf_\mu、方向估计器 gϕg_\phi、描述子 hρh_\rho——在同一个损失函数下联合优化。

LIFT 在 DTU 数据集上的匹配数量(平均 98.5)远超 SIFT(平均 34.1),展示了端到端学习的优势。更关键的是组件协同效应的递进验证:

  1. SIFT 描述子 + SIFT 关键点 → 基准性能(NN mAP 0.325\approx 0.325
  2. LIFT 描述子 + SIFT 关键点 → 性能提升(描述子更好)
  3. LIFT 描述子 + LIFT 关键点 → 性能最高(NN mAP 0.55\approx 0.55

这说明各组件为彼此优化LIFT 的检测器学会了产生对 LIFT 描述子最有利的关键点,反之亦然——单独替换任何一个组件都不如整体替换效果好。

描述子的演进与权衡

描述子的发展经历了几个阶段:

flowchart LR
    A["SIFT 及变体<br/>(~2004)"] --> B["学习型方法<br/>(~2007)"]
    B --> C["二值描述子<br/>(~2010)"]
    C --> D["CNN 方法<br/>(~2015)"]

    classDef era fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    class A,B,C,D era

在不同维度上,各类描述子的特性有所不同:

描述子 维度 速度 鲁棒性 适用场景
SIFT 128 (float) 极强 通用匹配、3D 重建
SURF 64 (float) 实时匹配
GIST 4×4×N4 \times 4 \times N 场景级 场景分类(非关键点匹配)
LBP 8 (binary) 极快 纹理分类、人脸识别
BRIEF nn (binary) 极快 移动端实时匹配
CNN 描述子 128-256 慢(需 GPU) 极强 高精度匹配

区分力与泛化能力的谱系

描述子设计中最核心的权衡是区分力(Discriminative Power)与泛化能力(Generalization Power)之间的关系。这不是一个非此即彼的选择,而是一个连续的谱系:

级别 方式 区分力 泛化能力 例子
原始像素 保留全部空间信息 最高 最低 模板匹配
采样 保留部分空间信息 BRIEF
局部无序 子区域内统计,丢弃局部空间 SIFT
全局直方图 完全丢弃空间信息 最低 最高 颜色直方图

从左到右,描述子逐步丢弃空间信息——每丢弃一层,对几何变化的容忍度就增加一点,但区分不同图像块的能力也随之下降。好的描述子需要在两者之间找到合适的平衡点。SIFT 的成功正是因为它巧妙地处于这个谱系的中间位置——4×44 \times 4 的子区域保留了粗略的空间布局,每个子区域内的直方图又容忍了微小的空间偏移。

局部特征的价值

回顾两章的内容,局部特征(关键点 + 描述子)的价值可以总结为四点:

  • 多视图匹配的基础:找到独特且可重复的局部区域,是三维重建、全景拼接等下游任务的关键
  • 降低复杂度:通过选择少量有区分力的点,将全图比较简化为关键点级别的比较
  • 无需分割且抗遮挡:描述子直接在局部区域上计算,不依赖全局分割,对杂乱背景和部分遮挡天然鲁棒
  • 对变化鲁棒:经过归一化处理后,描述子对中等程度的视角变化、噪声和模糊保持稳定

现状与趋势

在图像块级别的匹配数据集上,学习方法已经超越了手工设计方法。但在图像级别的实际匹配中,学习方法与手工方法的差距并不显著——除了 LIFT 这样的端到端方法。值得注意的是,在跨域场景(如可见光到红外)中,手工设计的描述子反而更具适应性,因为它们不依赖特定数据集的统计分布。此外,CNN 方法在欧氏空间中操作(输出向量可以直接计算 L2 距离),这对于更广泛的应用场景(如最近邻搜索、聚类)非常重要。