標籤:介紹 lse 表示 五個 wait 相關資訊 mes mat 最小
SURF原理詳解:https://wenku.baidu.com/view/2f1e4d8ef705cc1754270945.html
SURF演算法工作原理
選擇映像中的POI(Points of interest) Hessian Matrix
在不同的尺度空間發現關鍵點,非最大訊號壓制
發現特徵點方法、旋轉不變性要求
產生特徵向量
SURF建構函式介紹
C++: SURF::SURF(
double hessianThreshold, --閾值檢測器使用Hessian的關鍵點,預設值在
300-500之間
int nOctaves=4, -- 4表示在四個尺度空間
int nOctaveLayers=2, -- 表示每個尺度的層數
bool extended=false,
bool upright=false --表示計算旋轉不變性,不計算的速度更快
)
特徵點繪製
特徵點繪製是為了把檢測出來的Surf特徵點在原圖上繪製出來,這一步是為了把特徵點直觀的顯示出來給我們看,跟整個Surf運算元的特徵提取和匹配流程沒關係。
繪製使用drawKeypoints方法:
void drawKeypoints( const Mat& image,
const vector<KeyPoint>& keypoints,
CV_OUT Mat& outImage,
const Scalar& color=Scalar::all(-1),
int flags=DrawMatchesFlags::DEFAULT
);
第一個參數image:原始映像,可以使三通道或單通道映像;
第二個參數keypoints:特徵點向量,向量內每一個元素是一個KeyPoint對象,包含了特徵點的各種屬性資訊;
第三個參數outImage:特徵點繪製的畫布映像,可以是原映像;
第四個參數color:繪製的特徵點的顏色資訊,預設繪製的是隨機彩色;
第五個參數flags:特徵點的繪製模式,其實就是設定特徵點的那些資訊需要繪製,那些不需要繪製,有以下幾種模式可選:
DEFAULT:只繪製特徵點的座標點,顯示在映像上就是一個個小圓點,每個小圓點的圓心座標都是特徵點的座標。
DRAW_OVER_OUTIMG:函數不建立輸出的映像,而是直接在輸出映像變數空間繪製,要求本身輸出映像變數就是一個初始化好了的,size與type都是已經初始化好的變數
NOT_DRAW_SINGLE_POINTS:單點的特徵點不被繪製
DRAW_RICH_KEYPOINTS:繪製特徵點的時候繪製的是一個個帶有方向的圓,這種方法同時顯示映像的座標,size,和方向,是最能顯示特徵資訊的一種繪製方式。
1 #include <opencv2/opencv.hpp> 2 #include <opencv2/xfeatures2d.hpp> 3 #include <iostream> 4 5 using namespace cv; 6 using namespace cv::xfeatures2d; 7 using namespace std; 8 9 int main(int argc, char** argv) {10 Mat src = imread("test.jpg", IMREAD_GRAYSCALE);11 if (src.empty()) {12 printf("could not load image...\n");13 return -1;14 }15 namedWindow("input image", CV_WINDOW_AUTOSIZE);16 imshow("input image", src);17 18 // SURF特徵點檢測19 int minHessian = 100;20 Ptr<SURF> detector = SURF::create(minHessian);//建立一個surf類對象並初始化21 vector<KeyPoint> keypoints;22 detector->detect(src, keypoints, Mat());//找出關鍵點23 24 // 繪製關鍵點25 Mat keypoint_img;26 drawKeypoints(src, keypoints, keypoint_img, Scalar::all(-1), DrawMatchesFlags::DEFAULT);27 imshow("KeyPoints Image", keypoint_img);28 29 waitKey(0);30 return 0;31 }
繪製匹配點
drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1, const Mat& img2, const vector<KeyPoint>& keypoints2, const vector<DMatch>& matches1to2, Mat& outImg, const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1), const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT );
其中參數如下:
* img1 – 源映像1
* keypoints1 –源映像1的特徵點.
* img2 – 源映像2.
* keypoints2 – 源映像2的特徵點
* matches1to2 – 源映像1的特徵點匹配源映像2的特徵點[matches[i]] .
* outImg – 輸出映像具體由flags決定.
* matchColor – 匹配的顏色(特徵點和連線),若matchColor==Scalar::all(-1),顏色隨機.
* singlePointColor – 單個點的顏色,即未配對的特徵點,若matchColor==Scalar::all(-1),顏色隨機.
*matchesMask – Mask決定哪些點將被畫出,若為空白,則畫出所有匹配點.
*flags—它跟drawKeypoints方法中flags的含義是一樣的。
當僅使用篩選出的最優匹配點進行匹配的時候,意味著會有很多非最優的特徵點不會被匹配,這時候可以設定flags=DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS
1 #include <opencv2/opencv.hpp> 2 #include <opencv2/xfeatures2d.hpp> 3 #include <iostream> 4 5 using namespace cv; 6 using namespace cv::xfeatures2d; 7 using namespace std; 8 9 int main(int argc, char** argv) {10 Mat src = imread("數字.jpg", IMREAD_GRAYSCALE);11 Mat temp = imread("2.png", IMREAD_GRAYSCALE);12 if (src.empty()|| temp.empty()) {13 printf("could not load image...\n");14 return -1;15 }16 namedWindow("input image", CV_WINDOW_AUTOSIZE);17 imshow("input image", src);18 19 // SURF特徵點檢測20 int minHessian = 400;21 Ptr<SURF> detector = SURF::create(minHessian,4,3,true,true);//建立一個surf類檢測器對象並初始化22 vector<KeyPoint> keypoints1, keypoints2;23 detector->detect(src, keypoints1, Mat());//找出關鍵點24 detector->detect(temp, keypoints2, Mat());//找出關鍵點25 26 BFMatcher matcher; //執行個體化一個暴力匹配器27 Mat src_vector, temp_vector;//用來存放特徵點的描述向量28 vector<DMatch> matches; //DMatch是用來描述匹配好的一對特徵點的類,包含這兩個點之間的相關資訊29 //比如左圖有個特徵m,它和右圖的特徵點n最匹配,這個DMatch就記錄它倆最匹配,並且還記錄m和n的30 //特徵向量的距離和其他資訊,這個距離在後面用來做篩選31 32 detector->detectAndCompute(src, Mat(), keypoints1, src_vector);//輸入映像,輸入遮罩,輸入特徵點,輸出Mat,存放所有特徵點的描述向量33 detector->detectAndCompute(temp, Mat(), keypoints2, temp_vector);//這個Mat行數為特徵點的個數,列數為每個特徵向量的尺寸,SURF是64(維)34 35 matcher.match(src_vector, temp_vector, matches); //匹配,資料來源是特徵向量,結果存放在DMatch類型裡面 36 37 //sort函數對資料進行升序排列38 sort(matches.begin(), matches.end()); //篩選匹配點,根據match裡面特徵對的距離從小到大排序39 vector< DMatch > good_matches;40 int ptsPairs = std::min(50, (int)(matches.size() * 0.15));41 cout << ptsPairs << endl;42 for (int i = 0; i < ptsPairs; i++)43 {44 good_matches.push_back(matches[i]);//距離最小的50個壓入新的DMatch45 }46 Mat outimg; //drawMatches這個函數直接畫出擺在一起的圖47 drawMatches(src, keypoints1, temp, keypoints2, good_matches, outimg, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); //繪製匹配點 48 imshow("KeyPoints Image", outimg); 49 50 waitKey(0);51 return 0;52 }
OpenCV——SURF特徵檢測與匹配