ORB-SLAM2學習1 convert.h Frame.h


寫在前面: 

  orb_slam是自己學習的第一個完整的開源slam系統,將自己的粗略理解寫成博客,有理解不到位和出錯的地方還望各位大神前輩指出。文中涉及的公式理論,主要是參考了ORB_SLAM論文和高博的視覺SLAM14講,希望大家共同進步。博客的主要內容是對各個函數代碼的理解,網上也有很多優秀的博客可以參考。

如:

http://www.cnblogs.com/shang-slam/

http://www.fengbing.net/

 

1.Convert.h

  這一頭文件的作用是將g2o類型的數據,cv類型的數據,vector類型的數據進行轉換。里面的實現都很簡單,不必細說。

2.Frame.h

  這個頭文件里面包含了Frame類,論文中沒有提到的是,這里實現的時候,講圖像划分成很多網格,網格里面對應有關鍵點,加快匹配。 

    1.Frame(const Frame &frame);

 復制構造函數.主要注意的事情:將frame中格子里面的東西一個個拷貝到當前幀,設置當前幀的位姿。

 

   2.Frame(const cv::Mat &imLeft, const cv::Mat &imRight, const double &timeStamp, ORBextractor* extractorLeft, ORBextractor* extractorRight, ORBVocabulary* voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth); 3.Frame(const cv::Mat &imGray, const cv::Mat &imDepth, const double &timeStamp, ORBextractor* extractor,ORBVocabulary* voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth); 4.Frame(const cv::Mat &imGray, const double &timeStamp, ORBextractor* extractor,ORBVocabulary* voc, cv::Mat &K, cv::Mat &distCoef, const float &bf, const float &thDepth);

構造函數:分別表示:雙目,RGBD,和單目的構造函數。

具體實現:首先給這幀圖像一個編號mnId,然后確定將在這個圖像金字塔的哪層提取特征,得到金字塔的系數。緊接着提取ORB特征,計算不失真的關鍵點,划分網格,將關鍵點分配到個個網格里面去用於加速匹配。

 

  // Extract ORB on the image. 0 for left image and 1 for right image. 5 void ExtractORB(int flag, const cv::Mat &im);

  說明:提取圖像的orb 特征,提取完之后,關鍵點存在了公共變量mvKeys中,描述子存在了公共變量mDescriptors中。

 

    // Compute Bag of Words representation. 6 void ComputeBoW();

說明:  計算該幀的ORB特征,輸出的結果存放在了全局公共變量mBowVec,和mFeatVec中。mFeatVec是啥樣子呢?- -> public std::map<NodeId, std::vector<unsigned int> >,也就是說這個特征向量里面是個map ,map 的第一個元素代表的是Node編號,第二個元素代表的是與第一個元素的NodeID對應的所有特征點的集合。意思就是,將特征點聚類起來了。。。。。。每一類我們都能知道有哪些特征點。(存的是第四層 (從葉子節點向上數)的節點里的特征點)

 

  7 void SetPose(cv::Mat Tcw);  

  設置當前幀的位資。

 8 void UpdatePoseMatrices();

  更新下,公共的R ,T ,O(相機的中心)

 

    // Returns the camera center.  9 inline cv::Mat GetCameraCenter(){ return mOw.clone(); } // Returns inverse of rotation  10 inline cv::Mat GetRotationInverse(){ return mRwc.clone(); }

返回公共全局變量。

 

 11  bool isInFrustum(MapPoint* pMP, float viewingCosLimit);

說明:判斷地圖點是不是在視錐里面,並將合適的地圖點存起來,用於跟蹤。兩個參數都是輸入。

具體實現:第一步:計算這個地圖點在世界坐標系下的坐標,然后經過變化,得到該點在相機坐標系下的坐標->得到像素坐標。

第二步:檢驗計算觀測角。啥叫觀測角?觀測角,就是兩個向量的夾角,第一個向量是相機中心連接這個的點的空間三維點組成的向量,另一個向量是所有能看到這個點的幀的相機中心與空間三維點組成的向量的平均值向量。接下來就是說,如果該點的視差滿足要求,這個點就能用於跟蹤,然后再設置各種可以用來跟蹤的參數。

 

 

  12  bool PosInGrid(const cv::KeyPoint &kp, int &posX, int &posY);

說明:posX, posY是輸出的該關鍵點在格子中的位置。

具體做法:該點橫(縱)坐標減去,格子最小的橫(縱)坐標,然后除以每個格子的寬(高)。

 

  13  vector<size_t> GetFeaturesInArea(const float &x, const float &y, const float &r, const int minLevel=-1, const int maxLevel=-1) const;

說明: x, y, r 是輸入,r表示的是離x,y多遠處的范圍minLevel,maxLevel,限定了一個金字塔范圍,就是說每個格子里面的每個關鍵點,都得在這個金字塔層數范圍內才能被選中輸出到vector<size_t>里面。

 

 14 void ComputeStereoMatches();

說明:這個函數是用於雙目的時候,用於匹配左右兩邊圖像的關鍵點的。結果改變的是兩個公有變量 mvDepth 和mvuRight 。左右兩邊的關鍵點一旦匹配好了。就會計算出這個點(左邊),深度,和與左邊點匹配的右邊點的ID。

主 要實現:第一步:在右邊圖像的金字塔第0層找出行數nRows,然后生成一個二維數組大小是nRows*200,每行可以最多裝200個關鍵點。

第二步:講右邊圖像的所有關鍵點按一定的標准放到這些行里面,然后匹配。這樣做的目的是為了加快匹配。根據匹配好的結果,在右邊關鍵點實際所在的金字塔層,又繼續匹配,選出最好的匹配,(這里的實現沒怎么看懂....),最后得到mvDepth ,和mvuRight.

 

  15  void ComputeStereoFromRGBD(const cv::Mat &imDepth);

 說明:就是將地圖點與其深度對應起來。

 

  16  cv::Mat UnprojectStereo(const int &i);

說明:返回的是,編號為 i的三維點在世界坐標系下的坐標加上相機中心的坐標。

 

私有函數:

1  void UndistortKeyPoints();

說明:計算該幀關鍵點的去除畸變后的位置,在構造函數里面調用。結果放在了公有變量 mvKeyUn 中。這個函數主要調用OPENCV函數............

 

2  void ComputeImageBounds(const cv::Mat &imLeft);

說明:計算的是去除畸變后,圖像的邊界,在構造函數中調用。得到的是 mnMinX,mnMaxX,mnMinY,mnMaxY. 去除畸變之后的圖像范圍。。。

具體做法:將圖像的行數和列數(去除畸變之前圖像最大的邊界范圍)按一定的順序放到一個4*2的矩陣里,經過去畸變校准之后得到的東西,就是我們想要的去除畸變后的圖像邊界。

 

3 void AssignFeaturesToGrid();

說明:就是將這一幀的關鍵點,放入到我們划分的格子nGrid[i][j]中去。目的是加快匹配速度。在構造函數里面調用。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM