特徴の検出と記述

ExtractSURF

Comments from the Wiki

void cvExtractSURF(const CvArr* image, const CvArr* mask, CvSeq** keypoints, CvSeq** descriptors, CvMemStorage* storage, CvSURFParams params)

画像から SURF 特徴を抽出します.

パラメタ:
  • image – 8 ビット,グレースケールの入力画像.
  • mask – オプション.8 ビットの入力マスク.0以外のマスクピクセルが50 % 以上を占める領域の特徴のみが計算されます.
  • keypoints – 出力パラメータ.キーポイントのシーケンスへのダブルポインタ.CvSURFPoint 構造体のシーケンスは,次のようになります:
typedef struct CvSURFPoint
{
   CvPoint2D32f pt; // 画像内の特徴の位置
   int laplacian;   // -1, 0 または +1 .この点におけるラプラシアンの符号.
                    // SURF の比較に利用されます.
                    // (通常,ラプラシアン符号の異なる特徴同士は
                    // マッチしません)
   int size;        // 特徴のサイズ
   float dir;       // 特徴の方向: 0..360 度
   float hessian;   // ヘッシアンの値(特徴の強さを大まかに推定する
                    // のに利用できます. params.hessianThreshold
                    // の説明も参照してください)
}
CvSURFPoint;
パラメタ:
  • descriptors – オプションの出力パラメータ.ディスクリプタのシーケンスへのダブルポインタ.params.extended の値に依存して,このシーケンスの各要素は,64-要素,または 128-要素の浮動小数点型( CV_32F )のベクトルになります.このパラメータが NULL Nお場合,ディスクリプタは計算されません.
  • storage – キーポイントとディスクリプタが格納されるメモリストレージ.
  • params – CvSURFParams 構造体に格納された,様々なアルゴリズムパラメータ:
typedef struct CvSURFParams
{
   int extended; // 0 の場合,基本ディスクリプタを意味します( 64 要素),
                 // 1 の場合,拡張ディスクリプタを意味します( 128 要素)
   double hessianThreshold; // keypoint.hessian が,この閾値よりも大きい
                            // 特徴だけが抽出されます.
                            // 適切なデフォルト値は,約 300-500 です(これは,
                            // 画像の局所的なコントラストとシャープネスに依存します).
                            // ユーザは,ヘッシアン値やその他の特徴に基づいて,
                            // さらに特徴を除外する事ができます.
   int nOctaves; // 抽出に利用されるオクターブ数.
                 // オクターブが 1 階上がる毎に,特徴サイズは 2 倍になります.
                 // (デフォルトは 3 )
   int nOctaveLayers; // 各オクターブ内のレイヤ数.
                      // (デフォルトは 4 )
}
CvSURFParams;

CvSURFParams cvSURFParams(double hessianThreshold, int extended=0);
         // デフォルトパラメータを返します.

関数 cvExtractSURF は, Bay06 で述べられたロバストな特徴を画像から検出します.各特徴は,それ自身の位置,サイズ,姿勢に加え,オプションとして(基本または拡張)ディスクリプタ,を返します. この関数は,物体追跡や位置同定,画像スティッチングに利用できます.

OpenCV のサンプルディレクトリにあるデモ find_obj.cpp を参照してください.

GetStarKeypoints

Comments from the Wiki

CvSeq* cvGetStarKeypoints(const CvArr* image, CvMemStorage* storage, CvStarDetectorParams params=cvStarDetectorParams())

StarDetector アルゴリズムを用いて,キーポイントを抽出します.

パラメタ:
  • image – 8 ビット,グレースケールの入力画像.
  • storage – キーポイントが格納されるメモリストレージ.
  • params – CvStarDetectorParams 構造体に与えられる,様々なアルゴリズムパラメータ:
typedef struct CvStarDetectorParams
{
   int maxSize; // 検出される特徴の最大サイズ.
                // 次のパラメータ値がサポートされています:
                // 4, 6, 8, 11, 12, 16, 22, 23, 32, 45, 46, 64, 90, 128
   int responseThreshold; // 近似されたラプラシアンに対する閾値.
                          // 弱い特徴を除外するために利用されます.
   int lineThresholdProjected; // ラプラシアンに対するもう一つの閾値.
                               // エッジを除外するために利用されます.
   int lineThresholdBinarized; // 特徴のスケールに対する閾値.
                               // エッジを除外するために利用されます.
   int suppressNonmaxSize; // ピクセルの近傍領域の線形サイズ.
                           // non-maxima suppression で利用されます.
}
CvStarDetectorParams;

関数 GetStarKeypoints は,スケール-空間における極大値であるキーポイントを抽出します. スケール-空間は,各ピクセルに対して,異なるシグマのラプラシアンを近似値計算することで作成されます. 画像ピラミッドは計算時間を削減する有名な方法ですが,それを利用する代わりに,元の高解像度画像のピクセル毎に,すべてのラプラシアンを計算します. しかし,それぞれの近似ラプラシアン値は,積分画像を利用することで,シグマに関係なく O(1) 時間で計算できます. このアルゴリズムは,Agrawal08 の論文に基づいていますが,矩形や六角形,八角形の代わりに,直立した矩形と45度回転した矩形を重ね合わせた八頂点の星型形状を利用しており,これが名前の由来になっています.

求められた各特徴は,以下の構造体により表現されます:

typedef struct CvStarKeypoint
{
    CvPoint pt; // 特徴の座標.
    int size; // 特徴のサイズ. CvStarDetectorParams::maxSize を参照してください.
    float response; // その点における近似されたラプラシアン値.
}
CvStarKeypoint;

inline CvStarKeypoint cvStarKeypoint(CvPoint pt, int size, float response);

以下は,簡単な使い方の例です:

#include "cv.h"
#include "highgui.h"

int main(int argc, char** argv)
{
    const char* filename = argc > 1 ? argv[1] : "lena.jpg";
    IplImage* img = cvLoadImage( filename, 0 ), *cimg;
    CvMemStorage* storage = cvCreateMemStorage(0);
    CvSeq* keypoints = 0;
    int i;

    if( !img )
        return 0;
    cvNamedWindow( "image", 1 );
    cvShowImage( "image", img );
    cvNamedWindow( "features", 1 );
    cimg = cvCreateImage( cvGetSize(img), 8, 3 );
    cvCvtColor( img, cimg, CV_GRAY2BGR );

    keypoints = cvGetStarKeypoints( img, storage, cvStarDetectorParams(45) );

    for( i = 0; i < (keypoints ? keypoints->total : 0); i++ )
    {
        CvStarKeypoint kpt = *(CvStarKeypoint*)cvGetSeqElem(keypoints, i);
        int r = kpt.size/2;
        cvCircle( cimg, kpt.pt, r, CV_RGB(0,255,0));
        cvLine( cimg, cvPoint(kpt.pt.x + r, kpt.pt.y + r),
            cvPoint(kpt.pt.x - r, kpt.pt.y - r), CV_RGB(0,255,0));
        cvLine( cimg, cvPoint(kpt.pt.x - r, kpt.pt.y + r),
            cvPoint(kpt.pt.x + r, kpt.pt.y - r), CV_RGB(0,255,0));
    }
    cvShowImage( "features", cimg );
    cvWaitKey();
}

目次

このページ