当前位置: 首页 > news >正文

ORB-SLAM3 关键帧相似度计算

float si = mpVoc->score(F->mBowVec, pKFi->mBowVec);这行代码的核心作用,是计算当前帧与某个候选关键帧在视觉上的相似度得分,得分越高,两者在视觉上就越相似。

这个得分是后续筛选和聚合候选关键帧的基础,也是ORB-SLAM3重定位流程中“粗匹配”的关键一环。

下面将从得分计算方式和算法实现两个层面来详细解释:

📊 得分计算方式:基于词袋向量的相似度

mpVoc->scoreDBoW2库提供的接口,其输入是两个词袋向量(BowVector),输出是一个浮点数,代表它们的相似度。

  • 输入是什么?F->mBowVec是当前帧的词袋向量,pKFi->mBowVec是候选关键帧的词袋向量。每个向量都是一个std::map<WordId, WordValue>,记录了该帧图像包含的“视觉单词”及其对应的TF-IDF权重。

  • 如何计算相似度?DBoW2库提供了多种评分方法,例如L1范数、L2范数、卡方距离、点积等。ORB-SLAM3通常使用L1范数评分(L1Scoring),其本质是计算两个词袋向量的加权曼哈顿距离。得分越高,代表两帧共享的视觉单词越多、权重越大,它们在视觉内容上就越相似。

⚙️ 算法实现:为什么这一步是关键?

理解了得分计算方式后,我们再把这个步骤放回DetectRelocalizationCandidates函数的上下文中,就能更清楚地看到它的重要性:

  1. 从“粗筛”到“精筛”:在这行代码之前,系统通过倒排索引mvInvertedFile)快速找出了所有与当前帧有共视单词的关键帧,这是第一步的“粗筛”。

  2. 计算精确得分score()函数就是第二步的“精筛”。它基于TF-IDF权重,为每一个通过粗筛的关键帧计算一个精确的相似度得分。TF-IDF确保了那些罕见但更具区分度的视觉单词(高区分度)对得分的贡献更大,而普遍出现的单词(如天空、墙壁)的贡献被削弱。

  3. 指导后续筛选:这个得分会被用于后续的筛选逻辑。例如,代码中常见的策略是:只保留得分大于最高分75%的候选帧,然后将这些高得分帧的得分累加到它们共视图中的邻居帧上,形成“累积得分”,从而找到视觉上最相似的“区域”,而非单个孤立的帧。

💎 总结

mpVoc->score(...)这行代码,本质上是利用DBoW2库提供的相似度计算接口,将两个词袋向量转换为一个量化的视觉相似度得分。这个得分是重定位候选帧筛选流程的核心依据,它让系统能够快速地从成百上千个候选帧中,精确定位到与当前帧视觉上最相似的几个关键帧。

补充:

mpVoc->score(F->mBowVec, pKFi->mBowVec)这行代码,其核心是调用DBoW2库来计算两个词袋向量的相似度得分。在ORB-SLAM3中,默认使用的是L1范数评分(L1 Scoring)方法。

下面,将从代码结构、计算原理和具体例子三个方面来拆解这个过程。


🧱 1. 代码结构:DBoW2的评分家族

在DBoW2库中,score是一个定义在基类GeneralScoring中的纯虚函数。它通过一个宏__SCORING_CLASS来定义不同的评分方法。

cpp

// Thirdparty/DBoW2/DBoW2/ScoringObject.h[reference:6] namespace DBoW2 { /// Base class of scoring functions class GeneralScoring { public: // 纯虚函数:计算两个向量的得分 virtual double score(const BowVector &v, const BowVector &w) const = 0; // ... }; }

ORB-SLAM3支持多种评分方法,并通过宏来声明:

评分方法宏定义是否需要归一化
L1范数评分 (L1 Scoring)__SCORING_CLASS(L1Scoring, true, L1)
L2范数评分 (L2 Scoring)__SCORING_CLASS(L2Scoring, true, L2)
卡方评分 (ChiSquare Scoring)__SCORING_CLASS(ChiSquareScoring, true, L1)
KL散度评分 (KL Scoring)__SCORING_CLASS(KLScoring, true, L1)
巴氏距离评分 (Bhattacharyya Scoring)__SCORING_CLASS(BhattacharyyaScoring, true, L1)
点积评分 (Dot Product Scoring)__SCORING_CLASS(DotProductScoring, false, L1)

ORB-SLAM3默认使用的是L1Scoring。这类评分通常要求向量先进行归一化(mustNormalize返回true)。

⚙️ 2. 核心原理:L1范数评分如何计算?

L1Scoring的计算分为两步:向量归一化计算相似度

步骤一:向量归一化 (Normalization)

在进行相似度计算前,需要对词袋向量vw进行L1归一化

对于一个词袋向量v,它包含了一系列(单词ID, 权重)对。L1归一化就是让向量中所有权重的绝对值之和等于1

公式
v_norm = v / ||v||₁

其中,||v||₁ = Σ |v_i|是向量中所有元素绝对值之和。

步骤二:计算L1相似度

归一化后,两个向量的L1相似度通过以下交集(Intersection)方法计算:

公式
score(v, w) = Σᵢ min(v_i, w_i)

这个公式的含义是:遍历两个向量中所有共同的单词,将其权重中较小的那个累加起来。

注意:由于L1归一化保证了向量元素和为1,这个交集得分天然地落在[0, 1]区间内。得分越高,表示两个向量共享的视觉单词越多,图像越相似。


💡 3. 实例演示:从公式到数字

让我们通过一个具体的例子来理解这个过程。

