SIFT SURFを用いた特徴点マッチング
回転やスケール変化にも頑健なSIFTとSURFを用いて特徴点の対応づけをしてみた。
計算時間とマッチング数もそれぞれ算出。
プログラム
#include <iostream> #include <opencv/cxcore.h> #include <opencv2/highgui/highgui.hpp> #include <opencv2/nonfree/nonfree.hpp> #include <opencv2/legacy/legacy.hpp> int main(int argc, char *argv[]) { //画像読み込み cv::Mat colorImg1 = cv::imread("/image/lena2.png"); cv::Mat colorImg2 = cv::imread("/image/lena3.png"); if(colorImg1.empty() || colorImg2.empty()){ std::cout << "No Image" << std::endl; return -1; } //特徴点抽出用のグレー画像用意 cv::Mat grayImg1, grayImg2; cv::cvtColor(colorImg1, grayImg1, CV_BGR2GRAY); cv::normalize(grayImg1, grayImg1, 0, 255, cv::NORM_MINMAX); cv::cvtColor(colorImg2, grayImg2, CV_BGR2GRAY); cv::normalize(grayImg2, grayImg2, 0, 255, cv::NORM_MINMAX); //SIFT //cv::SiftFeatureDetector detector; //cv::SiftDescriptorExtractor extractor; //SURF cv::SurfFeatureDetector detector(1000); cv::SurfDescriptorExtractor extractor; //------------ 処理時間計測 開始 -------------- double ticFrequency; // 1マイクロ秒あたりのTick数 double processTime; // 実行時間 int startTic; // 開始 int stopTic; // 終了時間 ticFrequency = cvGetTickFrequency(); // 計測開始点でのTick数を得ます。 startTic = (int)cvGetTickCount(); //------------------------------------------- //画像から特徴点を検出 std::vector<cv::KeyPoint> keypoints1; detector.detect(grayImg1, keypoints1); std::cout << "Detected " << (int) keypoints1.size() << " keypoints1" <<std::endl; //特徴点算出 std::vector<cv::KeyPoint> keypoints2; detector.detect(grayImg2, keypoints2); std::cout << "Detected " << (int) keypoints2.size() << " keypoints2" <<std::endl; //特徴点算出 //画像の特徴点における特徴量を抽出 cv::Mat descriptors1; extractor.compute(grayImg1, keypoints1, descriptors1); cv::Mat descriptors2; extractor.compute(grayImg2, keypoints2, descriptors2); //特徴点の対応付け std::vector<cv::DMatch> matches; cv::BruteForceMatcher<cv::L2<float> > matcher; matcher.match(descriptors1, descriptors2, matches); std::cout << "Matching " << (int) matches.size() << " matching" <<std::endl; //特徴点算出 //ソートしたn番目までの対応線を表示させる。nth_elementは要素を基準要素よりも手前に移動させるある種のソート int N=50; nth_element(matches.begin(), matches.begin()+N-1, matches.end()); matches.erase(matches.begin()+N, matches.end()); //------------ 処理時間計測 終了 -------------- // 計測終了点でのTick数を得ます。 stopTic = (int)cvGetTickCount(); // 実行時間を計算します。単位はマイクロ秒であることに注意してください。 processTime = (stopTic-startTic)/ticFrequency; printf("%f",processTime); //----------------------------------------- //対応づけされた画像の用意 cv::Mat matchedImg; cv::drawMatches(colorImg1, keypoints1, colorImg2, keypoints2, matches, matchedImg); /// 画像を表示するウィンドウの名前,プロパティ // CV_WINDOW_AUTOSIZE : ウィンドウサイズを画像サイズに合わせる // CV_WINDOW_FREERATIO : ウィンドウのアスペクト比を固定しない cv::namedWindow("SURF", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO); // ウィンドウ名でウィンドウを指定して,そこに画像を描画 cv::imshow("SURF", matchedImg); // キー入力を(無限に)待つ cv::waitKey(0); return 0; }
参考サイト:http://kesin.hatenablog.com/entry/20120810/1344582180
実行結果
SIFT
SURF
SURFの方が計算処理は速かったです。
他にも局所勾配特徴点を抽出する方法はSIFT SURF FAST BRIEF RIFF DAISYがあるみたい。
でも特徴量を記述するのはSIFT SURFぐらいなのか。
次はFAST使って同じようなことができるか試してみよう。
SURFによる特徴点の抽出とそのオプティカルフローの描画で
PTAMみたいな映像を作ってみるのも面白いかも。