目錄
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軸的夾角)
然後按照原來定義的比較點位置進行比較,輸出描述向量