假设我们有两个极度简化的词袋向量,词汇表里只有单词A、B、C三个视觉单词。

  • 图像1 (当前帧):包含单词A(权重2) 和 单词B(权重3)。

    • 向量v = {A: 2, B: 3}

  • 图像2 (候选关键帧):包含单词B(权重4) 和 单词C(权重1)。

    • 向量w = {B: 4, C: 1}

步骤一:L1归一化
  • ||v||₁ = 2 + 3 = 5

  • v_norm = {A: 2/5, B: 3/5} = {A: 0.4, B: 0.6}

  • ||w||₁ = 4 + 1 = 5

  • w_norm = {B: 4/5, C: 1/5} = {B: 0.8, C: 0.2}

步骤二:计算L1相似度

找到两个向量共有的单词(即交集),这里是单词B

  • 对于单词B:min(v_norm(B), w_norm(B)) = min(0.6, 0.8) = 0.6

  • 最终的相似度得分:score = 0.6

这个0.6就是mpVoc->score()函数返回的float si值。

💎 4. 总结

float si = mpVoc->score(F->mBowVec, pKFi->mBowVec);

  1. mpVoc是一个指向DBoW2::Vocabulary类的指针,它内部维护着一个DBoW2::L1Scoring类型的评分对象。

  2. score()函数接收两个BowVector作为输入。

  3. 函数内部首先对两个向量进行L1归一化

  4. 然后计算它们归一化后权重的交集和,得到一个[0, 1]范围内的浮点数。

  5. 这个数值就是两帧图像在视觉上的相似度得分,分数越高,视觉上越相似。

关于:

累加的结果绝不会大于 1,最大值就是1。原因其实很简单:

📐 数学证明

假设有两个经过L1 归一化的非负向量vw,它们的所有元素和都等于 1:

∑ivi=1,∑iwi=1i∑​vi​=1,i∑​wi​=1

对于每个共同的单词i,我们取min(v_i, w_i)。由于min(v_i, w_i) ≤ v_i(也 ≤w_i),所以对整个向量求和:

∑imin⁡(vi,wi)≤∑ivi=1i∑​min(vi​,wi​)≤i∑​vi​=1

同理,它也 ≤ 1。因此累加和≤ 1,并且只有当两个向量完全相等(非零元素完全相同且权重一致)时,才能达到1

💡 直观理解

你可以把 L1 归一化后的向量看作一个“概率分布”,每个单词的权重就是它出现的相对频率。两个分布的交集(共同单词中较小的频率)的总和,不可能超过整个分布的总概率(即 1)。这就像两个馅饼,你只能取它们重叠的那部分,最多也只能取到整个馅饼(1)。

所以,mpVoc->score()返回的相似度得分始终在[0, 1]之间,非常合理。

http://www.jsqmd.com/news/1106407/

相关文章:

  • 武汉农商银行13名员工手工拼接碎币,帮失智老人兑换养老金
  • okbiye 领衔|九大 AI 毕业论文写作工具横向实测,适配全学段学术创作需求
  • AI时代的HR系统选型:从“挑功能”到“挑能力底座”
  • 《2026年AI数字人直播系统深度评测:从 “伪” 到 “真” 进化》
  • 一体式步进伺服电机在油漆生产产线中的应用
  • 2026中小企业选择高性价比制氮机公司推荐
  • AI客服智能体开始参与商品推荐,企业正在重构客户决策支持方式
  • MySQL 迁移实战——如何实现真正的“零改造“平滑切换
  • 2026长春靠谱人造草坪供应商,选这家不踩坑
  • 耐压仪一开机5kV,屏幕数据直接跳飞?换过三个牌子才找到答案
  • backstage~openapi的接入与protobuf的对比
  • 缠论自动化分析终极指南:5分钟掌握ChanlunX核心价值
  • Unlocker终极指南:如何在Windows/Linux上免费运行macOS虚拟机
  • AI写教材神器来袭!低查重一键生成,20万字教材框架瞬间搞定!
  • Java毕设项目:基于 SpringBoot 的宠物诊疗设备调度管理系统的设计与实现 基于 SpringBoot 的宠物疫苗信息公示与统计系统的设计与实现 (源码+文档,讲解、调试运行,定制等)
  • MCP协议深度解读:200+服务器实现背后的协议演进与生产环境部署
  • 2026 年专业的 4K HDMI Over IP 网传芯片方案商
  • 3分钟免费解锁QQ音乐格式限制:QMCFLAC2MP3让你的音乐真正自由播放
  • 2026 GitHub最受欢迎的10个AI开源项目盘点
  • 用箭头标注精准修改 AI 图片,Cowart 项目已获 2k+ Stars
  • `Codex` 和 `Claude Code` 的官方能力都很强,真正麻烦的往往不是工具本身,而是国内这层接入。
  • TVBoxOSC终极指南:如何让电视盒子变身全能媒体中心
  • 国产SSD定制化开发涉及哪些能力层次?固件调参和全链路自研有什么本质区别?
  • cw-omnibus:一本 Android 开发书的全部示例代码
  • [InverseLerp节点]原理解析与实际应用
  • RAG+GEO 深度融合:2026—2027 技术路线与落地效果预测
  • Codex 新手优选的 6 个实用 Skill:让 AI 真正成为你的开发助手
  • 运行codex时出现登录失败:failed to start login server: 以一种访问权限不允许的方式做了一个访问套接字的尝试。 (os error 10013) 解决方案
  • 鼠标革命:让你的普通鼠标在Mac上比触控板更好用!
  • 5分钟搞定Windows和Office永久激活:KMS_VL_ALL_AIO终极指南