輪郭を取得する

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.Treeで検出した結果

ContourRetrieval.Externalで検出した結果 上の図で緑で表現された輪郭は消えています。

 Windows7 Vs2008 OpenCv2.4 And OpenCvSharp

ところで Android版を記述した際 DrawContoursメソッドが見つからないと記述しましたが 見落としでした。DrawContoursメソッドを使う形で 修正します。

スポンサーリンク
Rectangle大広告
Rectangle大広告

シェアする

  • このエントリーをはてなブックマークに追加

フォローする