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形式でもよい.
画像分割,領域結合,輪郭検出(Image Segmentation, Connected Components and Contour Retrieval)
CvConnectedComp
連結成分
typedef struct CvConnectedComp { double area; /* セグメント化された連結成分の面積 */ float value; /* セグメント化された連結成分のグレースケール値 */ CvRect rect; /* セグメント化された連結成分のROI */ } CvConnectedComp;
FloodFill
連結成分を指定した色で塗りつぶす
void cvFloodFill( CvArr* image, CvPoint seed_point, CvScalar new_val,
CvScalar lo_diff=cvScalarAll(0), CvScalar up_diff=cvScalarAll(0),
CvConnectedComp* comp=NULL, int flags=4, CvArr* mask=NULL );
#define CV_FLOODFILL_FIXED_RANGE (1 << 16)
#define CV_FLOODFILL_MASK_ONLY (1 << 17)
- image
- 入力画像.1チャンネルあるいは3チャンネル,8ビットあるいは浮動小数点型.CV_FLOODFILL_MASK_ONLYフラグ(以下を参照)がセットされたとき以外は,データが書き換えられる.
- seed_point
- 連結成分の開始点.シードピクセル.
- new_val
- 塗りつぶされる領域の新しいピクセル値(塗りつぶす値).
- lo_diff
- 現在の観測対象ピクセルと,その連結成分に属する隣接ピクセル, またはそのピクセルを連結成分に追加するためのシードピクセルとの,輝度値/色の差(違い)の許容下限値. 8ビットカラー画像のときは,パックされた値.
- up_diff
- 現在の観測対象ピクセルと,その連結成分に属する隣接ピクセル, またはそのピクセルを連結成分に追加するためのシードピクセルとの,輝度値/色の差(違い)の許容上限値. 8ビットカラー画像のときは,パックされた値.
- comp
- 構造体へのポインタ.この関数は,塗りつぶされた領域の情報を構造体に代入する.
- flags
- 操作フラグ.下位ビットは関数内で用いられる連結性に関する値4(デフォルト)または8が入っている. 連結性は,どのピクセルを隣接ピクセルと見なすかを定義する.上位ビットは0,あるいは以下のフラグの組み合わせである.
- CV_FLOODFILL_FIXED_RANGE - セットされている場合は,現在のピクセルとシードピクセルとの差が対象となる.それ以外は,隣接同士の差が対象となる(つまりこのフラグがセットされない場合,レンジは変動的である).
- CV_FLOODFILL_MASK_ONLY - セットされている場合は,この関数では画像を塗りつぶさない(new_val は無視される)が, マスク(この場合,マスクはNULL以外の値でないといけない)は塗りつぶす.
- mask
- 処理用マスク.シングルチャンネル8ビット画像でimageより横・縦とも2ピクセル大きくなければならない. NULLでない場合,この関数はこのマスクの使用と更新を行う.そのためユーザがmaskの内容を初期化しなければならない. Floodfillはマスク中の0でないピクセルを塗りつぶさない.例えば,エッジ検出の結果は,エッジ部分で塗りつぶしを堰き止めるためのマスクとして利用できる. あるいは,塗りつぶし領域の重なりがないことを確認するために,複数回の関数の呼び出しで同じマスクを用いることができる. 注意:マスクのサイズが塗られる画像より大きいため,image中の(x,y)座標のピクセルに 対応するmask中のピクセル座標は(x+1,y+1)になる.
関数 cvFloodFill は,シードピクセルから始まる連結成分を指定された色で塗る. 連結しているかどうかは,ピクセル値の近さによって決定される. (x, y)座標のピクセルは,以下に示すような場合,塗りつぶされる領域に属していると認識される.
src(x',y')-lo_diff<=src(x,y)<=src(x',y')+up_diff, グレースケール画像,変動レンジ src(seed.x,seed.y)-lo<=src(x,y)<=src(seed.x,seed.y)+up_diff, グレースケール画像,固定レンジ src(x',y')r-lo_diffr<=src(x,y)r<=src(x',y')r+up_diffr かつ src(x',y')g-lo_diffg<=src(x,y)g<=src(x',y')g+up_diffg かつ src(x',y')b-lo_diffb<=src(x,y)b<=src(x',y')b+up_diffb, カラー画像,変動レンジ src(seed.x,seed.y)r-lo_diffr<=src(x,y)r<=src(seed.x,seed.y)r+up_diffr かつ src(seed.x,seed.y)g-lo_diffg<=src(x,y)g<=src(seed.x,seed.y)g+up_diffg かつ src(seed.x,seed.y)b-lo_diffb<=src(x,y)b<=src(seed.x,seed.y)b+up_diffb, カラー画像,固定レンジここで,src(x',y') は隣接ピクセルのうちの一つの値である.これは,対象のピクセルの色・輝度値が以下のものと十分に近いとき,連結成分に追加されるということを意味する.
- 変動レンジの場合:連結成分で参照済みの自分の隣接ピクセルの色/輝度値.
- 固定レンジの場合:シードポイント(ピクセル)の色/輝度値.
FindContours
2値画像中の輪郭を見つける
int cvFindContours( CvArr* image, CvMemStorage* storage, CvSeq** first_contour,
int header_size=sizeof(CvContour), int mode=CV_RETR_LIST,
int method=CV_CHAIN_APPROX_SIMPLE, CvPoint offset=cvPoint(0,0) );
- image
- 入力画像(8ビットシングルチャンネル).値が0以外のピクセルは「1」,0のピクセルは「0」とする - これは画像を2値として扱うことを意味する.グレースケール画像から2値画像を得るために,cvThreshold,cvAdaptiveThreshold,あるいは cvCanny などを使うことができる.この関数は入力画像の内容を変更する.
- storage
- 抽出された輪郭を保存する領域.
- first_contour
- 出力パラメータ.一番外側の輪郭へのポインタが入っている.
- header_size
- シーケンスヘッダのサイズ.method=CV_CHAIN_CODEの場合, >=sizeof(CvChain) ,それ以外の場合 >=sizeof(CvContour).
- mode
- 抽出モード
- CV_RETR_EXTERNAL - 最も外側の輪郭のみ抽出
- CV_RETR_LIST - 全ての輪郭を抽出し,リストに追加
- CV_RETR_CCOMP - 全ての輪郭を抽出し,二つのレベルを持つ階層構造を構成する.1番目のレベルは連結成分の外側の境界線,2番目のレベルは穴(連結成分の内側に存在する)の境界線.
- CV_RETR_TREE - 全ての輪郭を抽出し,枝分かれした輪郭を完全に表現する階層構造を構成する.
- method
- 近似手法(CV_LINK_RUNS以外の全ての手法は,組み込まれた近似手法を用いる).
- CV_CHAIN_CODE - 出力はフリーマンチェーンコード(Freeman chain code)で表現される.他の手法ではポリゴン(頂点のシーケンス).
- CV_CHAIN_APPROX_NONE - 全ての点をチェーンコードから点へ変換する.
- CV_CHAIN_APPROX_SIMPLE - 水平・垂直・斜めの線分を圧縮する.すなわち,この関数はそれぞれの端点のみを残す.
- CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS - Teh-Chinチェーンの近似アルゴリズム中の一つを適用する.
- CV_LINK_RUNS - 値1の水平セグメントの接続に基づく,異なる輪郭を抽出する全く異なるアルゴリズムを適用する.抽出モードが CV_RETR_LIST の場合のみ指定可能.
- offset
- オフセット.全ての輪郭点はこれによってシフトされる.これは,画像のROIから輪郭を抽出した後に,それらを画像全体の中で解析しなければならない場合に有用である.
関数 cvFindContours は,2値画像から輪郭を抽 出し,その個数を返す.ポインタ first_contour に結果が出力される. ここには最も外側の輪郭へのポインタが入り, 輪郭が抽出されなかった場合(画像が完全に黒の場合)はNULLが入る. 他の輪郭へは, h_nextと v_nextを用いることで, first_contour から辿ることができる. cvDrawContours で説明されるサンプルは,連結成分を検出するためどのように輪郭を用いるかを示している. 輪郭は形状解析やオブジェクト認識などにも用いられる - OpenCVサンプルディレクトリの squares.c を参照.
StartFindContours
輪郭走査処理の初期化を行う
CvContourScanner cvStartFindContours( CvArr* image, CvMemStorage* storage,
int header_size=sizeof(CvContour),
int mode=CV_RETR_LIST,
int method=CV_CHAIN_APPROX_SIMPLE,
CvPoint offset=cvPoint(0,0) );
- image
- 入力画像.8ビットシングルチャンネルの2値化画像.
- storage
- 抽出された輪郭データの保存領域.
- header_size
- シーケンスヘッダのサイズ. method=CV_CHAIN_CODEの時, >=sizeof(CvChain) ,それ以外の場合 >=sizeof(CvContour).
- mode
- 抽出モード.cvFindContours を参照.
- method
- 近似手法.cvFindContoursと同様,但し CV_LINK_RUNS は使用不可.
- offset
- ROIのオフセット.cvFindContoursを参照.
関数 cvStartFindContours は初期化を行い,輪郭スキャナのポインタを返す. スキャナはcvFindNextContourにおいて,残りの輪郭を抽出するためにも用いられる.
FindNextContour
画像中の次の輪郭を検索する
CvSeq* cvFindNextContour( CvContourScanner scanner );
- scanner
- 関数cvStartFindContoursで初期化された輪郭スキャナ.
関数 cvFindNextContour は,画像中から次の輪郭を検索・抽出し,そのポインタを返す. これ以上輪郭が見つからない場合,この関数はNULLを返す.
SubstituteContour
抽出された輪郭を置き換える
void cvSubstituteContour( CvContourScanner scanner, CvSeq* new_contour );
- scanner
- 関数cvStartFindContoursで初期化された輪郭スキャナ.
- new_contour
- 新しく置き換える輪郭.
関数 cvSubstituteContour は,直前のcvFindNextContourで抽出され, 輪郭スキャナの内部に保存された輪郭を,ユーザ指定の輪郭と置き換える. 新しい輪郭(抽出モードに応じて,リストや2階層構造あるいはツリー)は,結果として返される構造体に挿入される. パラメータnew_contour=NULLの場合は,抽出された輪郭も,そのすべての子も,結果として返される構造体には含まれず,後から構造体に加えられることもない.
EndFindContours
輪郭走査処理を終了する
CvSeq* cvEndFindContours( CvContourScanner* scanner );
- scanner
- 輪郭スキャナへのポインタ.
関数 cvEndFindContours は,輪郭走査処理を終了し,一番上のレベルにある先頭の輪郭へのポインタを返す.
PyrSegmentation
画像ピラミッドを用いたセグメント化を行う
void cvPyrSegmentation( IplImage* src, IplImage* dst,
CvMemStorage* storage, CvSeq** comp,
int level, double threshold1, double threshold2 );
- src
- 入力画像.
- dst
- 出力画像.
- storage
- 結果として得られる接続成分のシーケンスを保存するための領域.
- comp
- セグメント化された成分の出力シーケンスへのポインタ.
- level
- セグメント化のためのピラミッドの最大レベル.
- threshold1
- リンク構築のための誤差閾値.
- threshold2
- セグメントクラスタリングのための誤差閾値.
関数 cvPyrSegmentation は,画像ピラミッドによる画像のセグメント化を実装する. ピラミッドは,levelまで作成される. p(c(a),c(b))<threshold1 の場合,レベル i の任意のピクセル a と,それに隣接するレベルにある親候補ピクセル b とのリンクが構築される. 連結成分が定義された後,いくつかのクラスタに分類される. p(c(A),c(B))<threshold2 の場合,任意の二つのセグメントAとBは同じクラスタに属する. 入力画像がシングルチャンネルの場合は, p(c¹,c²)=|c¹-c²|. 入力画像が3チャンネル(赤,緑,青)の場合は,p(c¹,c²)=0,3·(c¹r-c²r)+0,59·(c¹g-c²g)+0,11·(c¹b-c²b) . 一つのクラスタについて一つ以上の連結成分が存在する場合もある. 画像 src と dst は8ビットシングルチャンネルか3チャンネル,または同じサイズでないといけない.
PyrMeanShiftFiltering
Mean-Shift法による画像のセグメント化を行う
void cvPyrMeanShiftFiltering( const CvArr* src, CvArr* dst,
double sp, double sr, int max_level=1,
CvTermCriteria termcrit=cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,5,1));
- src
- 入力画像.8ビット,3チャンネル.
- dst
- 出力画像.入力画像と同じフォーマット,同じサイズ.
- sp
- 空間ウィンドウの半径.
- sr
- 色空間ウィンドウの半径.
- max_level
- セグメント化のためのピラミッドの最大レベル.
- termcrit
- 終了条件.Mean-Shiftをいつまで繰り返すか.
関数 cvPyrMeanShiftFiltering は,Mean-Shift法による画像のセグメント化アルゴリズムのフィルタリング部分を実装する.つまり,この関数の出力画像は,色勾配と細かいピクセル値が平坦化された ”posterized”な画像になる.入力画像(あるいはダウンサイズされた入力画像,下記参照)中の各ピクセル(X,Y)において,この関数はMean-Shiftを繰り返し実行する. つまり,空間-色を軸とする超空間内のピクセル (X,Y) の近傍は以下のように表される.
{(x,y): X-sp≤x≤X+sp && Y-sp≤y≤Y+sp && ||(R,G,B)-(r,g,b)|| ≤ sr},ここで (R,G,B) と (r,g,b) は,(X,Y) と (x,y)における,それぞれの色成分のベクトルである(しかし,アルゴリズムは使用される色空間に依存しないので,代わりに任意の3成分を持つ色空間を用いても構わない). 隣接間において,平均の空間(X',Y')と平均の色ベクトル(R',G',B') が計算され,それらは次の繰り返しにおいて以下のように隣接の中心として扱われる.
(X,Y)~(X',Y'), (R,G,B)~(R',G',B').繰り返しの後,最初のピクセル(繰り返しが始まった最初のピクセル)の色成分は,以下のような最終値(最終繰り返し時の色平均)にセットされる.
I(X,Y) <- (R*,G*,B*).
max_level>0 であるなら,max_level+1 レベルのガウシアンピラミッドを作成する. そして上記の処理が最も小さいレイヤーにおいて実行される.その結果はより大 きいレイヤーに伝播され,低解像度のレイヤーとそのレイヤーの色が大幅に異な る(>sr) 位置のピクセルについてのみ,繰り 返しが再び実行される.これは,色領域の境界がより明確になるということを意 味する.ガウシアンピラミッドを用いて得られた結果は,オリジナル画像全体に Mean-Shift 処理を施して(例えば max_level==0 の とき)得られた結果とは異なることに注意する.
Watershed
watershedアルゴリズムによる画像のセグメント化を行う
void cvWatershed( const CvArr* image, CvArr* markers );
- image
- 入力画像.8ビット,3チャンネル画像.
- markers
- 入出力画像.32ビットシングルチャンネルのマーカー画像(マップ).
関数 cvWatershed は,参考文献[Meyer92]にある,ノンパラメトリックマーカーベースのセグメンテーションアルゴリズムであるwatershedの一種を実装する. 画像をこの関数に渡す前に,ユーザーは大まかに画像markers中の処理対象領域を, 正(>0)のインデックスを用いて区切っておかなければならない.例えば,各領域がピクセル値として1,2,3...を持ち,一つあるいはそれ以上の連結成分で表現されるなど.これらの成分は,処理における各画像領域の「シード」となる.区切られた領域との関係が未知なその他の領域は,このアルゴリズムによって関係が定義される.関係が未知の領域の値は0にセットしておく必要がある.関数の出力時には,markers中の各ピクセル値は,シード成分に振られていた値か,領域の間に属する場合の-1,のいずれかがセットされる.
連結成分のそれぞれ二つの隣接間が,watershed境界(値が-1のピクセル)で分離されている必要がないことに注意する.例えば,初期マーカー画像中に接成分(tangent components)が存在する場合など.デモとこの関数の使用方法については,OpenCVサンプルディレクトリ中の watershed.cpp を参照.