Mat の使い方【OpenCV/C#(OpenCvSharp)】作成・初期化・基本操作

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

Mat の使い方【OpenCV/C#(OpenCvSharp)】作成・初期化・基本操作

OpenCV における Mat は、画像やテンソルを表す中心的なデータ構造です。C#(OpenCvSharp)でも Mat クラスがその役割を担い、ピクセルデータの読み書きから行列演算まで一手に引き受けます。この記事では Mat の作成・初期化・基本操作を、動くコードとともに体系的に押さえます。

using var mat = new Mat(480, 640, MatType.CV_8UC3);

動作環境

項目 バージョン
OpenCV 4.x(OpenCV 4.x 時点の情報)
OpenCvSharp4 4.9.x(NuGet)
OpenCvSharp4.runtime.win 同上(Windows 実行時に必須)
.NET 8(コンソール・トップレベルステートメント)

NuGet パッケージは以下の2つを必ずインストールしてください。

dotnet add package OpenCvSharp4
dotnet add package OpenCvSharp4.runtime.win

基本の使い方

完全プログラム

using OpenCvSharp;

// 1. サイズ・型を指定して Mat を作成(中身は未初期化)
using var mat1 = new Mat(480, 640, MatType.CV_8UC3);

// 2. 指定値で初期化して作成
using var mat2 = new Mat(480, 640, MatType.CV_8UC3, new Scalar(128, 0, 0));

// 3. ゼロ行列(黒画像)
using var zeros = Mat.Zeros(300, 400, MatType.CV_8UC1);

// 4. 全要素 1 の行列(白画像には 255 倍が必要)
using var ones = Mat.Ones(300, 400, MatType.CV_8UC1);

// 5. 単位行列(3x3, 64bit 浮動小数点)
using var eye = Mat.Eye(3, 3, MatType.CV_64FC1);

// 基本プロパティを確認
Console.WriteLine($"mat2 サイズ : {mat2.Rows} x {mat2.Cols}");
Console.WriteLine($"mat2 チャネル数 : {mat2.Channels()}");
Console.WriteLine($"mat2 要素型  : {mat2.Type()}");
Console.WriteLine($"mat2 空か   : {mat2.Empty()}");

// 6. 画像ファイルから読み込み
using var img = Cv2.ImRead("input.png", ImreadModes.Color);
if (img.Empty())
{
    Console.WriteLine("画像の読み込みに失敗しました");
    return;
}
Console.WriteLine($"img サイズ  : {img.Rows} x {img.Cols}");

// 7. ROI(部分領域)を切り出す(メモリ共有に注意)
using var roi = new Mat(img, new Rect(100, 100, 200, 150));

// 8. クローン(独立したコピー)
using var cloned = img.Clone();

// 9. 保存
Cv2.ImWrite("output.png", cloned);
Console.WriteLine("output.png を保存しました");

実行結果

mat2 サイズ : 480 x 640
mat2 チャネル数 : 3
mat2 要素型  : CV_8UC3
mat2 空か   : False
img サイズ  : (input.png の実際の高さ) x (幅)
output.png を保存しました

行ごとの解説

説明
new Mat(rows, cols, type) 行(高さ)→列(幅)の順。未初期化のためノイズが入る
new Mat(..., new Scalar(...)) 第4引数で初期値を指定。チャネル数に合わせて Scalar(B,G,R)
Mat.Zeros / Mat.Ones ゼロ・1 で埋めた行列を返すスタティックメソッド
Mat.Eye 単位行列。線形代数処理の基点として使う
mat.Rows / mat.Cols 高さ・幅(int)
mat.Channels() チャネル数(グレー=1, BGR=3, BGRA=4)
mat.Type() MatType を返す。デバッグ時に必ず確認
new Mat(img, new Rect(...)) ROI。元の Mat とメモリを共有する点に要注意
img.Clone() ディープコピー。ROI を独立させたいときに使う

引数と戻り値

new Mat(int rows, int cols, MatType type)

引数 説明
rows int 行数(=画像の高さ)
cols int 列数(=画像の幅)
type MatType 要素型とチャネル数の組み合わせ(下表参照)

new Mat(int rows, int cols, MatType type, Scalar s)

引数 説明
s Scalar 初期値。new Scalar(v0, v1, v2, v3) で最大4チャネルを指定

