Cv2.DrawContours の使い方【OpenCV/C#(OpenCvSharp)】〜輪郭を描画する〜

OpenCV for C#
📌 準備: OpenCV の環境構築がまだの方はこちら → C++ 環境構築ガイド / C#(OpenCvSharp)セットアップ

Cv2.DrawContours の使い方【OpenCV/C#(OpenCvSharp)】〜輪郭を描画する〜

Cv2.DrawContours は、Cv2.FindContours で検出した輪郭点列を画像上に描画する関数です。指定した輪郭インデックス・色・線幅を組み合わせることで、検出結果を視覚的に確認したり、マスク画像を生成したりできます。最小の呼び出し例はこのとおりです。

Cv2.DrawContours(dst, contours, -1, Scalar.Green, 2);

動作環境

  • OpenCV 4.x(OpenCvSharp4)
  • .NET 8 コンソールアプリ
  • NuGet: OpenCvSharp4、OpenCvSharp4.runtime.win(Windows 実行時)

環境構築がまだの方は環境構築ガイドを先にどうぞ。


基本の使い方

グレースケール変換 → 二値化 → 輪郭検出 → 描画、という一連の流れをそのまま動かせる完全なサンプルです。

using OpenCvSharp;

// 入力画像の読み込み
using var src = Cv2.ImRead("input.png", ImreadModes.Color);
if (src.Empty()) throw new Exception("画像が読み込めませんでした");

// グレースケール変換
using var gray = new Mat();
Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);

// 大津の方法で二値化
using var binary = new Mat();
Cv2.Threshold(gray, binary, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);

// 輪郭検出
Cv2.FindContours(
    binary,
    out Point[][] contours,
    out HierarchyIndex[] hierarchy,
    RetrievalModes.External,        // 最外輪郭のみ
    ContourApproximationModes.ApproxSimple
);

// 描画先に元画像をコピー
using var dst = src.Clone();

// すべての輪郭を緑・線幅 2 で描画(contourIdx = -1 で全描画)
Cv2.DrawContours(dst, contours, -1, Scalar.Green, 2);

// 結果を保存・表示
Cv2.ImWrite("output.png", dst);
Cv2.ImShow("DrawContours", dst);
Cv2.WaitKey(0);

実行すると、入力画像の物体外周が緑の線で囲まれた output.png が生成され、ウィンドウにも表示されます。

コード解説

行の内容 ポイント
CvtColor → Threshold DrawContours 自体はカラー Mat を受け付けるが、検出には二値化が必要
FindContours の RetrievalModes.External 最外輪郭のみ取得。階層付きが必要な場合は Tree を使う
contourIdx = -1 負値を渡すと contours の全要素を一括描画
dst = src.Clone() 元画像を保護しつつカラーで描画するためコピーを作る

引数と戻り値

void Cv2.DrawContours(
    InputOutputArray image,
    IEnumerable<IEnumerable<Point>> contours,
    int contourIdx,
    Scalar color,
    int thickness = 1,
    LineTypes lineType = LineTypes.Link8,
    IEnumerable<HierarchyIndex>? hierarchy = null,
    int maxLevel = int.MaxValue,
    Point offset = default
)
引数 型 説明
image Mat 描画先 Mat(上書き)。カラー・グレースケール両対応
contours IEnumerable<IEnumerable<Point>> FindContours が返す輪郭点列の配列
contourIdx int 描画する輪郭のインデックス。-1 で全描画
color Scalar 描画色。BGR 順で指定
thickness int 線幅(ピクセル)。-1 または Filled で塗りつぶし
lineType LineTypes Link8(8近傍)・Link4・AntiAlias
hierarchy IEnumerable<HierarchyIndex>? 階層情報。maxLevel と組み合わせて使う
maxLevel int 描画する輪郭の階層深さ上限
offset Point 全輪郭点に加算するオフセット(ROI 描画時に便利)

戻り値は void(画像は image に直接書き込まれます)。


