.NET ビットマップと OpenCV イメージが同じメモリ チャンクを指すようにするにはどうすればよいですか? あるピクセルから別のピクセルにコピーできることはわかっていますが、同じピクセルを指しているだけの方がいいと思います。
Emgu を使用したソリューションのボーナス ポイント。
以下は単なる理論であり、機能しない可能性があります。私はopencv/emgucvの経験があまりありません
との両方System.Drawing.Bitmap
に、引数としてEmgu.CV.Image
取るコンストラクターがあります。scan0
イメージにメモリを割り当て、このポインターをそのコンストラクターに渡すことができます。メモリはvar ptr = Marshal.AllocHGlobal(stride*height)
(ofc を解放することを忘れないでください) によって、または十分なサイズのマネージ配列を割り当ててそのアドレスを取得することによって割り当てることができます。アドレスは次の方法で取得できます。
var array = new byte[stride*height];
var gch = GCHandle.Alloc(array, GCHandleType.Pinned);
var ptr = gch.AddrOfPinnedObject();
これも配列を「固定」するため、ガベージコレクターによって移動できず、アドレスは変更されません。
これらのコンストラクターを使用します。
Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0);
Image<Bgr, Byte>(int width, int height, int stride, IntPtr scan0);
width
引数はheight
自明です。
format
ビットマップ用はPixelFormat.Format24bppRgb
。stride
画像の 1 行のバイト数であり、位置合わせも必要です (4 の倍数)。次の方法で取得できます。
var stride = (width * 3);
var align = stride % 4;
if(align != 0) stride += 4 - align;
Andscan0
はメモリ ブロックへのポインタです。
したがって、これらのコンストラクターを作成System.Drawing.Bitmap
しEmgu.CV.Image
て使用した後、同じメモリ ブロックを使用することをお勧めします。そうでない場合は、opencv またはビットマップ、または提供されたメモリ ブロックと可能な解決策 (存在する場合) の両方をコピーすることは、明らかに努力する価値がないことを意味します。
Emgu.CV
ソースから:
// Summary:
// The Get property provide a more efficient way to convert Image<Gray, Byte>,
// Image<Bgr, Byte> and Image<Bgra, Byte> into Bitmap such that the image data
// is shared with Bitmap. If you change the pixel value on the Bitmap, you change
// the pixel values on the Image object as well! For other types of image this
// property has the same effect as ToBitmap() Take extra caution not to use
// the Bitmap after the Image object is disposed The Set property convert the
// bitmap to this Image type.
public Bitmap Bitmap { get; set; }
基本的に、特定の種類の画像について.Bitmap
は、CV 画像のプロパティを使用するだけで、CV 画像データを直接参照できます。
例:
string filename;
// ... point filename to your file of choice ...
Image<Bgr, byte> cvImg = new Image<Bgr, byte>(filename);
Bitmap netBmp = cvImg.Bitmap;
これが役立つかどうかはわかりませんが、.Ptrを使用してEmgu画像からポインタを取得できます
例:IntPtr ip = img1.Ptr;