视觉SLAM笔记(58) 字典
视觉SLAM中字典的生成主要通过聚类技术实现。首先,字典由多个单词组成,每个单词代表一组局部特征点,并非单个图像特征点。聚类问题属于无监督机器学习中的典型问题之一(如K-means),其目的是让机器自动发现数据中的规律。
具体来说:
字典的结构:通过从大量图像中提取特征点并进行聚类生成。
创建过程:使用K-means算法将N个特征点聚类为k个单词;也可以通过层次聚类(如k-ary树)扩展K-means的优势。
查找效率:采用树状数据结构(如k-ary树)提升查找速度至对数级别。
代码实现:以ORB特征为例,在C++环境中使用DBoW3库进行训练,并提供相应代码示例。
参考《视觉SLAM十四讲》进一步了解相关内容及应用场景。
视觉SLAM笔记(58) 字典
- 1. 字典的结构
- 2. 创建字典
1. 字典的结构
基于前面的讲解中提到,“字典由大量词汇构成,并且每个词汇都代表着一个概念。” 单一词汇与独立特征点相异。它并非通过单一图像提取而来,而是通过一类特征集合构建而成。因此,在生成过程中的字典构建等价于一种聚类(Clustering)问题。
在无监督机器学习(Unsupervised ML)领域中,聚类问题是一个核心话题。此类问题通常涉及让机器自行寻找数据中的规律,在无监督机器学习中,让机器自行寻找数据中的规律通常涉及一类特定的问题。在自然语言处理领域中,采用Bag of Words方法生成词汇表同样属于这类技术。
在处理大量图像数据时,在特征识别阶段已经获得了N个代表性点位。接着,在构建词汇库的过程中需要确定一个包含k个单词的字典模型,在这种情况下每个单词词义对应着局部区域内的相邻特征点集合。这可以通过经典的 K-means(K 均值)算法来实现。该算法作为一个简单而高效的无监督学习方法,在模式识别领域具有广泛的应用基础。
当给定的数据集包含N个样本时,在目标将数据划分为k个类别的情景下

该算法的基本实现方式是直接而有效的。然而,在实际应用中也面临一些挑战:除了需要预先设定聚类的数量之外,在选择初始中心点时会引入一定的随机性导致结果差异较大;此外还存在计算效率有待提升的问题。针对这些问题的研究者们提出了多种改进方案:例如层次聚类法和 K-means++等改进算法以进一步优化性能综上所述,在应用K-means算法后可以通过数据处理将大量特征点归结为k个核心词汇所构成的词典
现在的问题转化为如何基于图像中的特定特征点,在字典中找到对应的单词。
仍然保留了一种基础思路:即通过将输入与每个词进行对比,并选择最接近的那个作为结果。
这种方法显然是简单且有效的策略。
但是由于字典的一般性要求较高,在实际应用中通常会选择一个包含大量词汇的大规模词库来覆盖当前场景下的各种可能特征。
即便对于仅仅十个词也要一一对应检查来说工作量也不算太大但对于上万个甚至数十万的情况就显得有些吃力了。
由于读者可能已经掌握数据结构知识基础,在常规线性时间复杂度O(n)的查找算法面前显得不够高效。然而,在数据组织有序的情况下,则可以通过二分查找显著提高搜索效率至对数时间复杂度。而在实际应用中常用更为复杂的索引结构如Fabmap中的Chou-Liu树等。
这里介绍另一种较为简单实用的树结构,使用一种 k 叉树来表达字典

它的思路很简单,类似于层次聚类,是 kmeans 的直接扩展
假定我们有 N 个特征点,希望构建一个深度为 d,每次分叉为 k 的树,那么做法如下:

就而言之,在构建语言模型的过程中,在树结构的最底层仍然形成了词汇单元。其中非叶子节点仅作为快速查找辅助结构存在
2. 创建字典
在 VO 部分主要依赖于 ORB 特征描述。
接下来我们将会详细讲解ORB字典的应用方法,并展示其在实际操作中的具体应用。

从 TUM 数据集中选择 10 张图像(存储于 /data 文件夹内),这些图片记录了真实场景的一次连续拍摄过程。
观察发现,在这组图片中,第一张和最后一张影像均源自同一地点。
接下来的任务是评估程序是否能够识别出这一现象。
基于词袋模型框架,在此数据集上构建特征向量时需要首先提取包含这十张图片的关键信息。
需要注意的是,在实际应用中BoW模型通常由外部较大的语料库构建。此外,最好选择与目标场景高度相似的地方作为训练数据源
通常采用规模较大的词汇库——即词汇量越多越好,方便找到匹配当前图像的关键词
但必须控制在不超过计算资源与存储容量的程度
不打算将一个较大的字典文件存储在github上,
因此目前计划基于10张图像训练出一个小规模的字典。
通过引入更多数据进行训练,
构建一个更大规模的模型,
这个方案的实际效果会更好。
此外,
可利用已有的训练结果,
但需要确认所使用的特征类型是否匹配。
现准备开始训练字典,请安装本程序所依赖的 Bag of Words 库。具体来源可通过该GitHub链接获取:https://github.com/rmsalinas/DBow3。在代码的第三方目录中亦可找到该库。此乃一个CMake项目,在完成编译后即可进行安装操作。
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
AI助手
接下来考虑训练字典feature_training.cpp:
#include "DBoW3/DBoW3.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <iostream>
#include <vector>
#include <string>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
// 读取图像
cout << "reading images... " << endl;
vector<Mat> images;
for (int i = 0; i < 10; i++)
{
string path = "../data/" + to_string(i + 1) + ".png";
images.push_back(imread(path));
}
// 检测ORB功能
cout << "detecting ORB features ... " << endl;
Ptr< Feature2D > detector = ORB::create();
vector<Mat> descriptors;
for (Mat& image : images)
{
vector<KeyPoint> keypoints;
Mat descriptor;
detector->detectAndCompute(image, Mat(), keypoints, descriptor);
descriptors.push_back(descriptor);
}
// 创建字典
cout << "creating vocabulary ... " << endl;
DBoW3::Vocabulary vocab;
vocab.create(descriptors);
cout << "vocabulary info: " << vocab << endl;
vocab.save("vocabulary.yml.gz");
cout << "done" << endl;
return 0;
}
AI助手
DBBoW3 的实现过程相对简便
运行此程序:
$ ./feature_training
AI助手
将看到输出的字典信息:

查看输出的字典内容:分支数量 k 设定为 10;树的最大深度 L 设置为 5;总共有 4970 个词汇;当前状态并未达到最大容量限制。然而,在当前阶段还存在未使用的 Weighting 和 Scoring 参数。从字面名称来看,Weighting 即代表权重设置;而Scoring 则对应于评分机制。
参考:
相关推荐:
视觉 SLAM 笔记(57):回路检测问题
视觉 SLAM 笔记(56):位姿图的优化方法
视觉 SLAM 笔记(55):位姿图相关技术
视觉 SLAM 笔记(54):基于 Ceres 框架的操作后端优化
视觉 SLAM 笔记(53):基于 g2o 的操作后端优化
谢谢!
