第4章:视觉传感器与里程计——单目/双目/深度相机原理、视觉特征提取与匹配、视觉里程计基本原理

各位同学,欢迎来到第四章。这一章我们聊聊视觉传感器和视觉里程计。说实话,视觉传感器在导航系统里是个“又爱又恨”的角色——它信息量大,但处理起来也麻烦。我最早做融合导航时,对视觉数据的态度是“能用,但别太依赖”。后来项目做多了,才慢慢摸透它的脾气。

4.1 单目、双目、深度相机:三种“眼睛”的区别

先说说这三种相机。它们都是“看”世界,但看的方式完全不同。

4.1.1 单目相机

单目相机,说白了就是一个普通摄像头。它只能拍到二维图像,没有深度信息。你想想看,一张照片里,远处的山和近处的树,在图像上都是像素点,你怎么知道哪个远哪个近?

单目相机靠的是“运动恢复结构”(Structure from Motion, SfM)。相机移动时,同一物体在不同帧里的位置会变化,通过这种变化可以反推出深度。但有个问题——它只能得到相对深度,不知道绝对尺度。比如你看到一个杯子,你知道它离你“大概这么远”,但具体是1米还是2米?单目说不准。

我个人的经验:单目相机在室内短距离还行,但一到室外长距离,尺度漂移就很明显。我曾经在一个AGV项目里只用单目做定位,结果跑了50米后,位置误差直接飙到2米多。后来加了IMU才稳住。

4.1.2 双目相机

双目相机模仿人的双眼。两个镜头相隔一定距离(基线),同时拍两张图。通过左右图的视差,就能算出深度。原理很简单:左眼看到物体在A点,右眼看到在B点,两点差越大,物体越近。

双目相机的优势是:不需要运动就能得到深度。静态场景下也能用。而且它不依赖外部光源,白天黑夜都能工作(当然,太暗了也不行)。

但缺点也很明显:计算量大。每帧都要做立体匹配,找左右图的对应点。分辨率越高,计算越慢。我记得有一次在嵌入式平台上跑双目,640x480的图像,匹配一帧要200多毫秒,根本跑不到实时。后来降分辨率到320x240,才勉强到15帧。

4.1.3 深度相机

深度相机(比如Kinect、Intel RealSense)直接输出深度图。它用结构光或ToF(飞行时间)技术,主动发射光信号,测量反射时间或光斑变形来算深度。

好处是:深度数据直接拿,不用算。而且精度高,近距离(0.5-5米)能到毫米级。但坏处是:怕强光。户外阳光下,结构光会被淹没,ToF也会受干扰。所以深度相机基本是室内专用。

类型 深度获取方式 优点 缺点 典型应用
单目 运动恢复结构 成本低、结构简单 无绝对尺度、依赖运动 手机AR、无人机
双目 立体匹配 静态可用、不依赖外部光 计算量大、基线限制 机器人、自动驾驶
深度相机 结构光/ToF 直接输出深度、精度高 怕强光、距离有限 室内导航、手势识别

4.2 视觉特征提取与匹配:ORB vs SIFT

有了图像,下一步就是找特征点。特征点就是图像里“特别”的地方——角点、边缘、纹理丰富区域。这些点在不同帧之间要能稳定匹配,才能算出运动。

4.2.1 SIFT:老牌劲旅

SIFT(Scale-Invariant Feature Transform)是2004年提出的算法。它最大的特点是尺度不变性——物体放大缩小,特征点还能认出来。而且它对旋转、光照变化也很鲁棒。

但SIFT有个致命伤:太慢了。一张640x480的图像,提取SIFT特征要几百毫秒。在嵌入式平台上基本跑不动。我当年在ARM Cortex-A9上试过,一帧要1.2秒,直接放弃。

4.2.2 ORB:轻量级选手

ORB(Oriented FAST and Rotated BRIEF)是2011年提出的。它结合了FAST角点检测和BRIEF描述子,并加入了旋转不变性。说白了,就是又快又够用