実践例

例 1:特定インデックスの輪郭だけを塗りつぶす

面積が最大の輪郭だけを赤で塗りつぶすパターンです。

using OpenCvSharp;

using var src = Cv2.ImRead("input.png", ImreadModes.Color);
using var gray = new Mat();
using var binary = new Mat();
Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
Cv2.Threshold(gray, binary, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);

Cv2.FindContours(
    binary,
    out Point[][] contours,
    out _,
    RetrievalModes.External,
    ContourApproximationModes.ApproxSimple
);

// 面積が最大の輪郭インデックスを求める
int maxIdx = 0;
double maxArea = 0;
for (int i = 0; i < contours.Length; i++)
{
    double area = Cv2.ContourArea(contours[i]);
    if (area > maxArea) { maxArea = area; maxIdx = i; }
}

using var dst = src.Clone();
// thickness = -1(Filled)で塗りつぶし
Cv2.DrawContours(dst, contours, maxIdx, new Scalar(0, 0, 200), -1);

Cv2.ImWrite("output_filled.png", dst);

例 2:二値化前にガウシアンぼかしを挟んでノイズを減らす

実画像では二値化ノイズが多く、小さな偽輪郭が大量に検出されることがあります。Cv2.GaussianBlur の使い方【OpenCV/C#(OpenCvSharp)】 でぼかしを前処理として挟むと輪郭数が激減します。

using OpenCvSharp;

using var src = Cv2.ImRead("input.png", ImreadModes.Color);
using var gray = new Mat();
using var blurred = new Mat();
using var binary = new Mat();

Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
// ガウシアンぼかしでノイズ除去
Cv2.GaussianBlur(gray, blurred, new Size(5, 5), 0);
Cv2.Threshold(blurred, binary, 0, 255, ThresholdTypes.Otsu | ThresholdTypes.Binary);

Cv2.FindContours(
    binary,
    out Point[][] contours,
    out _,
    RetrievalModes.External,
    ContourApproximationModes.ApproxSimple
);

using var dst = src.Clone();
Cv2.DrawContours(dst, contours, -1, Scalar.Lime, 2);
Cv2.ImWrite("output_blur.png", dst);

描画色の詳細な指定方法はOpenCvSharp.Scalar の使い方【OpenCV/C#】も参考にしてください。


つまずきポイント

⚠️ FindContours の入力を二値化し忘れる

DrawContours 自体はカラー Mat を受け付けますが、FindContours に渡す画像はグレースケール二値化済みである必要があります。カラー画像をそのまま渡すと例外またはゴミ結果になります。前処理のパイプラインを確認してください。

⚠️ Mat を using で解放していないとネイティブメモリリーク

src・gray・binary・dst などの Mat は、すべて using 宣言を付けて確実に解放してください。DrawContours はネイティブ側で実行されるため、GC が即座に回収してくれません。長時間稼働するアプリでは特に顕著なリークになります。

⚠️ contours の型が Point[][] と IEnumerable<IEnumerable<Point>> で混乱しやすい

OpenCvSharp の FindContours は out Point[][] contours を返しますが、DrawContours の第 2 引数は IEnumerable<IEnumerable<Point>> です。Point[][] はこのインターフェースを実装しているのでそのまま渡せます。明示的なキャストは不要です。


関連する関数


まとめ

Cv2.DrawContours は FindContours の結果をそのまま受け取って描画できる、輪郭可視化の定番関数です。contourIdx = -1 で全描画、thickness = -1 で塗りつぶしと、引数の組み合わせだけで用途が大きく変わります。前処理のぼかし・二値化をしっかり整えることが、意図どおりの輪郭を得るための実質的な鍵です。

🛠 画像処理のプロが開発するSDK/API

本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/APIを開発しています。SDK は C#/.NET 8 に正式対応しており、OpenCvSharp を使うプロジェクトからそのまま組み込めます。

→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

タイトルとURLをコピーしました