Cv2.MorphologyEx は、膨張・収縮を組み合わせたモルフォロジー変換をワンコールで実行できる関数です。オープニング(ノイズ除去)・クロージング(穴埋め)・トップハット変換など、二値画像処理の定番操作をすべてカバーします。
Cv2.MorphologyEx(src, dst, MorphTypes.Open, kernel);
動作環境
- OpenCV 4.x(OpenCvSharp4)
- .NET 8 / コンソールアプリ(トップレベルステートメント)
- NuGet:
OpenCvSharp4、OpenCvSharp4.runtime.win(Windows実行時)
環境構築がまだの方は環境構築ガイドを先にどうぞ。
基本の使い方
まずオープニング処理(小さなノイズを除去する)の完全なサンプルを示します。
using OpenCvSharp;
// グレースケール画像を読み込む
using var src = Cv2.ImRead("input.png", ImreadModes.Grayscale);
if (src.Empty()) throw new Exception("画像の読み込みに失敗しました");
// 二値化(大津の方法)
using var binary = new Mat();
Cv2.Threshold(src, binary, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
// 構造化要素(カーネル)を生成: 5×5 の楕円形
using var kernel = Cv2.GetStructuringElement(
MorphShapes.Ellipse,
new Size(5, 5));
// オープニング: 収縮 → 膨張(小さなノイズを除去)
using var opened = new Mat();
Cv2.MorphologyEx(binary, opened, MorphTypes.Open, kernel);
// クロージング: 膨張 → 収縮(小さな穴・隙間を埋める)
using var closed = new Mat();
Cv2.MorphologyEx(binary, closed, MorphTypes.Close, kernel);
Cv2.ImWrite("opened.png", opened);
Cv2.ImWrite("closed.png", closed);
Console.WriteLine("オープニング・クロージング処理が完了しました");
実行すると、カレントディレクトリに opened.png(ノイズ除去済み)と closed.png(穴埋め済み)が出力され、コンソールに次のメッセージが表示されます。
オープニング・クロージング処理が完了しました
コードのポイント
Cv2.GetStructuringElementでカーネルを生成します。形状はRect(矩形)・Cross(十字)・Ellipse(楕円)から選べます。サイズが大きいほど処理の影響範囲が広がります。MorphTypes.Openが「収縮 → 膨張」(オープニング)、MorphTypes.Closeが「膨張 → 収縮」(クロージング)です。この組み合わせを手動で2回呼ぶ代わりにMorphologyEx1回で完結します。Matはすべてusingで管理し、ネイティブメモリを確実に解放しています。
引数と戻り値
| 引数 | 型 | 内容 |
|---|---|---|
src |
Mat |
入力画像(グレースケール・カラー両対応) |
dst |
Mat |
出力画像(srcと同サイズ・同チャンネル) |
op |
MorphTypes |
変換の種類(下表参照) |
element |
Mat |
構造化要素(カーネル)。GetStructuringElement で生成 |
anchor |
Point |
(省略可)カーネルのアンカー点。デフォルトは中心 (-1,-1) |
iterations |
int |
(省略可)反復回数。デフォルトは 1 |
borderType |
BorderTypes |
(省略可)境界の補完方法。デフォルトは Reflect101 |
borderValue |
Scalar |
(省略可)Constant 境界時の値 |
戻り値はありません(dst に結果が書き込まれます)。
MorphTypes の主な値
| 値 | 内容 |
|---|---|
Erode |
収縮(Erosion) |
Dilate |
膨張(Dilation) |
Open |
オープニング(収縮 → 膨張) |
Close |
クロージング(膨張 → 収縮) |
Gradient |
モルフォロジー勾配(膨張 − 収縮) |
TopHat |
トップハット変換(元画像 − オープニング) |
BlackHat |
ブラックハット変換(クロージング − 元画像) |
実践例
実践例 1: 指紋・文書画像の細線ノイズ除去(オープニング)
スキャン文書や指紋画像では、二値化後に孤立した細かいノイズが残りがちです。オープニングで短時間に除去できます。
using OpenCvSharp;
using var src = Cv2.ImRead("document.png", ImreadModes.Grayscale);
if (src.Empty()) throw new Exception("画像の読み込みに失敗しました");
using var binary = new Mat();
Cv2.Threshold(src, binary, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
// 3×3 の矩形カーネルで軽めのオープニング
using var kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
using var result = new Mat();
Cv2.MorphologyEx(binary, result, MorphTypes.Open, kernel, new Point(-1, -1), iterations: 2);
Cv2.ImWrite("document_cleaned.png", result);
Console.WriteLine("ノイズ除去完了");
iterations: 2 で反復回数を増やすことで、カーネルサイズを変えずに処理を強くできます。
実践例 2: 欠陥検査での穴埋め(クロージング)
工業製品の外観検査では、対象領域の内側に小さな欠落(穴)が生じることがあります。クロージングで安定した塗りつぶしが行えます。
using OpenCvSharp;
using var src = Cv2.ImRead("defect.png", ImreadModes.Grayscale);
if (src.Empty()) throw new Exception("画像の読み込みに失敗しました");
using var binary = new Mat();
Cv2.Threshold(src, binary, 128, 255, ThresholdTypes.Binary);
// 楕円カーネルで穴埋め(カーネルが大きいほど大きな穴も閉じる)
using var kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(9, 9));
using var result = new Mat();
Cv2.MorphologyEx(binary, result, MorphTypes.Close, kernel);
Cv2.ImWrite("defect_filled.png", result);
Console.WriteLine("クロージング処理完了");
二値化については Cv2.Threshold の使い方【OpenCV/C#(OpenCvSharp)】〜画像を二値化する(大津の方法含む)〜 も合わせてご覧ください。照明ムラがある環境では Cv2.AdaptiveThreshold の使い方【OpenCV/C#(OpenCvSharp)】〜適応的二値化で照明ムラに強い処理を実現する〜 との組み合わせが有効です。
つまずきポイント
⚠️ カーネル(Mat)を Dispose し忘れる
Cv2.GetStructuringElement の戻り値は Mat です。通常の画像と同様に using で管理しないとネイティブメモリがリークします。カーネルは小さいので気づきにくいですが、ループ内で繰り返し生成する処理では確実に問題になります。
// NG: using なし
var kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(5, 5));
// OK: using で解放を保証
using var kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(5, 5));
⚠️ MorphTypes の Open / Close と処理順の混同
MorphTypes.Open(オープニング)は「収縮 → 膨張」、MorphTypes.Close(クロージング)は「膨張 → 収縮」です。名前だけ覚えると順番を逆に実装してしまうことがあります。効果で覚えるのが確実です。
- Open → 白い前景の 小さな点(ノイズ)を消す(前景が収縮されるため)
- Close → 白い前景の 小さな穴・隙間を埋める(前景が膨張されるため)
⚠️ カーネルサイズは奇数でなければならない
GetStructuringElement に偶数サイズを渡すとアンカー中心が曖昧になり、意図しない位置ずれが発生することがあります。Size(5, 5) や Size(9, 9) のように奇数を使う習慣をつけてください。
関連する関数
Cv2.Erode/Cv2.Dilate: 収縮・膨張を単体で行う関数。MorphologyExの内部でも使われており、単純な1ステップ処理ならこちらが直感的です。Cv2.GetStructuringElement:MorphologyExに渡すカーネルを生成する関数。形状とサイズがそのまま処理の挙動を決めます。Cv2.Threshold/Cv2.AdaptiveThreshold: モルフォロジー処理は通常二値化後に適用します。内部リンク先の記事も参照してください。- ノイズ除去という観点では、グレースケール画像に対しては Cv2.MedianBlur の使い方【OpenCV/C#(OpenCvSharp)】〜メディアンフィルタで画像のノイズを除去する〜 との使い分けも検討に値します。二値化前のノイズ抑制にはメディアンフィルタ、二値化後の形状調整にはモルフォロジー処理、という役割分担が現場ではよく使われます。
まとめ
Cv2.MorphologyExはオープニング・クロージングをはじめ7種類のモルフォロジー変換を統一的に呼び出せる関数です。- カーネルは
Cv2.GetStructuringElementで生成し、usingで確実に解放することが C# では必須です。 - 用途に合わせて
MorphTypesとiterations・カーネルサイズを調整するだけで、ノイズ除去から穴埋めまで幅広い二値画像処理に対応できます。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/APIを開発しています。SDK は C#/.NET 8 に正式対応しており、OpenCvSharp を使うプロジェクトからそのまま組み込めます。
→ 顔認証のなりすまし対策 設計チェックリスト(当ブログ)
→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

