About BBS

勾配,エッジ,コーナー

作成者: 怡土順一, 最終変更者: 怡土順一, 最終変更リビジョン: 309, 最終変更日時: 2007-09-26 01:28:01 +0900 (水, 26 9月 2007)
This is a local copy taken at 2010/09/20. CLICK HERE to the original page at opencv.jp.

■ 勾配,エッジ

画像の勾配(濃度勾配)とは,各画素値の変化の度合を示すものである. これは,画素の位置を変数とした場合の微分値であるので"微分画像"と呼ばれる. どのような場合に画素値の変化が大きくなるのかを考えると, オブジェクトやテクスチャの"端"において画素値が急激に変化することが多い. そのため,微分画像はエッジらしい個所を表す画像と見なされ,オブジェクト の検出や認識,輪郭追跡の前処理などにしばしば利用される. OpenCVでは,Sobel, Laplacian, Cannyによるエッジ検出のための関数を用意している.

サンプル


エッジの検出 cvSobel, cvLaplace, cvCanny

Sobel,Laplacian,Cannyによるエッジ検出

サンプルコード

#include <cv.h> #include <highgui.h> int main (int argc, char **argv) { IplImage *src_img, *dst_img1, *dst_img2, *dst_img3; IplImage *tmp_img; // (1)画像の読み込み if (argc != 2 || (src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_GRAYSCALE)) == 0) return -1; tmp_img = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_16S, 1); dst_img1 = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1); dst_img2 = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1); dst_img3 = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1); // (2)Sobelフィルタによる微分画像の作成 cvSobel (src_img, tmp_img, 1, 0); cvConvertScaleAbs (tmp_img, dst_img1); // (3)画像のLaplacianの作成 cvLaplace (src_img, tmp_img); cvConvertScaleAbs (tmp_img, dst_img2); // (4)Cannyによるエッジ画像の作成 cvCanny (src_img, dst_img3, 50.0, 200.0); // (5)画像の表示 cvNamedWindow ("Original", CV_WINDOW_AUTOSIZE); cvShowImage ("Original", src_img); cvNamedWindow ("Sobel", CV_WINDOW_AUTOSIZE); cvShowImage ("Sobel", dst_img1); cvNamedWindow ("Laplace", CV_WINDOW_AUTOSIZE); cvShowImage ("Laplace", dst_img2); cvNamedWindow ("Canny", CV_WINDOW_AUTOSIZE); cvShowImage ("Canny", dst_img3); cvWaitKey (0); cvDestroyWindow ("Original"); cvDestroyWindow ("Sobel"); cvDestroyWindow ("Laplace"); cvDestroyWindow ("Canny"); cvReleaseImage (&src_img); cvReleaseImage (&dst_img1); cvReleaseImage (&dst_img2); cvReleaseImage (&dst_img3); cvReleaseImage (&tmp_img); return 0; }

// (1)画像の読み込み
コマンド引数で指定されたファイル名の画像(入力画像)をオープンし,関数 cvLoadImage()で読み込む.2番目の引数にCV_LOAD_IMAGE_GRAYSCALE を指定することで,元画像をグレースケール画像として読み込む.

// (2)Sobelフィルタによる微分画像の作成
x方向に1次微分するための,3×3サイズのSobelフィルタを用いて微分画像を作成する. ここでは,aperture_sizeを指定していないが,その場合はデフォルトのサイズ3が利用される. また,ここでCV_SCHARR(=-1)を指定すると,Sharrフィルタを利用することができる. この関数ではスケーリングは行われないので,出力画像の各ピクセル値は, ほとんどの場合入力画像のそれよりも大きな値になる.オーバーフローを避 けるために,例えば入力画像が8ビットの場合,出力画像として16ビット画像を指定する必要がある.

// (3)画像のLaplacianの作成
以下のように,x-y両方向の二次微分の和を計算し,画像のLaplacianを作成する.