ORB的速度比SIFT快两个数量级。同样640x480的图像,ORB提取+匹配只要10-20毫秒。在嵌入式平台上,这是唯一能跑实时的方案。

避坑指南:我曾经在一个项目里用ORB做特征匹配,结果发现匹配错误率很高。后来排查发现,是图像纹理太弱(白墙、光滑地面),ORB提取的特征点太少。解决办法是:加一些人工纹理,或者改用深度学习特征。

// ORB特征提取示例(OpenCV)
cv::Ptr<cv::ORB> orb = cv::ORB::create(500); // 提取500个特征点
std::vector<cv::KeyPoint> keypoints;
cv::Mat descriptors;
orb->detectAndCompute(image, cv::noArray(), keypoints, descriptors);

// 特征匹配
cv::BFMatcher matcher(cv::NORM_HAMMING);
std::vector<cv::DMatch> matches;
matcher.match(descriptors1, descriptors2, matches);

4.3 视觉里程计(Visual Odometry)基本原理

视觉里程计,说白了就是用相机算运动。它通过连续帧之间的特征匹配,估计相机的位姿变化(旋转和平移)。

4.3.1 基本流程

  1. 图像获取:从相机拿到连续帧。
  2. 特征提取:每帧提取ORB或SIFT特征点。
  3. 特征匹配:找相邻帧之间的对应点。
  4. 运动估计:用匹配点对解算旋转矩阵R和平移向量t。
  5. 位姿更新:把当前帧的位姿累加到全局轨迹上。

运动估计这一步,常用的是对极几何(单目)或PnP(已知3D点)。对极几何通过本质矩阵E分解出R和t,但只能得到相对尺度。PnP则需要已知的3D点(比如从深度相机或双目得到)。

核心公式:对极约束

x₂ᵀ · E · x₁ = 0

其中x₁、x₂是匹配点归一化坐标,E是本质矩阵。通过SVD分解E得到R和t。

4.3.2 视觉里程计的痛点

视觉里程计看着简单,实际坑很多。我总结几个常见问题:

  • 尺度漂移:单目VO没有绝对尺度,轨迹会越走越歪。解决办法是加IMU或已知尺寸的参照物。
  • 特征丢失:快速运动或纹理不足时,特征匹配会失败。我建议保持帧率在20fps以上,减少帧间运动量。
  • 累积误差:每帧估计都有小误差,时间长了就变成大误差。所以VO必须配合回环检测或全局优化。

我的小技巧:在VO里加一个“关键帧”策略。不是每帧都做运动估计,而是只选那些运动足够大的帧作为关键帧。这样能减少计算量,还能避免小运动带来的噪声。

4.4 本章知识体系图

下面这张图展示了本章的核心逻辑:从传感器选型,到特征处理,再到运动估计,最后是融合定位。

视觉传感器与里程计知识体系 视觉传感器 特征提取与匹配 视觉里程计 单目 / 双目 / 深度 ORB / SIFT 对极几何 / PnP 输出:帧间位姿变化(R, t) 与IMU/GNSS融合(后续章节) 图:视觉里程计在融合导航中的位置

4.5 实践建议

最后,给各位一些实战建议:

  • 选传感器看场景:室内用深度相机,室外用双目,低成本用单目+IMU。
  • 特征提取选ORB:除非你算力过剩,否则别碰SIFT。ORB在嵌入式平台上足够用。
  • 别忘了回环检测:纯VO会漂,加回环检测能大幅提升精度。我习惯用DBoW2做词袋模型。
  • 多传感器融合是王道:视觉+IMU+轮速计,能互补短板。后面几章会详细讲。

警告:视觉里程计在光照剧烈变化(比如从室内到室外)时,特征匹配会大量失败。我曾经在隧道出口处直接丢跟踪,后来加了曝光补偿才解决。建议在图像预处理阶段做直方图均衡化。

好了,这一章就到这里。视觉里程计是个大话题,我们只讲了基础。下一章会深入讲视觉+IMU的紧耦合融合,那才是真正好戏开场的地方。


公众号:蓝海资料掘金营,微信deep3321