這里寫目錄標題
- 1、特征點提取
- (1)GFTT算法提取特征點
- A.What(什么是GFTT)
- B.GFTT的優勢
- C.How(如何使用GFTT算法提取圖像特征點)
- (2)FAST算法提取特征點
- A.What(什么是FAST角點)
- B.FAST角點的強度值
- C.How(如何使用FAST算法提取圖像特征點)
- (3)BRISK算法提取特征點
- A.What
- B.How(如何使用BRISK算法提取特征點)
- (4)ORB算法提取特征點
- A.What
- B.How(如何使用ORB算法提取特征點)
- 2、描述子
- (1)What
- (2)How(如何衡量兩個特征點相似性)
- A.周圍像素的特征
- B.周圍像素的描述子
- C.基于深度學習的方法
- (3)SIFT描述子實現關鍵點匹配
- A.原理
- B.How(如何得到SIFT特征點和描述子)
- (4)ORB描述子實現關鍵點匹配
- A.原理
- B.BRIEF算法計算描述子
- C.How(如何得到ORB特征點描述子)
- 3、圖像匹配
- 4、圖像配準
1、特征點提取
(1)GFTT算法提取特征點
A.What(什么是GFTT)
GFTT算法是對Harris的改進:一是針對特征點聚集問題,使用局部區域最大值解決;二是針對不均勻分布問題,使用限制兩個特征點之間最短具體解決
B.GFTT的優勢
- 穩定性好:GTFF 算法檢測到的角點相對更加穩定,不容易出現聚簇現象,且角點信息的丟失和位置偏移也相對較少
- 參數可調節:通過設置相關參數,如最大角點數目、角點可接受的最小特征值、角點之間的最小距離等,可以根據具體需求和圖像特點來優化特征點的提取效果
C.How(如何使用GFTT算法提取圖像特征點)
int GetKpsByGTFF(const cv::Mat& imSrcGray, std::vector<cv::KeyPoint>& vkps)
{//對參數進行檢測if(imSrcGray.empty() ){ return -1; }if(imSrcGray.channels()!=1){ return -2; }if(!vkps.empty()){ vkps.clear(); }//提取圖像特征點cv::Ptr<cv::GFTTDetector> ptrGFTT = cv::GFTTDetector::create(500, //關鍵點的最大數量0.01, //角點的最小特征值15); //角點之間允許的最短距離ptrGFTT->detect(imSrcGray, vkps); //調用算法探測圖像上的特征點if(vkps.size()==0){ return -3; }else{ return 1; }}
(2)FAST算法提取特征點
A.What(什么是FAST角點)
以某個點為中心做一個圓,根據圓上的像素值判斷該 點是否為關鍵點。由于不需要作復雜的梯度計算,該方法提取關鍵點的效率很高,在實時性要求高的條件下使用很廣
B.FAST角點的強度值
計算中心點像素與 認定的連續圓弧上的像素的差值,然后將這些差值的絕對值累加,就能得到角點強度
C.How(如何使用FAST算法提取圖像特征點)
int GetKpsByFAST(const cv::Mat& imSrcGray, std::vector<cv::KeyPoint>& vkps)
{//對參數進行檢測if(imSrcGray.empty() ){ return -1; }if(imSrcGray.channels()!=1){ return -2; }if(!vkps.empty()){ vkps.clear(); }//使用FAST算法提取特征點cv::Ptr<cv::FastFeatureDetector> ptrFAST = cv::FastFeatureDetector::create(65);//65表關鍵點強度,即FAST角點的強度值(response)ptrFAST->detect(imgSrcGray, vkps);if(vkps.size()==0){return -3;}else{return 1;}
}
(3)BRISK算法提取特征點
A.What
基于FAST的多尺度快速檢測器。首先下采樣構建圖像金字塔,然后對金字塔所有圖像應用FAST特征檢測。只有是局部最大值的像素才可能成 為關鍵點。這個條件滿足后,比較這個點與上下兩層的相鄰像素的評分;如果它的評分在尺度上 也更高,那么就認為它是一個興趣點。
B.How(如何使用BRISK算法提取特征點)
int GetKpsByBRISK(const cv::Mat& imSrcGray, std::vector<cv::KeyPoint>& vkps)
{//對參數進行檢測if(imSrcGray.empty() ){ return -1; }if(imSrcGray.channels()!=1){ return -2; }if(!vkps.empty()){ vkps.clear(); }//使用BRISK算法提取圖像特征點cv::Ptr<cv::BRISK> ptrBRISK = cv::BRISK::create(60, 5); //60表示FAST角點的強度值必須達到60,才有可能被認為是關鍵點;5表示金字塔層數ptrBRISK->detect(imSrcGray, vkps);if (vkps.size() == 0){return -3;}else{return 1;}
}
(4)ORB算法提取特征點
A.What
基于FAST的多尺度帶方向的特征檢測算法。
- 特征點方向:每個被檢測的興趣點總是關聯了一個方向。在FAST的中心點的圓形區域內計算重心,中心與重心的組成的向量即為該關鍵電的方向。
B.How(如何使用ORB算法提取特征點)
int GetKpsByORB(const cv::Mat& imSrcGray, std::vector<cv::KeyPoint>& vkps)
{//對參數進行檢測if(imSrcGray.empty() ){ return -1; }if(imSrcGray.channels()!=1){ return -2; }if(!vkps.empty()){ vkps.clear(); }//使用ORB算法對圖像進行特征點提取cv::Ptr<cv::ORB> ptrORB = cv::ORB::create(500, 1.2, 8);//500:特征點數量;1.2:金字塔的縮放尺度;8:金字塔層數ptrORB->detect(imSrcGray, vkps);if (vkps.size() == 0){return -3;}else{return 1;}
}
2、描述子
(1)What
A圖像的某一點和B圖像的某一點如果對應現實世界的同一點,那么它們就應該是匹配的。這也是特征點匹配的目的
從數學的角度分析:要進行特征點的匹配,就應該考慮兩個關鍵點的相似性,因此,如何衡量兩個關鍵點的相似性成為了我們要考慮的首要問題
(2)How(如何衡量兩個特征點相似性)
A.周圍像素的特征
計算該特征點指定區域的均值、方差、梯度等,用作衡量標準。但單個的值很容易受到環境的印象,具有不穩定性,在工程實踐中不會采用這些特征
B.周圍像素的描述子
使用一些專門為特征點設計的描述子(可以理解為一個向量),這些描述子能夠捕捉到角點的獨特特性,通過比較描述子的差異來衡量相似性。在工程實踐中一般采用特征點的描述子來進行特征點的匹配
C.基于深度學習的方法
利用訓練好的卷積神經網絡模型提取角點的深層特征,然后比較這些特征的相似度
(3)SIFT描述子實現關鍵點匹配
A.原理
step01:首先選取關鍵點周圍16×16像素點,將其分為4×4大小的子區域,總共16個子區域。
step02:然后對每個子區域統計八個方向的梯度方向直方圖,每個子區域用這8個統計結果進行描述。
step03:最后得到8×16 = 128 個數據作為描述符向量。
B.How(如何得到SIFT特征點和描述子)
#include <opencv2/features2d/features2d.hpp>
int GetKpsAndDescriptorBySIFT(const cv::Mat& imSrc,std::vector<cv::KeyPoint>& vkps,cv::Mat& matDescriptor)
{//對輸入的參數進行檢查if (imSrc.empty()){return -1;}if (imSrc.channels() != 1){return - 2;}if (!vkps.empty()){vkps.clear();}//提取關鍵點cv::Ptr<cv::SIFT> ptrSIFT = cv::SIFT::create(500, 3);ptrSIFT->detect(imSrc, vkps);if (vkps.size() == 0){return -3;}//計算關鍵點的描述子ptrSIFT->compute(imSrc, vkps, matDescriptor);if (matDescriptor.empty()){return -4;}return 1;
}
(4)ORB描述子實現關鍵點匹配
A.原理
采用BRIEF算法提取關鍵點的描述子
B.BRIEF算法計算描述子
- 為減少噪聲干擾,先對圖像進行高斯濾波(方差為2,高斯窗口為9x9)
- 以特征點為中心,取s×s的鄰域窗口,在窗口內隨機選取一對點,比較二者像素的大小,進行二進制賦值:若p(x) > p(y),則賦值為1;若p(x) ≤ p(y),則賦值為0,其中p(x)、p(y)分別是隨機點x=(u1,v1)、y=(u2,v2)的像素值。
- 在窗口中隨機選取n對隨機點(一般n=256),重復步驟2的二進制賦值,形成一個二進制編碼,即特征描述子。
C.How(如何得到ORB特征點描述子)
int GetKpsAndDescriptorByORB(const cv::Mat& imSrc,std::vector<cv::KeyPoint>& vkps,cv::Mat& matDescriptor)
{//對輸入的參數進行檢查if (imSrc.empty()){return -1;}if (imSrc.channels() != 1){return - 2;}if (!vkps.empty()){vkps.clear();}//提取ORB關鍵點cv::Ptr<cv::Feature2D> ptrORB = cv::ORB::create(500, 1.2, 8);ptrORB->detect(imSrc, vkps);if (vkps.size() == 0){return -3;}//計算關鍵點的描述子ptrORB->compute(imSrc, vkps, matDescriptor);if (matDescriptor.empty()){return -4;}return 1;
}