从这篇开始,我们正式进入视觉SLAM的前端部分。前端的第一件事就是特征提取——从图像里找出那些"有辨识度"的点,方便后续匹配和跟踪。
特征提取听起来简单,其实是视觉SLAM的地基。地基不牢,后面的位姿估计、建图全都会出问题。面试的时候,特征提取是必考内容,你得清楚ORB、SIFT、SuperPoint各自的特点、优缺点和适用场景。很多面试官自己就做过SLAM系统,对特征提取的理解很深,你得准备好才能过关。
什么是"好"的特征点
在聊具体算法之前,先想想什么样的点算"好"特征。
好特征要有区分度。一面白墙上的点长得都一样,没法用来定位。但墙角、桌角、文字边缘这种地方,每个点都有独特的邻域模式,很容易在不同图像里被识别出来。
好特征要稳定。不管相机怎么动、光照怎么变,这个点都应该能被检测到。如果一个特征只在特定角度才出现,那它的实用性就很差。
好特征要计算快。SLAM是实时系统,每帧图像的处理时间有严格限制。特征提取如果太慢,整个系统就跑不起来。
这三个要求——区分度、稳定性、速度——往往是互相矛盾的。不同的特征提取算法就是在三者之间做不同的取舍。
SIFT:经典但慢
SIFT(Scale-Invariant Feature Transform)是2004年David Lowe提出的。它的核心思想是在尺度空间里找极值点,然后用128维的描述子来表征每个特征点周围的外观。
SIFT的优点很明显:尺度不变性(不同距离拍同一个物体,特征都能匹配上)、旋转不变性、对光照变化也有不错的鲁棒性。描述子是128维的浮点向量,区分度很高。
但SIFT有个致命问题:慢。构建尺度空间、检测极值点、计算描述子,整个流程的计算量很大。在嵌入式平台上,一帧图像提取SIFT特征可能要几百毫秒,根本满足不了实时要求。
import cv2 # SIFT特征提取(OpenCV) sift = cv2.SIFT_create() keypoints, descriptors = sift.detectAndCompute(gray_img, None) # descriptors: N×128的float32数组SIFT的专利在2020年过期了,现在OpenCV里可以免费使用。但在SLAM这种实时场景下,SIFT已经很少被用作默认选择了。
ORB:SLAM的主流选择
ORB(Oriented FAST and Rotated BRIEF)是2011年提出的,专门为实时应用设计。它是视觉SLAM里用得最多的特征提取方法,ORB-SLAM系列就靠它吃饭。
ORB的思路很直接:用FAST算法检测特征点,用BRIEF算法生成描述子,再加上旋转不变性的改进。
FAST角点检测极快。它看一个像素周围的16个像素,如果有连续N个像素都比中心像素亮或暗一定阈值,就认为这是个角点。计算量非常小,只需要做几次加减法和比较,适合实时系统。FAST有三个常用变体:FAST-9、FAST-10和FAST-12,数字代表需要连续满足条件的像素数量,越多越严格但越稳定。
BRIEF描述子是二进制的。它通过比较特征点邻域内随机选取的像素对的灰度值,生成一个256位的二进制串。匹配的时候用汉明距离,一个XOR运算就搞定了,比浮点运算快得多。
# ORB特征提取(OpenCV) orb = cv2.ORB_create(nfeatures=2000) keypoints, descriptors = orb.detectAndCompute(gray_img, None) # descriptors: N×32的uint8数组(256位=32字节)ORB的缺点是描述子的区分度不如SIFT。256位的二进制描述子能表达的信息量有限,在纹理简单的场景下容易出现误匹配。而且FAST检测的角点在视角变化大的时候不够稳定。
SuperPoint:深度学习的降维打击
SuperPoint是2018年提出的,用深度学习来训练特征提取器。它的思路是:让神经网络自己学什么样的点是好特征,而不是用手工设计的规则。
SuperPoint的输出和ORB类似——关键点和描述子。但描述子是256维的浮点向量,信息量比ORB的256位二进制描述子丰富得多。关键点的检测也更稳定,对光照变化和视角变化的鲁棒性都更好。
# SuperPoint推理(简化版) from superpoint import SuperPoint sp = SuperPoint() result = sp.run(gray_img) keypoints = result['keypoints'] # N×2坐标 descriptors = result['descriptors'] # N×256浮点描述子SuperPoint的缺点是计算量比ORB大。虽然比SIFT快,但在低端嵌入式平台上仍然有压力。而且它需要GPU才能跑满速度,纯CPU推理会慢一些。
SuperPoint的网络结构分为两部分:关键点检测头和描述子提取头。两个头共享底层的特征提取网络,所以计算效率还不错。关键点检测头输出每个像素是角点的概率图,描述子提取头输出每个像素的256维描述子向量。训练数据是用虚拟场景合成的,这让它对真实场景的泛化能力有时候不够理想。
后来还出现了SuperPoint的改进版本,比如R2D2和ALIKE。ALIKE专门针对SLAM场景做了优化,在保持精度接近SuperPoint的同时,计算速度快了不少。这些新方法值得关注,但目前还没有成为SLAM的主流选择。
面试中怎么对比这三种方法
面试官问"ORB和SIFT的区别",你要从四个维度回答:
速度:ORB远快于SIFT。ORB的特征提取可以在几毫秒内完成,SIFT要几十到几百毫秒。
描述子维度:SIFT是128维浮点,ORB是256位二进制。ORB匹配用汉明距离,SIFT用欧氏距离。ORB匹配更快,但区分度稍差。
不变性:SIFT的尺度和旋转不变性更好。ORB只有旋转不变性(FAST本身不具备尺度不变性,ORB通过构建图像金字塔来弥补)。
实际选择:实时SLAM系统(ORB-SLAM、VINS)普遍用ORB。离线三维重建、图像匹配等对精度要求高的场景可以用SIFT。SuperPoint是新兴方案,精度好但部署门槛高。
简单总结一下:ORB是性价比之王,SIFT是精度之王,SuperPoint是未来之星。做SLAM选ORB,做三维重建考虑SIFT,有GPU资源可以试SuperPoint。
"为什么ORB-SLAM选择ORB而不是SIFT?" 因为SLAM是实时系统,每帧处理时间必须控制在几十毫秒以内。SIFT的特征提取太慢,会拖累整个系统的帧率。ORB虽然描述子区分度差一些,但速度快一个数量级,配合好的匹配策略(比如交叉验证、几何验证),完全能满足SLAM的需求。
"SuperPoint会取代ORB吗?" 短期内不会。SLAM系统对可靠性和实时性的要求很高,深度学习方法的部署复杂度(需要GPU、模型版本管理、推理延迟不确定)是实际落地的障碍。但在算力充足的平台上,SuperPoint确实能提供更好的特征质量。
工程实践中的经验
实际做SLAM项目的时候,特征提取有几个要注意的点。
第一,特征点的数量不是越多越好。太多特征点会增加匹配的计算量,而且低质量的特征点反而引入噪声。ORB-SLAM2默认提取2000个特征点,这个数量在大多数场景下够用了。
第二,特征点要均匀分布。如果所有特征都集中在图像的某个区域(比如纹理丰富的桌面),其他区域(比如白墙)没有特征,位姿估计的鲁棒性会很差。ORB-SLAM用网格化的方式来保证特征点均匀分布。
第三,不同层的特征有不同用途。金字塔底层的特征定位精确但尺度小,顶层的特征尺度大但定位粗糙。好的系统会分层使用不同层级的特征。
第四,特征提取的参数要根据场景调整。室内纹理丰富的环境可以降低特征点数量,室外大场景需要更多特征点。ORB-SLAM允许你配置每帧提取的最大特征点数,根据实际场景调一调,效果会好很多。
特征提取是视觉SLAM的第一步,选对了方法后面的路就顺了。
上一篇:第238篇 SLAM中的优化vs滤波——两大技术路线的选择
下一篇我们聊特征匹配——提取出特征之后,怎么在不同图像之间找到对应的点,以及怎么剔除误匹配。
如果这篇文章对你有帮助,欢迎点赞支持一下,你的鼓励是我持续更新的动力!