コーナー検出(EigenValue,Harris,FAST)

26 2月 2010 Under: opencv2.x-samples

C++

#include <cvaux.h>
#include <highgui.h>

using namespace cv;

int
main (int argc, char **argv)
{
  // (1)load a specified file as a 3-channel color image
  const char *imagename = argc > 1 ? argv[1] : "../image/library.png";
  Mat eigen_img = imread(imagename);
  if(!eigen_img.data)
    return -1;
  Mat harris_img = eigen_img.clone();
  Mat fast_img = eigen_img.clone();

  // (2)convert to a grayscale image and normalize it
  Mat gray_img;
  cvtColor(eigen_img, gray_img, CV_BGR2GRAY);
  normalize(gray_img, gray_img, 0, 255, NORM_MINMAX);

  // (3)detect and draw strong corners on the image based on Eigen Value
  vector<Point2f> corners;
  goodFeaturesToTrack(gray_img, corners, 80, 0.01, 5);
  vector<Point2f>::iterator it_corner = corners.begin();
  for(; it_corner!=corners.end(); ++it_corner) {
    circle(eigen_img, Point(it_corner->x, it_corner->y), 1, Scalar(0,200,255), -1);
    circle(eigen_img, Point(it_corner->x, it_corner->y), 8, Scalar(0,200,255));
  }

  // (4)detect and draw strong corners on the image using Harris detector
  goodFeaturesToTrack(gray_img, corners, 80, 0.01, 3, Mat(), 3, true);
  it_corner = corners.begin();
  for(; it_corner!=corners.end(); ++it_corner) {
    circle(harris_img, Point(it_corner->x, it_corner->y), 1, Scalar(0,255,0), -1);
    circle(harris_img, Point(it_corner->x, it_corner->y), 8, Scalar(0,255,0 ));
  }

  // (5)detect corners using high-speed corner detection; FAST
  int threshold = 100;
  bool nonmax = true;
  vector<KeyPoint> keypoints;
  FAST(gray_img, keypoints, threshold, nonmax);
  vector<KeyPoint>::iterator it_kp = keypoints.begin();
  for(; it_kp!=keypoints.end(); ++it_kp) {
    circle(fast_img, Point(it_kp->pt.x, it_kp->pt.y), 1, Scalar(50,0,255), -1);
    circle(fast_img, Point(it_kp->pt.x, it_kp->pt.y), 8, Scalar(50,0,255));
  }

  // (6)show destination images, and quit when any key pressed
  namedWindow("EigenValue",CV_WINDOW_AUTOSIZE);
  namedWindow("Harris",CV_WINDOW_AUTOSIZE);
  namedWindow("Fast",CV_WINDOW_AUTOSIZE);
  imshow("EigenValue", eigen_img);
  imshow("Harris", harris_img);
  imshow("Fast", fast_img);
  waitKey(0);

  return 0;
}

// (1)指定ファイルを3チャンネルカラー画像として読み込みます.

コマンドライン引数で指定されたファイルを,3チャンネルカラー画像として読み込みます.

// (2)カラー画像をグレースケール画像に変換します.

関数 cvtColor により,カラー画像をRGBカラーからグレースケールに変換します.また,変換後のグレースケール画像の輝度値が[0-255] に分布するように正規化を行います.

// (3)固有値に基づき,画像中の強いコーナーを検出します.

関数 goodFeaturesToTrack を用いて,最小固有値が十分に大きいコーナーを検出します.cornerEigenValsAndVecs も参照してください.ここでは,上位80個のコーナーを検出しています.最後に,検出されたコーナー位置に円を描画します.

// (4)Harris 検出器を用いて,画像中の強いコーナーを検出します.

関数 goodFeaturesToTrack を用いて,強いコーナーを検出します.ここでは上述の例と異なり,第8引数に true を与えることで,固有値を計算する代わりに Harris 検出器を利用し,十分に大きな応答(cornerHarris を参照してください)を持つコーナーを検出します.ここでは,上位80個のコーナーを検出しています.最後に,されたコーナー位置に円を描画します.

// (5)FASTアルゴリズムを利用してコーナーを検出します.

FAST クラスのコンストラクタにより,コーナーを検出します.この機能は,OpenCV2.0 から追加されました.第3引数は閾値に影響します.FAST アルゴリズムでチェックする対象ピクセルと,それを中心とする円周上のピクセルとの比較時の閾値の上下幅を表します.つまり,この値が小さくなると,対象ピクセルが周囲と異なる明度と見やしやすくなり,より多くのコーナーが検出されます.また,第4引数によって non-maxima suppression を行うか否かを指定します.最後に,検出されたコーナー位置に円を描画します.この手法は,前述の2手法とは異なり,「より強いコーナーを上から指定数だけ検出する」といったことはできず,その結果は単純に比較できるものではありません.

// (6)コーナーの検出結果を表示します.

それぞれの手法によって検出されたコーナー位置を円と点で描画した画像を表示します.また,何かキーが押されるとプログラムを終了します.

実行結果例


(左)最小固有値に基づく手法,(中)Harris 検出器,(右)FAST