dst(x,y) = d2src/dx2 + d2src/dy2
この関数でも,cvSobelの場合と同様に出力画像として16ビット画像を指定する.

// (4)Cannyによるエッジ画像の作成
関数cvCanny()が出力する結果は,前述の二つの関数とは異なり,勾配画像では無い. ここで出力される画像は,エッジか,そうでないかの二値画像となる. cvCanny()は,二種類の閾値を引数(3番目,4番目)にとり, 小さいほうがエッジ同士を接続するために用いられ,大きいほうが強いエッジ の初期検出に用いられる. エッジの接続では,注目ピクセルの8近傍(4方向)に対する勾配が求められ, 最も強い勾配を持つ方向に(閾値を下回らない限り)エッジが接続される.

// (5)画像の表示
入力画像と処理画像を実際に表示し,何かキーが押されるまで待つ.

実行結果例

入力画像 結果(Sobel) 結果(Laplacian) 結果(Canny)

■ コーナー

サンプル


コーナーの検出 cvGoodFeaturesToTrack, cvFindCornerSubPix

画像中のコーナー(特徴点)検出

サンプルコード

#include <cv.h> #include <highgui.h> int main (int argc, char **argv) { int i, corner_count = 150; IplImage *dst_img1, *dst_img2, *src_img_gray; IplImage *eig_img, *temp_img; CvPoint2D32f *corners; if (argc != 2 || (dst_img1 = cvLoadImage (argv[1], CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH)) == 0) return -1; dst_img2 = cvCloneImage (dst_img1); src_img_gray = cvLoadImage (argv[1], CV_LOAD_IMAGE_GRAYSCALE); eig_img = cvCreateImage (cvGetSize (src_img_gray), IPL_DEPTH_32F, 1); temp_img = cvCreateImage (cvGetSize (src_img_gray), IPL_DEPTH_32F, 1); corners = (CvPoint2D32f *) cvAlloc (corner_count * sizeof (CvPoint2D32f)); // (1)cvCornerMinEigenValを利用したコーナー検出 cvGoodFeaturesToTrack (src_img_gray, eig_img, temp_img, corners, &corner_count, 0.1, 15); cvFindCornerSubPix (src_img_gray, corners, corner_count, cvSize (3, 3), cvSize (-1, -1), cvTermCriteria (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03)); // (2)コーナーの描画 for (i = 0; i < corner_count; i++) cvCircle (dst_img1, cvPointFrom32f (corners[i]), 3, CV_RGB (255, 0, 0), 2); // (3)cvCornerHarrisを利用したコーナー検出 corner_count = 150; cvGoodFeaturesToTrack (src_img_gray, eig_img, temp_img, corners, &corner_count, 0.1, 15, NULL, 3, 1, 0.01); cvFindCornerSubPix (src_img_gray, corners, corner_count, cvSize (3, 3), cvSize (-1, -1), cvTermCriteria (CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03)); // (4)コーナーの描画 for (i = 0; i < corner_count; i++) cvCircle (dst_img2, cvPointFrom32f (corners[i]), 3, CV_RGB (0, 0, 255), 2); // (5)画像の表示 cvNamedWindow ("EigenVal", CV_WINDOW_AUTOSIZE); cvShowImage ("EigenVal", dst_img1); cvNamedWindow ("Harris", CV_WINDOW_AUTOSIZE); cvShowImage ("Harris", dst_img2); cvWaitKey (0); cvDestroyWindow ("EigenVal"); cvDestroyWindow ("Harris"); cvReleaseImage (&dst_img1); cvReleaseImage (&dst_img2); cvReleaseImage (&eig_img); cvReleaseImage (&temp_img); cvReleaseImage (&src_img_gray); return 0; }

