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.FindContours — 輪郭検出。DrawContours とセットで使う基本関数
- Cv2.ContourArea — 輪郭の面積を算出。描画前のフィルタリングに使う
- Cv2.BoundingRect — 輪郭を囲む矩形を取得。
Cv2.Rectangleと組み合わせてバウンディングボックスを描画できる - Cv2.Threshold の使い方【OpenCV/C#(OpenCvSharp)】 — DrawContours の前処理として必須の二値化
- Cv2.AdaptiveThreshold の使い方【OpenCV/C#(OpenCvSharp)】 — 照明ムラがある画像での輪郭検出に有効
まとめ
Cv2.DrawContours は FindContours の結果をそのまま受け取って描画できる、輪郭可視化の定番関数です。contourIdx = -1 で全描画、thickness = -1 で塗りつぶしと、引数の組み合わせだけで用途が大きく変わります。前処理のぼかし・二値化をしっかり整えることが、意図どおりの輪郭を得るための実質的な鍵です。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/APIを開発しています。SDK は C#/.NET 8 に正式対応しており、OpenCvSharp を使うプロジェクトからそのまま組み込めます。
→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