よく使う MatType

MatType 意味 用途例
CV_8UC1 8bit 符号なし・1ch グレースケール画像
CV_8UC3 8bit 符号なし・3ch BGR カラー画像
CV_8UC4 8bit 符号なし・4ch BGRA(透過あり)
CV_32FC1 32bit 浮動小数点・1ch 深度マップ・スコアマップ
CV_64FC1 64bit 浮動小数点・1ch 行列計算

Mat.Zeros / Mat.Ones / Mat.Eye

Mat Mat.Zeros(int rows, int cols, MatType type)
Mat Mat.Ones(int rows, int cols, MatType type)
Mat Mat.Eye(int rows, int cols, MatType type)

戻り値はいずれも新しい Matusing で受け取ること。


実践例

実践例1: グレースケール画像を黒→白にグラデーション塗りつぶし

using OpenCvSharp;

// 1行ずつ異なる輝度を書き込む
using var grad = new Mat(256, 256, MatType.CV_8UC1);
for (int r = 0; r < grad.Rows; r++)
{
    // 行全体を同じ輝度値で塗る
    grad.Row(r).SetTo(new Scalar(r));
}
Cv2.ImWrite("gradient.png", grad);
Console.WriteLine("gradient.png を保存しました");

Mat.Row(r) で取得した行 Mat は元 Mat とメモリを共有するため、SetTo が直接反映されます。

実践例2: ROI 操作(部分領域に矩形を描画)

using OpenCvSharp;

using var canvas = new Mat(480, 640, MatType.CV_8UC3, Scalar.All(200));

// ROI を取得して塗りつぶし(元 canvas に反映される)
var roiRect = new Rect(100, 100, 200, 150);
using var roi = new Mat(canvas, roiRect);
roi.SetTo(new Scalar(0, 0, 255)); // 赤で塗る

Cv2.ImWrite("roi_result.png", canvas);
Console.WriteLine("roi_result.png を保存しました");

ROI への書き込みは元の canvas に直接反映されます。意図せず元画像を変更しないよう、変更前に Clone() しておく設計が安全です。


つまずきポイント

⚠️ using を忘れるとネイティブメモリがリークする

Mat は C++ のネイティブヒープにピクセルデータを持ちます。GC が回収するのはマネージドラッパーだけで、ネイティブ側は Dispose() を呼ぶまで解放されません。ループ内で大量に Mat を生成するコードでは、using の付け忘れが致命的なメモリリークにつながります。

// NG: GC 任せ
var mat = new Mat(1080, 1920, MatType.CV_8UC3);

// OK: using で確実に解放
using var mat = new Mat(1080, 1920, MatType.CV_8UC3);

⚠️ ROI は元 Mat とメモリを共有する

using var roi = new Mat(src, new Rect(0, 0, 100, 100));
roi.SetTo(Scalar.All(0)); // src の左上100x100 も黒になる!

独立したコピーが必要なときは roi.Clone() を使ってください。

⚠️ Rows・Cols の順番(高さ→幅)に注意

コンストラクタの引数順は (rows, cols) つまり (高さ, 幅) です。new Mat(640, 480, ...) と書くと 640行×480列、すなわち縦長の画像になります。Size を使う場合は new Size(width, height) と逆になるため、混在すると混乱しやすい箇所です。

// (rows=高さ, cols=幅)
using var mat = new Mat(480, 640, MatType.CV_8UC3);

// Size は (width, height)
using var mat2 = new Mat(new Size(640, 480), MatType.CV_8UC3);

関連する関数

  • Cv2.ImRead / Cv2.ImWrite — ファイルから Mat を読み書きする基本関数
  • Cv2.CvtColorMat のチャネル変換(BGR ↔ グレースケール 等)
  • Cv2.ResizeMat のリサイズ
  • Mat.Clone / Mat.CopyToMat のコピー操作

まとめ

Mat は OpenCvSharp のあらゆる処理の出発点です。作成・初期化の方法(new MatMat.ZerosMat.Ones)を使い分け、ROI とクローンの違いを意識するだけで大半の基本操作に対応できます。using による確実な解放は C# 固有の必須作法として、コードの最初から習慣づけてください。

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

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

→ なりすまし判定SDK/APIの詳細を見る
→ API仕様書・サンプルコード

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