// (1)cvCornerMinEigenValを利用したコーナー検出
関数 cvGoodFeaturesToTrack() は,画像中から大きな固有値を持つコーナーを検出する. この関数は最初に,すべての入力画像のピクセルに対して, cvCornerMinEigenVal を用いて最小の固有値を計算し, 結果を(2番目の引数で指定された) eig_image に保存する. 次に,"non-maxima suppression"を実行する(3×3の隣接領域内の極大のみが残る). 次のステップでは,(6番目の引数で指定された)quality_levelth と max(eig_image(x,y)) の積よりも小さい最小固有値をもつコーナーを削除する. 最後に,この関数はコーナー点に着目し(最も強いコーナーが一番最初に対象となる), 新しく着目した特徴点とそれ以前に対象とした特徴点群との距離が (7番目の引数で指定された) min_distance よりも大きいことをチェックすることで, すべての検出されたコーナーそれぞれの距離が十分離れていることを保証する. そのため,この関数は鮮明な特徴点との距離が近い特徴点を削除する. さらに,関数 cvFindCornerSubPix()を利用して,4番目の引数で指定したサイズの倍の探索ウィンドウで, コーナー(特徴点)のより正確な座標を探索する.

// (2)コーナーの描画
検出されたコーナーを赤色の円で描画する.

// (3)cvCornerHarrisを利用したコーナー検出
10番目の引数が0でない場合は,デフォルトの cvCornerMinEigenVal の代わりに, Harrisオペレータ(cvCornerHarris)を用いる.

// (4)コーナーの描画
検出されたコーナーを青色の円で描画する.

// (5)画像の表示
実際に検出されたコーナーの画像を表示し,何かキーが押されるまで待つ.

実行結果例

最小固有値 Harris

OpenCV-1.0 リファレンス マニュアル
OpenCV-1.1pre リファレンス マニュアル
OpenCVサンプルコード


画素値の直接操作
部分画像のシャッフル
画像の連結
画像のコピー
画像形状の変形
タイリング
画像の反転
逆行列(擬似逆行列)の計算
色空間の写像
離散フーリエ変換
階層構造を持つ輪郭の座標取得
図形の描画
ポリゴンの描画
凸ポリゴンの描画
テキストの描画
IplImage構造体情報の保存
マップのシーケンスを保存
IplImage構造体情報の読み込み
マップのシーケンスを読み込む
K-means法によるクラスタリング
クラスタリングによる減色処理
エッジの検出
コーナーの検出
並進移動のためのピクセルサンプリング
回転移動のためのピクセルサンプリング
画像のサイズ変更
画像のアフィン変換(1)
画像のアフィン変換(2)
画像の透視投影変換
全方位画像の透視投影変換
モルフォロジー変換
平滑化
ユーザ定義フィルタ
境界線の作成
画像の二値化
画像の二値化(大津の手法)
画像ピラミッドの作成
画像ピラミッドを用いた画像の領域分割
平均値シフト法による画像のセグメント化
Watershedアルゴリズムによる画像の領域分割
輪郭の検出と描画
画像のモーメントを計算
ハフ変換による直線検出
ハフ変換による円検出
距離変換とその可視化
不要オブジェクトの除去
ヒストグラムの描画
ヒストグラム間の距離
二次元のヒストグラム
バックプロジェクションパッチ
ヒストグラムの均一化
テンプレートマッチング
形状のマッチング
点列を包含する矩形
輪郭領域の面積と輪郭の長さ
二つの矩形を包含する矩形
楕円のフィッティング
点列を包含する図形
動的背景更新による物体検出
snakeによる輪郭追跡(静止画)
オプティカルフロー1
オプティカルフロー2
オプティカルフロー3
Condensation
顔の検出
カメラキャリブレーション
歪み補正
マップを利用した歪み補正
サポートベクターマシン
画像の各ピクセル値を特徴ベクトルとしたSVMの学習
画像の各ピクセル値を特徴ベクトルとしたSVMによる物体検出
マウスイベントの取得
トラックバーの利用
カメラからの画像キャプチャ
動画としてファイルへ書き出す
ラベリング