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)
戻り値はいずれも新しい Mat。using で受け取ること。
実践例
実践例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.CvtColor—Matのチャネル変換(BGR ↔ グレースケール 等)Cv2.Resize—MatのリサイズMat.Clone/Mat.CopyTo—Matのコピー操作
まとめ
Mat は OpenCvSharp のあらゆる処理の出発点です。作成・初期化の方法(new Mat・Mat.Zeros・Mat.Ones)を使い分け、ROI とクローンの違いを意識するだけで大半の基本操作に対応できます。using による確実な解放は C# 固有の必須作法として、コードの最初から習慣づけてください。
🛠 画像処理のプロが開発するSDK/API
本ブログを運営するスワローインキュベートは、OpenCV ベースのなりすまし判定SDK/APIを開発しています。SDK は C#/.NET 8 に正式対応しており、OpenCvSharp を使うプロジェクトからそのまま組み込めます。

