CV リファレンス マニュアル
-
画像処理(Image Processing)
- 勾配,エッジ,コーナー(Gradients, Edges and Corners)
- サンプリング,補間,幾何変換(Sampling, Interpolation and Geometrical Transforms)
- モルフォロジー演算(Morphological Operations)
- フィルタと色変換(Filters and Color Conversion)
- ピラミッドとその応用(Pyramids and the Applications)
- 画像分割,領域結合,輪郭検出(Image Segmentation, Connected Components and Contour Retrieval)
- 画像と形状のモーメント(Image and Contour Moments)
- 特殊な画像変換(Special Image Transforms)
- ヒストグラム(Histograms)
- マッチング(Matching)
- 構造解析(Structural Analysis)
- モーション解析と物体追跡(Motion Analysis and Object Tracking)
- パターン認識(Pattern Recognition)
- カメラキャリブレーションと3次元再構成(Camera Calibration and 3D Reconstruction)
- 参考文献
画像処理(Image Processing)
注釈:
この章では画像処理及び解析のための関数について述べる.ほとんどの関数はピクセルの2次元配列に対して実行される.OpenCVでは配列を「画像」として取り扱う.しかしその配列はIplImage形式である必要はなく,CvMat形式またはCvMatND形式でもよい.
特殊な画像変換(Special Image Transforms)
HoughLines2
ハフ(Hough)変換を用いて2値画像から直線を検出する
CvSeq* cvHoughLines2( CvArr* image, void* line_storage, int method,
double rho, double theta, int threshold,
double param1=0, double param2=0 );
- image
- 入力画像(8ビット,シングルチャンネル,2値化画像).確率的な手法の場合は,画像は関数内で変換される.
- line_storage
- 検出された線を保存する領域.メモリストレージ(この場合,関数によって線分のシーケンスがストレージ内につくられ,そのポインタが返される),あるいは,線のパラメータが記述された特定のタイプ(下参照)の1行の行列/1列の行列 (CvMat*).行列のヘッダは,そのcols か rowsが検出された線の数となるように,この関数によって変更される.もし,line_storage が行列で,かつ実際の線の数が行列のサイズを超える場合は,線の最大可能数が返される(標準的ハフ変換の場合は 投票数でソートされる).
- method
- ハフ変換の種類,以下のいずれか一つ.
- CV_HOUGH_STANDARD - 標準的ハフ変換.全ての線分は2つの浮動小数点値 (ρ, θ)で表される.ここでρ は点(0,0) から線分までの距離,θ はx軸と線分の法線が成す角度. そのため,行列(作成されるシーケンス)は,CV_32FC2 タイプとなる.
- CV_HOUGH_PROBABILISTIC - 確率的ハフ変換(画像に長い線が少ない場合に有効).全ての線を返すのではなく,線分を返す. 全ての線分は始点と終点で表され,行列(作成されるシーケンス)は,CV_32SC4 タイプとなる.
- CV_HOUGH_MULTI_SCALE -マルチスケール型の古典的ハフ変換. 線は CV_HOUGH_STANDARD と同様の方法でエンコードされる.
- rho
- 距離解像度(1ピクセル当たりの単位).
- theta
- 角度解像度(ラジアン単位で計測).
- threshold
- 閾値パラメータ.対応する投票数がthresholdより大きい場合のみ,抽出された線が返される.
- param1
- 各手法に応じた1番目のパラメータ.
- 標準的ハフ変換では,使用しない(0).
- 確率的ハフ変換では,最小の線の長さ.
- マルチスケールハフ変換では, 距離解像度rhoの除数. (荒い距離解像度では rho であり,詳細な解像度では (rho / param1) となる).
- param2
- 各手法に応じた2番目のパラメータ.
- 標準的ハフ変換では,使用しない (0).
- 確率的ハフ変換では,同一線上に存在する線分として扱う(つまり,それらを統合しても問題ない),二つの線分の最大の間隔.
- マルチスケールハフ変換では,角度解像度 thetaの除数. (荒い角度解像度では theta であり,詳細な解像度では (theta / param2) となる).
関数 cvHoughLines2 は,線検出のための3種類のハフ変換を実行する.
(例)ハフ変換を用いた線の検出
/* これは,単独で動作するプログラムである.プログラムの最初の引数として画像名を渡す. "#if 1" を "#if 0" に変更したり戻したりすることで, 標準的ハフ変換と確率的ハフ変換を切り替えることができる. */ #include <cv.h> #include <highgui.h> #include <math.h> int main(int argc, char** argv) { IplImage* src; if( argc == 2 && (src=cvLoadImage(argv[1], 0))!= 0) { IplImage* dst = cvCreateImage( cvGetSize(src), 8, 1 ); IplImage* color_dst = cvCreateImage( cvGetSize(src), 8, 3 ); CvMemStorage* storage = cvCreateMemStorage(0); CvSeq* lines = 0; int i; cvCanny( src, dst, 50, 200, 3 ); cvCvtColor( dst, color_dst, CV_GRAY2BGR ); #if 1 lines = cvHoughLines2( dst, storage, CV_HOUGH_STANDARD, 1, CV_PI/180, 100, 0, 0 ); for( i = 0; i < MIN(lines->total,100); i++ ) { float* line = (float*)cvGetSeqElem(lines,i); float rho = line[0]; float theta = line[1]; CvPoint pt1, pt2; double a = cos(theta), b = sin(theta); double x0 = a*rho, y0 = b*rho; pt1.x = cvRound(x0 + 1000*(-b)); pt1.y = cvRound(y0 + 1000*(a)); pt2.x = cvRound(x0 - 1000*(-b)); pt2.y = cvRound(y0 - 1000*(a)); cvLine( color_dst, pt1, pt2, CV_RGB(255,0,0), 3, 8 ); } #else lines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 50, 50, 10 ); for( i = 0; i < lines->total; i++ ) { CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i); cvLine( color_dst, line[0], line[1], CV_RGB(255,0,0), 3, 8 ); } #endif cvNamedWindow( "Source", 1 ); cvShowImage( "Source", src ); cvNamedWindow( "Hough", 1 ); cvShowImage( "Hough", color_dst ); cvWaitKey(0); } }
サンプル画像.上のサンプルプログラムで用いられた関数の各パラメータは,この画像に対して調整されている.
上記の例題プログラムにおいて確率的ハフ変換を行った場合("#if 0" の場合)の出力.
HoughCircles
ハフ変換を用いてグレースケール画像中の円を検出する
CvSeq* cvHoughCircles( CvArr* image, void* circle_storage,
int method, double dp, double min_dist,
double param1=100, double param2=100,
int min_radius=0, int max_radius=0 );
- image
- 入力画像 (8ビット,シングルチャンネル,グレースケール).
- circle_storage
- 検出された円を保存する領域.メモリストレージ(この場合,関数によって円のシーケンスがストレージ内につくられ,そのポインタが返される),あるいは円のパラメータが記述されたCV_32FC3型の1行の行列/1列の行列 (CvMat*). 行列のヘッダは,そのcols か rowsが検出された円の数となるように,この関数によって変更される.もし,circle_storage が行列で,かつ実際の円の数が行列のサイズを超える場合は,円の最大可能数が返される.全ての円は3つの浮動小数点値(中心座標(x,y)と半径)としてエンコードされる.
- method
- 現状では,CV_HOUGH_GRADIENT(基本的な2段階のハフ変換, [Yuen03]参照)のみ実装されている.
- dp
- 円の中心を求める際に用いられる計算時の解像度.例えば,この値が 1 の場合は,計算は入力画像と同じ解像度で行われる.2 の場合は,計算は幅・高さともに1/2の解像度になる,等.
- min_dist
- 円検出における中心座標間の最小間隔.この値が非常に小さい場合は,正しく抽出されるべき円の近傍に複数の間違った円が検出されることになる.また,逆に非常に大きい場合は,円検出に失敗する.
- param1
- 手法に応じた1番目のパラメータ. CV_HOUGH_GRADIENT の場合は,Cannyのエッジ検出器で用いる二つの閾値の高い方の値 (低い方の値は,この値を1/2したものになる).
- param2
- 手法に応じた2番目のパラメータ. CV_HOUGH_GRADIENT の場合は,中心検出計算時の閾値.小さすぎると誤検出が多くなる.これに対応する値が大きい円から順に検出される.
- min_radius
- 検出すべき円の最小半径.
- max_radius
- 検出すべき円の最大半径 デフォルトの最大半径は max(image_width, image_height) にセットされている.
関数 cvHoughCircles は,グレースケール画像中の円をハフ変換を用いて検出する.
(例)ハフ変換による円の検出
#include <cv.h> #include <highgui.h> #include <math.h> int main(int argc, char** argv) { IplImage* img; if( argc == 2 && (img=cvLoadImage(argv[1], 1))!= 0) { IplImage* gray = cvCreateImage( cvGetSize(img), 8, 1 ); CvMemStorage* storage = cvCreateMemStorage(0); cvCvtColor( img, gray, CV_BGR2GRAY ); cvSmooth( gray, gray, CV_GAUSSIAN, 9, 9 ); // 画像の平滑化,行わないと誤検出が起こりやすい CvSeq* circles = cvHoughCircles( gray, storage, CV_HOUGH_GRADIENT, 2, gray->height/4, 200, 100 ); int i; for( i = 0; i < circles->total; i++ ) { float* p = (float*)cvGetSeqElem( circles, i ); cvCircle( img, cvPoint(cvRound(p[0]), cvRound(p[1])), 3, CV_RGB(0,255,0), -1, 8, 0 ); cvCircle( img, cvPoint(cvRound(p[0]), cvRound(p[1])), cvRound(p[2]), CV_RGB(255,0,0), 3, 8, 0 ); } cvNamedWindow( "circles", 1 ); cvShowImage( "circles", img ); } return 0; }
DistTransform
入力画像中の値が0でないピクセルから,最も近い値が0のピクセルまでの距離を計算する
void cvDistTransform( const CvArr* src, CvArr* dst, int distance_type=CV_DIST_L2,
int mask_size=3, const float* mask=NULL, CvArr* labels=NULL );
- src
- 入力画像(8ビット,シングルチャンネル,2値画像).
- dst
- 距離計算結果をピクセル値として持つ出力画像 (32ビット浮動小数点型,シングルチャンネル).
- distance_type
- 距離の種類.CV_DIST_L1, CV_DIST_L2, CV_DIST_C か CV_DIST_USER.
- mask_size
- 距離変換マスクのサイズで,3,5,0 のいずれか. CV_DIST_L1, CV_DIST_C の場合,このパラメータ値は3に固定される.なぜなら 3×3 は 5×5 のマスクを用いたときと同じ結果で,かつ計算速度が速いためである.mask_size==0の場合,距離計算に別の近似無しアルゴリズムが用いられる.
- mask
- ユーザ定義の距離の場合はユーザ定義のマスク.3×3のマスクを用いる場合は2つの値(上下シフト値,斜めシフト値)を指定,5×5のマスクを用いる場合は3つの値(上下シフト値,斜めシフト値,ナイト移動シフト値(桂馬飛びのシフト値))を指定する.
- labels
- オプション出力.整数ラベルに変換された2次元配列で,src ,dstと同じサイズ.現在は mask_size==3 あるいは 5 のときのみに使用される.
関数 cvDistTransform は,2値画像の各ピクセルから最も近い値が0のピクセルまでの近似距離,あるいは正確な距離を計算する.mask_size==0 の場合は,この関数は高精度に距離計算を行うアルゴリズム[Felzenszwalb04]を用いる.mask_size==3 あるいは 5の場合は,近似距離を計算するアルゴリズム [Borgefors86]を用いる.
近似距離計算アルゴリズムの計算方法を説明する.関数は,値0のピクセルに対して,距離0をセットする.そのほかのピクセルについては,値0のピクセルに至るまでの基本シフトでの移動(水平・垂直・斜め・(5×5のマスクを用いたときは)ナイト移動)による最短経路を探索する.基本移動の移動総量を距離として全長距離を計算する. 距離関数は対称であるべきなので,水平・垂直のシフトコスト(aとする)は同じでないといけない.また,全ての斜めシフトコスト(bとする),ナイト移動コスト(cとする)もまた,同じでないといけない. タイプCV_DIST_C と CV_DIST_L1 の場合,距離は正確に計算されるが,タイプ CV_DIST_L2 (ユークリッド距離)の場合,距離はいくらかの相対誤差を持つ(5×5 のマスクを用いると,より高精度な値を得ることができる).OpenCVでは以下のように,[Borgefors86]で推奨されている値を用いる.
CV_DIST_C (3×3): a=1, b=1 CV_DIST_L1 (3×3): a=1, b=2 CV_DIST_L2 (3×3): a=0.955, b=1.3693 CV_DIST_L2 (5×5): a=1, b=1.4, c=2.1969
白い矩形中心に黒(0)のピクセルがある画像に対して,ユーザ定義距離によって得られる距離フィールドの計算例を以下に示す.
ユーザ定義 3×3 マスク (a=1, b=1.5)
4.5 | 4 | 3.5 | 3 | 3.5 | 4 | 4.5 |
4 | 3 | 2.5 | 2 | 2.5 | 3 | 4 |
3.5 | 2.5 | 1.5 | 1 | 1.5 | 2.5 | 3.5 |
3 | 2 | 1 | 0 | 1 | 2 | 3 |
3.5 | 2.5 | 1.5 | 1 | 1.5 | 2.5 | 3.5 |
4 | 3 | 2.5 | 2 | 2.5 | 3 | 4 |
4.5 | 4 | 3.5 | 3 | 3.5 | 4 | 4.5 |
ユーザ定義 5×5 マスク (a=1, b=1.5, c=2)
4.5 | 3.5 | 3 | 3 | 3 | 3.5 | 4.5 |
3.5 | 3 | 2 | 2 | 2 | 3 | 3.5 |
3 | 2 | 1.5 | 1 | 1.5 | 2 | 3 |
3 | 2 | 1 | 0 | 1 | 2 | 3 |
3 | 2 | 1.5 | 1 | 1.5 | 2 | 3 |
3.5 | 3 | 2 | 2 | 2 | 3 | 3.5 |
4 | 3.5 | 3 | 3 | 3 | 3.5 | 4 |
一般に,高速に近似距離を求める場合は CV_DIST_L2, 3×3 マスクを用い, 高精度な距離が必要な場合は CV_DIST_L2, 5×5 マスクを用いる.
出力パラメータ labels が NULLでない場合,この関数は,すべての非0のピクセルに対して値0のピクセルから構成される最も近い接続成分も検索する.探索される接続成分は,関数の最初の部分で輪郭として認識されている.
このモードでの処理時間は O(N) である(Nはピクセル数). そのため,この関数を用いて2値化画像の近似ボロノイ図を高速に計算することができる.
Inpaint
画像中の選択領域を修復する
void cvInpaint( const CvArr* src, const CvArr* mask, CvArr* dst,
double inpaintRadius, int flags );
- src
- 入力画像(8ビット,1チャンネルあるいは3チャンネル).
- mask
- 修復マスク.8ビット,1チャンネル画像. 非0のピクセルが,修復の必要がある領域であることを示す.
- dst
- 出力画像(入力画像と同じサイズ,同じタイプ).
- inpaintRadius
- 修復されるピクセルの円状の隣接領域を示す半径.
- flags
- 修復方法,以下のいずれか.
CV_INPAINT_NS - ナビエ・ストークス(Navier-Stokes)ベースの手法
CV_INPAINT_TELEA - Alexandru Teleaによる手法 [Telea04]
関数 cvInpaint は,領域境界近くのピクセルを用いて選択領域を再構築する.この関数は,スキャンされた写真画像からスクラッチやノイズを除去したり,静止画やビデオ画像から不必要なオブジェクトを除去するために用いられる.