ORB-SLAM2代碼詳讀-------特徵點檢測

目錄

1 特徵點檢測的基本步驟

1.1 輸入圖像

1.2 圖像金字塔

1.3 計算每層FAST關鍵點

1.4 計算FAST關鍵點的描述子

1.5 計算特徵點的尺度座標


1 特徵點檢測的基本步驟

  輸入圖像----圖像金字塔----計算每層FAST關鍵點----計算FAST關鍵點描述子

 先列出這個類裏面關鍵的函數和變量

//創建圖像金字塔,這裏每層只是降採樣
 void ComputePyramid(cv::Mat image);
//計算每一層的關鍵點
 void ComputeKeyPointsOctTree(std::vector<std::vector<cv::KeyPoint> >& allKeypoints);
//控制關鍵點個數
std::vector<cv::KeyPoint> DistributeOctTree(const std::vector<cv::KeyPoint>& vToDistributeKeys, const int &minX,const int &maxX, const int &minY, const int &maxY, const int &nFeatures, const int &level);
//計算描述子多需要的點的位置
std::vector<cv::Point> pattern;
//需要提取的總的特徵點個數
int nfeatures;
//尺度因子
double scaleFactor;
//金字塔層數
int nlevels;
//初始FAST閾值
int iniThFAST;
//最小FAST閾值
int minThFAST;
//每層關鍵點個數
std::vector<int> mnFeaturesPerLevel;

  下面來看看每個步驟對應的代碼

   代碼有些地方也沒有完全搞明白,歡迎交流!

1.1 輸入圖像

   特徵點檢測的入口是ORBextractor類,其中最主要的是

void operator()( cv::InputArray image, cv::InputArray mask,
      std::vector<cv::KeyPoint>& keypoints,
      cv::OutputArray descriptors);

 參數包括輸入圖像image、輸入模板mask(好像沒有用到)、存儲關鍵點的向量keypoints、存儲描述子的數組descriptors

1.2 圖像金字塔

 這裏使用的是簡化版的圖像金字塔,每一層大小被改變,都是上一層*尺度因子,函數是

void ORBextractor::ComputePyramid(cv::Mat image)

  輸入參數image,主要目的是計算每層圖像,並且處理邊界

  主要的語句如下:

//每層縮放係數
float scale = mvInvScaleFactor[level];
//計算圖像大小
Size sz(cvRound((float)image.cols*scale), cvRound((float)image.rows*scale)); 
//將圖像進行縮放(雙線性插值)
resize(mvImagePyramid[level-1], mvImagePyramid[level], sz, 0, 0, cv::INTER_LINEAR); 
//處理邊界 
copyMakeBorder(mvImagePyramid[level], temp, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD, EDGE_THRESHOLD,BORDER_REFLECT_101+BORDER_ISOLATED);     

1.3 計算每層FAST關鍵點

void ORBextractor::ComputeKeyPointsOctTree(vector<vector<KeyPoint> >& allKeypoints)

  輸入參數allKeypoints,用來存儲每層關鍵點

  步驟:

           將每層圖像分成多個30*30的小格子(cell)

           在每個小格子裏面找FAST關鍵點(如果第一次沒找到,就減小閾值再找,裏面包括非極大值抑制)

           根據事先給定的每層圖像中特徵點的多少(根據尺度,按等比數列的方式給出)來進行局部關鍵點剔除

//給定總特徵點個數,根據等比數列求出最下面圖像特徵點個數
float nDesiredFeaturesPerScale = nfeatures*(1 - factor)/(1 - (float)pow((double)factor, (double)nlevels))
//記錄每層特徵點個數
mnFeaturesPerLevel[level] = cvRound(nDesiredFeaturesPerScale); //四捨五入
//計算上面一層特徵點個數
nDesiredFeaturesPerScale *= factor;

         進行局部關鍵點剔除的函數是(這個函數最多將圖像分成長/寬*16塊,在每塊中選取一個響應值最大的保留)//todo  是不是有點少  //參數:每層找到的關鍵點、有效區域、每層允許的最多關鍵點個數、金字塔層數

vector<cv::KeyPoint> ORBextractor::DistributeOctTree(const vector<cv::KeyPoint>& vToDistributeKeys, const int &minX,const int &maxX, const int &minY, const int &maxY, const int &N, const int &level)

         最後計算每個關鍵點-質心向量的夾角(裏面計算灰度質心的公式有點變形)

static void computeOrientation(const Mat& image, vector<KeyPoint>& keypoints, const vector<int>& umax) 

1.4 計算FAST關鍵點的描述子

  首先對每層圖像進行高斯濾波,然後計算256維描述子,計算描述子函數如下:

  //輸入參數:關鍵點位置 kpt、操作圖像 img、要比較的位置pattern、描述子輸出地址

static void computeOrbDescriptor(const KeyPoint& kpt,const Mat& img, const Point* pattern,uchar* desc)

計算步驟是:

                     先進行座標變換(原來的基底乘以過渡矩陣,這裏的過渡矩陣是旋轉矩陣,旋轉角爲質心與關鍵點連線與原來X軸的夾角)

                     然後按照原來定義的比較點位置進行比較,輸出描述向量

1.5 計算特徵點的尺度座標

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章