《視覺SLAM十四講精品總結》12 迴環檢測建立字典
阿新 • • 發佈:2018-11-15
這部分並不難,主要用到了一個詞袋模型(BoW),對兩幅影象的特徵點進行匹配。
建立字典:一個單詞是某一類特徵的集合,字典生成是個聚類問題,可使用K-meams演算法。
匹配相似性:暴力計算量太大,可用二分查詢提升效率,以及k叉樹表達字典(層次聚類)
目錄:
feature_training.cpp
loop_closure.cpp
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; /*************************************************** * 本節演示瞭如何根據data/目錄下的十張圖訓練字典 * ************************************************/ int main( int argc, char** argv ) { // 1.讀入10張影象 cout<<"reading images... "<<endl; vector<Mat> images; for ( int i=0; i<10; i++ ) { string path = "./data/"+to_string(i+1)+".png";//to_string數值轉為字串 images.push_back( imread(path) ); } // 2.檢測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 ); } //3.建立字典 cout<<"creating vocabulary ... "<<endl; //建立一個字典物件 DBoW3::Vocabulary vocab; //呼叫create函式,用描述子陣列建立 vocab.create( descriptors ); cout<<"vocabulary info: "<<vocab<<endl; //save函式輸出字典壓縮包 vocab.save( "vocabulary.yml.gz" ); cout<<"done"<<endl; return 0; }
基本流程:讀入照片、檢測ORB特徵點、建立字典
- 載入影象,路徑的表達
vector<Mat> images;
for ( int i=0; i<10; i++ )
{
string path = "./data/"+to_string(i+1)+".png";
images.push_back( imread(path) );
}
- 建立字典部分
DBoW3::Vocabulary vocab;//建立字典物件
vocab.create( descriptors );//描述子作為內容
vocab.save( "vocabulary.yml.gz" );//輸出字典壓縮包
loop_closure.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 ) { // 1.讀入影象和字典庫 cout<<"reading database"<<endl; DBoW3::Vocabulary vocab("./vocabulary.yml.gz"); // DBoW3::Vocabulary vocab("./vocab_larger.yml.gz"); // use large vocab if you want: if ( vocab.empty() ) { cerr<<"Vocabulary does not exist."<<endl; return 1; } 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) ); } // NOTE: in this case we are comparing images with a vocabulary generated by themselves, this may leed to overfitting. 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 ); } // we can compare the images directly or we can compare one image to a database // images : //影象與影象對比 cout<<"comparing images with images "<<endl; for ( int i=0; i<images.size(); i++ ) { DBoW3::BowVector v1; vocab.transform( descriptors[i], v1 ); for ( int j=i; j<images.size(); j++ ) { DBoW3::BowVector v2; //transform函式將影象轉為描述向量 vocab.transform( descriptors[j], v2 ); //score函式,傳入兩個詞袋描述向量,取得相似性得分 double score = vocab.score(v1, v2); cout<<"image "<<i<<" vs image "<<j<<" : "<<score<<endl; } cout<<endl; } // 用字典建立資料集 cout<<"comparing images with database "<<endl; // 建立資料集,把所有描述向量加進去,query函式輸出與所有圖匹配結果 DBoW3::Database db( vocab, false, 0); for ( int i=0; i<descriptors.size(); i++ ) db.add(descriptors[i]); cout<<"database info: "<<db<<endl; for ( int i=0; i<descriptors.size(); i++ ) { DBoW3::QueryResults ret; db.query( descriptors[i], ret, 4); // max result=4 cout<<"searching for image "<<i<<" returns "<<ret<<endl<<endl; } cout<<"done."<<endl; }
- 讀入生成的字典庫 DBoW3::Vocabulary vocab("./vocabulary.yml.gz");
- 匹配時暴力匹配所有影象
/** * 影象與影象之間的檢測比較簡單:
* 根據影象的描述子,呼叫transform()函式將影象轉化成描述向量,
* 根據描述向量,呼叫score()函式求兩張影象相似性得分。
- 影象與整個資料集匹配
*字典建立資料集
*所有影象描述子加進去
*利用query函式輸出各個圖匹配結果