匹配问题
把手机相机对着一张桌子拍一张照片,然后向旁边走半米再拍一张。对你来说,这两张图显然拍的是同一张桌子。可对机器人而言,它们只是两片看起来完全不同的亮度数字网格——每个像素都移动了,光照变了,桌角落在了新的坐标上。那么机器到底怎样判断照片 A 里那个深色桌角,就是照片 B 里那个同一个真实桌角呢?
这一个问题——“这里的哪个点和那里的哪个点是同一个?”——支撑着大量的机器人技术。全景拼接需要它,在视频里跟踪一个物体需要它,估计机器人在两帧之间移动了多远(即里程计)需要它,构建一间陌生房间的地图同样需要它。一旦拿到可靠的点对点对应关系,许多原本困难的问题,突然就能用几何方法解出来了。
最朴素的想法——把照片 A 里的一小块图块在照片 B 的每个位置上滑动,找出匹配最好的地方——几乎能用,但它既慢又脆弱。一面空白的白墙,几乎在任何位置都同样匹配得上,于是你什么也学不到。解决办法是“挑剔两次”:先只挑那些真正有辨识度的点,再把每个点描述得足够紧凑,让两个点之间的比较既快又稳。这两个想法就是关键点与描述子,本指南剩下的部分都在把它们一步步搭起来。
关键点:哪些点值得留下
图像关键点是系统认定足够有辨识度、值得跟踪的某个像素位置。经典的赢家是角点——也就是亮度在两个不同方向上同时急剧变化的地方,比如窗框两条边相交的拐角。斑点(小而圆的暗点或亮点)也算。要避开的,是那些沿着一条线方向模棱两可的位置。
对于角点为何特殊,有一个很简洁的直觉。想象把一个小窗口在图像上滑动,问问下面的图块变化了多少。在一面平墙上,往任何方向滑都没有变化——没用。在一条直边上,沿着边滑动毫无变化,所以你分不清自己在边上的哪个位置——这就是孔径问题。只有在角点处,往任意方向滑动都会让图块改变,于是位置在 x 和 y 两个方向上都被钉死了。角点检测器,不过是对这种“两个方向都敏感”特性的快速检验罢了。
从一张照片里,检测器可能会返回几百到几千个关键点。这本身已是巨大的胜利:机器人不必再拿每个像素和每个像素去比,而只需对一组稀疏、可信赖的地标进行推理。但仅有一个 (x, y) 位置还不足以拿来匹配——两个不同的角点,作为坐标看起来完全一样。每个关键点都还需要一枚指纹。
描述子,以及匹配究竟怎样进行
特征描述子就是那枚指纹:一串紧凑的数字,由关键点周围的小图块算出,用来刻画它的邻域长什么样。一种常见做法是,在一格格子区里记录亮度增加的方向(即局部梯度),再把它们打包成一个比如 128 维的向量。巧妙之处在于:要让同一块图块,即使经过旋转、轻微缩放或亮度变化,仍能得出几乎相同的向量——描述子的目标,是对那些与“它是哪个点”无关的干扰因素保持不变。
一旦每个关键点都带上了描述子,匹配就变成了寻找“近似双胞胎”。对照片 A 里的某个关键点,你在照片 B 中找出数值上最接近的那个描述子——它的最近邻——并把这一对提出来作为一组匹配。如果两个描述子的数字列表之间的距离很小,就说它们“接近”。
- 在两张图里都检测关键点,并为每个关键点计算一个描述子。
- 对图 A 里的每个描述子,按描述子距离在图 B 中找出它的最近邻。
- 施加比值检验:只有当最近邻明显比次近邻更近时才保留这组匹配,从而剔除模棱两可的配对。
- 进行外点剔除(例如 RANSAC):拟合一个真匹配必须共同满足的几何模型,再丢弃任何违背它的配对。
第三步和第四步,比初学者想象的更重要。即便是好的描述子也会产出错误匹配——重复纹理(一排一模一样的砖)和杂乱背景,注定让某些配对纯属张冠李戴。比值检验会在最佳与次佳候选几乎打平时丢掉这组匹配,因为“几乎打平”意味着系统其实分不清它们。随后外点剔除来强加大局约束:刚性场景两个视角之间所有正确的匹配,都必须服从同一个一致的相机运动,于是像 RANSAC 这样的方法会悄悄地猜出那个运动,数一数有多少匹配与之相符,再把其余的投票淘汰掉。判定哪个检测对应哪个,正是困扰每个感知系统的数据关联问题。
稀疏匹配与稠密光流
到目前为止的一切都是稀疏的:几百个地标,在时间或视角上可能相隔很远的图像之间进行匹配。对于相反的情形,还有一种互补的方法——两个连续的视频帧,相差仅几毫秒,几乎什么都没怎么动。这时你可以稠密地跟踪运动,估计出每一个像素都跑到了哪里。那一整片逐像素运动向量的场,就是光流。
光流依赖一个简单的假设:一小块图块从这一帧到下一帧亮度保持不变,只是稍微挪动了一点。正因为挪动极小,这种方法根本不需要抗旋转的指纹——它只是把每块图块推到下一帧里亮度对得上的地方。这让光流非常擅长平滑跟踪和运动估计,但一旦出现大跳变、快速运动或场景突变,“小位移”假设崩塌,它就失效了。注意,孔径问题在这里又回来了:在一条长直边内部,光流能感知到跨边的运动,却感知不到沿边的运动。
两条路最终都汇向同一份回报。一旦你知道匹配的点在两个相机视角之间是怎么移动的,几何就会把相机自身的运动交到你手上——这正是视觉里程计的核心;再与惯性传感器融合,它就成了视觉惯性里程计。把这些地标累积成一张持久的地图,并在重访某地时再次认出它们,你就跨进了 SLAM 的领域:匹配到的特征,正是把漂移的地图重新对齐的回环闭合线索。把同样的对应关系推广到一处静态场景的许多张照片上,你就能重建出它的三维形状——这是运动恢复结构要干的活。那个不起眼的匹配点,正是这一切的种子。