Cv2.Canny の使い方【OpenCV/C#(OpenCvSharp)】〜エッジ検出で輪郭を抽出する〜

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

Cv2.Canny の使い方【OpenCV/C#(OpenCvSharp)】〜エッジ検出で輪郭を抽出する〜

Cv2.Canny は、画像からエッジ(輪郭)を検出する OpenCV の代表的な関数です。ヒステリシスしきい値を使った Canny エッジ検出アルゴリズムを 1 行で呼び出せます。

Cv2.Canny(src, dst, threshold1: 50, threshold2: 150);

動作環境

  • OpenCV 4.x(OpenCvSharp4)
  • .NET 8 コンソールアプリ(トップレベルステートメント)
  • NuGet: OpenCvSharp4 + OpenCvSharp4.runtime.win(Windows 実行時)

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


基本の使い方

using OpenCvSharp;

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

// Canny エッジ検出(しきい値 50/150 はよく使われる出発点)
using var edges = new Mat();
Cv2.Canny(src, edges, threshold1: 50, threshold2: 150);

// 結果を保存
Cv2.ImWrite("edges.png", edges);
Console.WriteLine("エッジ画像を edges.png に保存しました");

実行結果

エッジ画像を edges.png に保存しました

edges.png を開くと、白いラインとして輪郭が抽出されたグレースケール画像が得られます。

各行の解説

行 ポイント
ImRead(..., Grayscale) Canny はグレースケール入力を受け取る。カラー画像を渡すとエラーになる
threshold1: 50 弱いエッジの下限しきい値。これを下回るエッジは除外される
threshold2: 150 強いエッジの上限しきい値。これを超えるエッジは確実に採用される
edges 出力は 8bit シングルチャンネル(グレースケール)の Mat

引数と戻り値

Cv2.Canny(Mat src, Mat dst, double threshold1, double threshold2,
          int apertureSize = 3, bool L2gradient = false)
引数 型 説明
src Mat 入力画像(8bit グレースケール)
dst Mat 出力エッジ画像(src と同サイズ・8bit 1ch)
threshold1 double ヒステリシスの低しきい値
threshold2 double ヒステリシスの高しきい値
apertureSize int Sobel フィルタのカーネルサイズ(3/5/7、省略可)
L2gradient bool true にすると L2 ノルムでグラジェント計算(精度向上・省略可)

戻り値はありません(dst に結果が書き込まれます)。


実践例

実践例 1: ガウシアンぼかしでノイズを除去してからエッジ検出

Canny は微分演算を使うため、ノイズに敏感です。事前にぼかしを入れることで不要なエッジを抑制できます。

using OpenCvSharp;

using var src = Cv2.ImRead("input.jpg", ImreadModes.Grayscale);
if (src.Empty()) throw new Exception("画像を読み込めませんでした");

// ノイズ除去のためガウシアンぼかしを前処理として適用
using var blurred = new Mat();
Cv2.GaussianBlur(src, blurred, new Size(5, 5), sigmaX: 0);

// ぼかし後にエッジ検出
using var edges = new Mat();
Cv2.Canny(blurred, edges, threshold1: 50, threshold2: 150);

Cv2.ImWrite("edges_blurred.png", edges);
Console.WriteLine("前処理ありのエッジ画像を保存しました");

ガウシアンぼかしの詳細はCv2.GaussianBlur の使い方【OpenCV/C#(OpenCvSharp)】〜ガウシアンぼかしで画像を平滑化する〜を参照してください。


実践例 2: カラー画像からエッジを検出してオーバーレイ表示

カラー画像を読み込み、エッジを赤色で元画像に重ねて保存します。

using OpenCvSharp;

// カラーで読み込み
using var colorSrc = Cv2.ImRead("input.jpg", ImreadModes.Color);
if (colorSrc.Empty()) throw new Exception("画像を読み込めませんでした");

// グレースケールに変換して Canny に渡す
using var gray = new Mat();
Cv2.CvtColor(colorSrc, gray, ColorConversionCodes.BGR2GRAY);

using var blurred = new Mat();
Cv2.GaussianBlur(gray, blurred, new Size(5, 5), sigmaX: 0);

using var edges = new Mat();
Cv2.Canny(blurred, edges, threshold1: 50, threshold2: 150);

// エッジ部分を赤色で元画像に重ねる
using var overlay = colorSrc.Clone();
overlay.SetTo(new Scalar(0, 0, 255), edges); // edges をマスクとして使用

Cv2.ImWrite("overlay.png", overlay);
Console.WriteLine("オーバーレイ画像を overlay.png に保存しました");

Mat.SetTo(value, mask) の第 2 引数にエッジ画像を渡すことで、エッジのピクセルのみを赤に塗り替えられます。


しきい値の選び方

threshold1 と threshold2 の比率は 1:2 〜 1:3 が一般的な目安です(Canny 本人の推奨比)。

用途 threshold1 threshold2
細かいエッジまで拾う 30 90
標準的な設定(出発点) 50 150
太く明確なエッジのみ 100 200

⚠️ 画像の明るさや被写体によって最適値は変わるため、実際の画像で試しながら調整してください。


つまずきポイント

⚠️ カラー画像をそのまま渡すとエラーになる

Canny はグレースケール(8bit 1ch)の入力を要求します。カラー画像(3ch)を渡すと実行時例外が発生します。Cv2.CvtColor で BGR2GRAY に変換してから渡してください。

// NG: カラー画像をそのまま渡す
Cv2.Canny(colorMat, edges, 50, 150); // → 例外

// OK: グレースケールに変換してから渡す
Cv2.CvtColor(colorMat, gray, ColorConversionCodes.BGR2GRAY);
Cv2.Canny(gray, edges, 50, 150);

⚠️ Mat の Dispose 漏れに注意

new Mat() で生成した中間画像(blurred、edges など)は using で解放してください。解放しないとネイティブメモリがリークします。Canny のように複数の中間 Mat を扱うコードほど注意が必要です。

⚠️ しきい値の大小が逆だと全エッジが消える

threshold1 > threshold2 になるよう渡してもエラーにはなりませんが、ほとんどのエッジが弱エッジとして棄却され、真っ黒な画像が出力されます。必ず threshold1 < threshold2 になっているか確認してください。


関連する関数


まとめ

Cv2.Canny は threshold1・threshold2 の 2 つのしきい値を指定するだけで実用的なエッジ検出が行えます。ノイズに弱い性質があるため、Cv2.GaussianBlur による前処理をセットで使うのが現場のセオリーです。カラー画像はグレースケール変換を忘れずに行い、using による Mat の解放を徹底することで安定したコードになります。

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

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

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

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