对应第12章回环检测的内容
关于前面章节前端和后端的内容,只是看了书中的内容,并没有用C++实现,主要原因是代码量太大,而且示例代码太抽象了...等其他内容学完后再实现吧 如果不自己实现一遍肯定不能完全理解。
回环检测和机器学习是密切相关的,这里书中只简单介绍了一种利用DBoW3库直接完成词典建立和提取的过程,基本没有高含量的东西。
创建词典主要靠以下两个函数:
DBoW3::Vocabulary Vocabulary
Vocabulary.create(Descriptors);
Vocabulary.save("SavePath");
可以看到词典的创建和图片的描述子是相关的,通过描述子特征对相似的类进行聚类并储存
打开和使用已保存的词典只需要利用构造函数:
DBoW3::Vocabulary Vocabulary("SavePath");
之后想要比较两个图片的相似性,只需要调用函数:
Vocabulary.score(V1, V2);
该函数返回一个double值,评价了两个图片的相似性,评分越高越相似。函数的参数为DBoW3::BowVector类型,该值通过Vocabulary.transform()函数获得,该函数是将某一个图片的描述子与词典中的相比较。
DBoW3::BowVector V1;
Vocabulary.transform(Descriptors[i], V1);
最终代码结果(以第10张图为例):
可以看到结果中第九张图与第一张图相似性最高(除去自己),但与其他图区别并不明显,可能需要更好的词典才能达到最好的效果。
附上源码,仅供参考,与示例代码基本类似:
#include <iostream>
#include <vector>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/features2d.hpp>
#include <DBoW3/DBoW3.h>
#include <opencv2/highgui.hpp>
void FeatureTraining(std::vector<cv::Mat>&, std::vector<cv::Mat>&) ;
int main(){
std::vector<cv::Mat> Images;
std::vector<cv::Mat> Descriptors;
FeatureTraining(Images, Descriptors);
//DBoW3::Vocabulary Vocabulary("../vocab_larger.yml.gz");
DBoW3::Vocabulary Vocabulary("../vocabulary.yml.gz");
if(Vocabulary.empty()){
std::cerr << "Vocabulary is empty" << std::endl;
return 1;
}
for (int i = 0; i < Images.size(); i++)
{
DBoW3::BowVector V1;
Vocabulary.transform(Descriptors[i], V1);
for (int j = 0; j < Images.size(); j++)
{
DBoW3::BowVector V2;
Vocabulary.transform(Descriptors[j], V2);
double score = Vocabulary.score(V1, V2);
std::cout << "image " << i << " vs image " << j << " : " << score << std::endl;
}
}
return 0;
}
void FeatureTraining(std::vector<cv::Mat>& Images, std::vector<cv::Mat>& Descriptors){
//std::vector<cv::Mat> Images;
for(int i = 0; i < 10; i++){
cv::Mat Image = cv::imread("../data/"+std::to_string(i+1)+".png");
Images.push_back(Image);
}
//std::vector<cv::Mat> Descriptors;
cv::Ptr<cv::ORB> Detector = cv::ORB::create();
for (int i = 0; i < 10; i++)
{
std::vector<cv::KeyPoint> KeyPoints;
cv::Mat Descriptor;
Detector->detectAndCompute(Images[i], cv::Mat(), KeyPoints, Descriptor);
Descriptors.push_back(Descriptor);
}
DBoW3::Vocabulary Vocabulary;
Vocabulary.create(Descriptors);
Vocabulary.save("../vocabulary.yml.gz");
}