OpenCv cookbookでは 次は『楕円フィッティングを行う』 になっていますが 手元に 適当なデータが無かったので同じ findContoursメソッドを使って 輪郭の取得を行います。
public static int FindContours(CvArr image,CvMemStorage storage,out CvSeq<CvPoint> first_contour,int header_size,ContourRetrieval mode,ContourChain method)
CvArr image : 入力画像,8ビット,シングルチャンネルの2値画像。
また,この関数は,輪郭抽出処理中に入力画像 image の中身を書き換えます。
CvMemStorage storage : 作業用領域。
out CvSeq<CvPoint> first_contour : 検出された輪郭.各輪郭は,点のベクトルとして格納されます。
int header_size : CvContour.SizeOf を指定すれば良いようです。
ContourRetrieval mode : 輪郭抽出モード
External 最も外側の輪郭のみを抽出します。
List すべての輪郭を抽出しますが,一切の階層構造を保持しません。
CComp すべての輪郭を抽出し,それらを2階層構造として保存します。
Tree すべての輪郭を抽出し,入れ子構造になった輪郭を完全に表現する階層構造を構成します。
ContourChain method : 輪郭の近似手法
None すべての輪郭点を完全に格納します.つまり,この手法により格納された任意の隣り合う2点は,互いに8近傍に存在します。
ApproxSimple 水平・垂直・斜めの線分を圧縮し,それらの端点のみを残します.例えば,まっすぐな矩形の輪郭線は,4つの点にエンコードされます。
ApproxTC89L1・ApproxTC89KCOS Teh-Chinチェーン近似アルゴリズムの1つを適用します.
コーディング |
ボタンクリック時の動作 入力画像を グレースケール化した後 2値化し さらに輪郭を検出しています。
private void btnDetect_Click(object sender, EventArgs e) { IplImage gray = new IplImage(src.Size, BitDepth.U8, 1); src.CvtColor(gray, ColorConversion.BgraToGray); IplImage bin = gray.Clone(); Cv.Threshold(gray, bin, 0, 255, ThresholdType.Binary | ThresholdType.Otsu); // 輪郭の検出 CvSeq<CvPoint> contours; CvMemStorage storage = new CvMemStorage(); Cv.FindContours(bin, storage, out contours, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple); //輪郭の描画 Cv.DrawContours(src, contours, new CvScalar(0, 0, 255), new CvScalar(0, 255, 0), 3); storage.Dispose(); pictureBox1.Invalidate(); }
ここで 輪郭の描画には DrawContoursメソッドを使っています。このメソッドは 外側の輪郭と 穴(hole)の輪郭の色を変えて描画できるので 外側は赤 穴は緑 で描画してみました。
処理結果 |
ContourRetrieval.Externalで検出した結果 上の図で緑で表現された輪郭は消えています。
Windows7 Vs2008 OpenCv2.4 And OpenCvSharp |
ところで Android版を記述した際 DrawContoursメソッドが見つからないと記述しましたが 見落としでした。DrawContoursメソッドを使う形で 修正します。