Marshal.Copy()を使いMatオブジェクトとC#のbyte配列間でピクセルデータのコピーが出来るようなので試してみました。
Matオブジェクトからbyte配列へコピー
// Matオブジェクト生成
Mat mat = new Mat(200, 300, MatType.CV_8UC1, Scalar.Gray);
// byte[]生成
byte[] pixels = new byte[mat.Total() * mat.Channels()];
// Matオブジェクトをbyte[]へコピー
Marshal.Copy(mat.Data, pixels, 0, pixels.Length);
byte配列からへMatオブジェクトへコピー
// byte[]をMatオブジェクトへコピー
Marshal.Copy(pixels, 0, mat.Data, pixels.Length);
byte配列の書き換えサンプル(Winforms)
灰色の画像のMatオブジェクトからbyte配列を生成。
byte配列を黒から白へグラデーションになるように書換。
Winformsで表示します。
using System.Runtime.InteropServices;
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace GrayMo01;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
// Matオブジェクト生成
Mat mat = new Mat(200, 300, MatType.CV_8UC1, Scalar.Gray);
// byte[]生成
byte[] pixels = new byte[mat.Total() * mat.Channels()];
// Matオブジェクトをbyte[]へコピー
Marshal.Copy(mat.Data, pixels, 0, pixels.Length);
// byte[]を書き換え
for(int i = 0; i < pixels.Length; i++)
{
pixels[i] = (byte)(i / mat.Width);
}
// byte[]をMatオブジェクトへコピー
Marshal.Copy(pixels, 0, mat.Data, pixels.Length);
this.BackgroundImageLayout = ImageLayout.Center;
this.BackgroundImage = mat.ToBitmap();
}
}
(グラデーションの計算が雑。画像の高さが256以上だと破綻。)
カラーだと色々面倒そうなので8ビットのグレスケールでのサンプルになります。
System.Drawing.Bitmapとbyte配列をコピーする方法と似ていますが、こちらはBitmapのロックなどの機構がなく(あるかもしれませんが知らない)strideの計算が無い分シンプルな構成だと思います。
サンプルプログラムを作るにあたり、元の画像を灰色で塗りつぶされた画像を用意しましたが、初期化時の引数がwidthとheightではなくrowとcolumonですので縦横が反対になります。(何故?)
あとMatオブジェクトをビットマップオブジェクトに変更しフォームのバックグラウンドイメージにセットしていますが、Matおbジェクトからビットマップオブジェクトの変換がmat.ToBitmap()で行っています。BitmapConverter.ToBitmap()と同じものでしょう。(多分)
カラーの場合どのようになるのかは、必要に迫られたら調べてみたいと思います。
コメント