<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ##基于SURF特征的圖像匹配 SURF算法是著名的尺度不變特征檢測器SIFT(Scale-Invariant Features Transform)的高效變種,它為每個檢測到的特征定義了位置和尺度,其中尺度的值可用于定義圍繞特征點的窗口大小,使得每個特征點都與眾不同。這里便是使用SURF算法提取兩幅圖像中的特征點描述子,并調用OpenCV中的函數進行匹配,最后輸出一個可視化的結果,開發平臺為Qt5.3.2+OpenCV2.4.9。以下給出圖像匹配的實現步驟: 一、輸入兩幅圖像,使用OpenCV中的cv::FeatureDetector接口實現SURF特征檢測,在實際調試中改變閾值可獲得不一樣的檢測結果: ~~~ // 設置兩個用于存放特征點的向量 std::vector<cv::KeyPoint> keypoint1; std::vector<cv::KeyPoint> keypoint2; // 構造SURF特征檢測器 cv::SurfFeatureDetector surf(3000); // 閾值 // 對兩幅圖分別檢測SURF特征 surf.detect(image1,keypoint1); surf.detect(image2,keypoint2); ~~~ 二、OpenCV 2.0版本中引入一個通用類,用于提取不同的特征點描述子。在這里構造一個SURF描述子提取器,輸出的結果是一個矩陣,它的行數與特征點向量中的元素個數相同。每行都是一個N維描述子的向量。**在SURF算法中,默認的描述子維度為64,該向量描繪了特征點周圍的強度樣式。**兩個特征點越相似,它們的特征向量也就越接近,因此這些描述子在圖像匹配中十分有用: ~~~ cv::SurfDescriptorExtractor surfDesc; // 對兩幅圖像提取SURF描述子 cv::Mat descriptor1, descriptor2; surfDesc.compute(image1,keypoint1,descriptor1); surfDesc.compute(image2,keypoint2,descriptor2); ~~~ 提取出兩幅圖像各自的特征點描述子后,需要進行比較(匹配)。可以調用OpenCV中的類cv::BruteForceMatcher構造一個匹配器。cv::BruteForceMatcher是類cv::DescriptorMatcher的一個子類,定義了不同的匹配策略的共同接口,結果返回一個cv::DMatch向量,它將被用于表示一對匹配的描述子。(關于cv::BruteForceMatcher 請參考:[http://blog.csdn.net/panda1234lee/article/details/11094483?utm_source=tuicool](http://blog.csdn.net/panda1234lee/article/details/11094483?utm_source=tuicool)) 三、在一批特征點匹配結果中篩選出評分(或者稱距離)最理想的25個匹配結果,這通過std::nth_element實現。 ~~~ void nth_element(_RandomAccessIterator _first, _RandomAccessIterator _nth, _RandomAccessIterator _last) ~~~ 該函數的作用為將迭代器指向的從_first 到 _last 之間的元素進行二分排序,以_nth 為分界,前面都比 _Nth 小(大),后面都比之大(小),因此適用于找出前n個最大(最小)的元素。 四、最后一步,將匹配的結果可視化。OpenCV提供一個繪制函數以產生由兩幅輸入圖像拼接而成的圖像,而匹配的點由直線相連: ~~~ // 以下操作將匹配結果可視化 cv::Mat imageMatches; cv::drawMatches(image1,keypoint1, // 第一張圖片和檢測到的特征點 image2,keypoint2, // 第二張圖片和檢測到的特征點 matches, // 輸出的匹配結果 imageMatches, // 生成的圖像 cv::Scalar(128,128,128)); // 畫直線的顏色 ~~~ **要注意SIFT、SURF的函數在OpenCV的nonfree模塊中而不是features2d,cv::BruteForceMatcher類存放在legacy模塊中**,因此函數中需要包含頭文件: ~~~ #include <opencv2/legacy/legacy.hpp> #include <opencv2/nonfree/nonfree.hpp> ~~~ 完整代碼如下: ~~~ #include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/legacy/legacy.hpp> #include <opencv2/nonfree/nonfree.hpp> #include <QDebug> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // 以下兩圖比之 // 輸入兩張要匹配的圖 cv::Mat image1= cv::imread("c:/Fig12.18(a1).jpg",0); cv::Mat image2= cv::imread("c:/Fig12.18(a2).jpg",0); if (!image1.data || !image2.data) qDebug() << "Error!"; cv::namedWindow("Right Image"); cv::imshow("Right Image", image1); cv::namedWindow("Left Image"); cv::imshow("Left Image", image2); // 存放特征點的向量 std::vector<cv::KeyPoint> keypoint1; std::vector<cv::KeyPoint> keypoint2; // 構造SURF特征檢測器 cv::SurfFeatureDetector surf(3000); // 閾值 // 對兩幅圖分別檢測SURF特征 surf.detect(image1,keypoint1); surf.detect(image2,keypoint2); // 輸出帶有詳細特征點信息的兩幅圖像 cv::Mat imageSURF; cv::drawKeypoints(image1,keypoint1, imageSURF, cv::Scalar(255,255,255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::namedWindow("Right SURF Features"); cv::imshow("Right SURF Features", imageSURF); cv::drawKeypoints(image2,keypoint2, imageSURF, cv::Scalar(255,255,255), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS); cv::namedWindow("Left SURF Features"); cv::imshow("Left SURF Features", imageSURF); // 構造SURF描述子提取器 cv::SurfDescriptorExtractor surfDesc; // 對兩幅圖像提取SURF描述子 cv::Mat descriptor1, descriptor2; surfDesc.compute(image1,keypoint1,descriptor1); surfDesc.compute(image2,keypoint2,descriptor2); // 構造匹配器 cv::BruteForceMatcher< cv::L2<float> > matcher; // 將兩張圖片的描述子進行匹配,只選擇25個最佳匹配 std::vector<cv::DMatch> matches; matcher.match(descriptor1, descriptor2, matches); std::nth_element(matches.begin(), // 初始位置 matches.begin()+24, // 排序元素的位置 matches.end()); // 終止位置 // 移除25位后的所有元素 matches.erase(matches.begin()+25, matches.end()); // 以下操作將匹配結果可視化 cv::Mat imageMatches; cv::drawMatches(image1,keypoint1, // 第一張圖片和檢測到的特征點 image2,keypoint2, // 第二張圖片和檢測到的特征點 matches, // 輸出的匹配結果 imageMatches, // 生成的圖像 cv::Scalar(128,128,128)); // 畫直線的顏色 cv::namedWindow("Matches"); //, CV_WINDOW_NORMAL); cv::imshow("Matches",imageMatches); return a.exec(); } ~~~ 效果一,由于原圖中飛機的邊緣有鋸齒狀,因此只需觀察拐角處,匹配效果良好: ![](https://box.kancloud.cn/2015-12-30_5683a75f83db5.jpg) 效果二,不涉及圖像的旋轉和變形,只是將一幅圖像進行縮放后進行匹配,得出的效果自然是很好: ![](https://box.kancloud.cn/2015-12-30_5683a75fa2360.jpg) 效果三,用兩個不同的角度拍攝的圖像進行匹配,其中部分特征點匹配有偏差,總體效果良好,在調試過程中還可以通過參數調整獲取更好的匹配效果。 ![](https://box.kancloud.cn/2015-12-30_5683a7601273b.jpg) **附注**:另一種匹配方法是使用 cv::FlannBasedMatcher 接口以及函數 FLANN 實現快速高效匹配(快速最近鄰逼近搜索函數庫(Fast Approximate Nearest Neighbor Search Library))。網上有源代碼例程如下: ~~~ #include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp" #include <opencv2/highgui/highgui.hpp> #include <opencv2/legacy/legacy.hpp> #include "opencv2/features2d/features2d.hpp" #include "opencv2/highgui/highgui.hpp" using namespace cv; void readme(); /** @function main */ int main( int argc, char** argv ) { if( argc != 3 ) { readme(); return -1; } Mat img_1 = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE ); Mat img_2 = imread( argv[2], CV_LOAD_IMAGE_GRAYSCALE ); if( !img_1.data || !img_2.data ) { std::cout<< " --(!) Error reading images " << std::endl; return -1; } //-- Step 1: Detect the keypoints using SURF Detector int minHessian = 400; SurfFeatureDetector detector( minHessian ); std::vector<KeyPoint> keypoints_1, keypoints_2; detector.detect( img_1, keypoints_1 ); detector.detect( img_2, keypoints_2 ); //-- Step 2: Calculate descriptors (feature vectors) SurfDescriptorExtractor extractor; Mat descriptors_1, descriptors_2; extractor.compute( img_1, keypoints_1, descriptors_1 ); extractor.compute( img_2, keypoints_2, descriptors_2 ); //-- Step 3: Matching descriptor vectors using FLANN matcher FlannBasedMatcher matcher; std::vector< DMatch > matches; matcher.match( descriptors_1, descriptors_2, matches ); double max_dist = 0; double min_dist = 100; //-- Quick calculation of max and min distances between keypoints for( int i = 0; i < descriptors_1.rows; i++ ) { double dist = matches[i].distance; if( dist < min_dist ) min_dist = dist; if( dist > max_dist ) max_dist = dist; } printf("-- Max dist : %f \n", max_dist ); printf("-- Min dist : %f \n", min_dist ); //-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist ) //-- PS.- radiusMatch can also be used here. std::vector< DMatch > good_matches; for( int i = 0; i < descriptors_1.rows; i++ ) { if( matches[i].distance < 2*min_dist ) { good_matches.push_back( matches[i]); } } //-- Draw only "good" matches Mat img_matches; drawMatches( img_1, keypoints_1, img_2, keypoints_2, good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS ); //-- Show detected matches imshow( "Good Matches", img_matches ); for( int i = 0; i < good_matches.size(); i++ ) { printf( "-- Good Match [%d] Keypoint 1: %d -- Keypoint 2: %d \n", i, good_matches[i].queryIdx, good_matches[i].trainIdx ); } waitKey(0); return 0; } /** @function readme */ void readme() { std::cout << " Usage: ./SURF_FlannMatcher <img1> <img2>" << std::endl; } ~~~ 以上只是記錄這種方法的實現例程,并沒有驗證代碼的正確性。 參考資料: [http://blog.sina.com.cn/s/blog_a98e39a201017pgn.html](http://blog.sina.com.cn/s/blog_a98e39a201017pgn.html) [http://www.cnblogs.com/tornadomeet/archive/2012/08/17/2644903.html](http://www.cnblogs.com/tornadomeet/archive/2012/08/17/2644903.html)?(SURF算法的理論介紹) [http://blog.csdn.net/liyuefeilong/article/details/44166069](http://blog.csdn.net/liyuefeilong/article/details/44166069) [http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.html](http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/features2d/feature_flann_matcher/feature_flann_matcher.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看