OpenCV 2.xでSURFを用いて特徴点を抽出、描画


このエントリーをはてなブックマークに追加

表題のことを単にやってみました。環境はWindows 7 + Visual Studio Express 2013 + Opencv2.4.8です。

ヘッダのインクルード

必要なファイルを以下のようにインクルード。SURFはSIFTと同じく特許が取られていて商用利用できなかったはずなので要注意。インクルードするファイルのパスに"nonfree"とあるのはそのため。

#include "opencv2/core/core.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include "opencv2/imgproc/imgproc.hpp"

画像を読み込み

適当な画像を白黒で読み込む。

    cv::Mat img = cv::imread("..\\img\\baboon200.jpg", CV_LOAD_IMAGE_GRAYSCALE);

SURFで特徴点(keypoints)を抽出する

適当なminHessianという値を決めて、SURFにより特徴点を抽出する。この値を大きくするほど良い特徴点だけを抽出できる。c++ - Whats the meaning of minHessian (Surffeaturedetector) - Stack Overflowによると、400から800に設定するとよいようだ。

    int minHessian = 400;
    cv::SurfFeatureDetector detector(minHessian);
    std::vector<cv::KeyPoint> keypoints;
    detector.detect(img, keypoints);

特徴点を描画する

特徴点を重畳した画像を生成するcv::drawKeypoints()という便利な関数が用意されているのでこれを使う。

    // keypointを描画
    cv::Mat dstImg;
    cv::drawKeypoints(
        img, // 入力画像
        keypoints, // 特徴点
        dstImg, // 出力画像
        cv::Scalar::all(-1), // 色  -1の場合はランダム?
        cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS // 描画のオプション  DRAW_RICH_KEYPOINTSを選んだ場合は、キーポイントのサイズと方向が描画される
        );
    cv::imshow("Keypoints", dstImg);

結果は以下の通り。良い特徴点ほど大きな円で表示されているようだ。

f:id:minus9d:20140317000243p:plain

自力で描画することももちろん可能。さりげなくC++11のrange-based forループとautoによる型推論を使っている。

    // 自力でkeypointを描画
    cv::Mat dstImgMine;
    cv::cvtColor(img, dstImgMine, CV_GRAY2BGR);
    for (auto k : keypoints){
        cv::circle(dstImgMine, k.pt, 3, cv::Scalar(255, 0, 0));
    }
    cv::imshow("KeypointsMine", dstImgMine);

結果は以下の通り。

f:id:minus9d:20140317000400p:plain

引用元

opencvに付属するサンプルコード samples\cpp\tutorial_code\features2D\SURF_descriptor.cpp を下敷きにしました。

コード全文

githubで晒し中です。