如何将.NET位图和OpenCV图像指向同一块内存?

Sea*_*ean 1 .net opencv bitmap emgucv

如何将.NET位图和OpenCV图像指向同一块内存?我知道我可以从一个复制到另一个,但我更希望他们只指向相同的像素.

使用Emgu的解决方案的奖励积分.

max*_*max 5

以下只是一个理论,可能不起作用,我对opencv/emgucv不是很有经验


双方System.Drawing.BitmapEmgu.CV.Image具有构造以scan0作为参数.您可以为映像分配内存并将此指针传递给该构造函数.内存可以通过var ptr = Marshal.AllocHGlobal(stride*height)(不要忘记free ofc)或通过分配足够大小的托管数组并获取其地址来分配.地址可以通过以下方式获取:

var array = new byte[stride*height];
var gch = GCHandle.Alloc(array, GCHandleType.Pinned);
var ptr = gch.AddrOfPinnedObject();
Run Code Online (Sandbox Code Playgroud)

这也是"引脚"数组,所以它不能被垃圾收集器移动,地址也不会改变.

我们将使用这些构造函数:

Bitmap(int width, int height, int stride, PixelFormat format, IntPtr scan0);
Image<Bgr, Byte>(int width, int height, int stride, IntPtr scan0);
Run Code Online (Sandbox Code Playgroud)

widthheight论点是不言自明的. format对于位图是PixelFormat.Format24bppRgb.stride是单行图像的字节数,它也必须对齐(是4的倍数).你可以这样得到它:

var stride = (width * 3);
var align = stride % 4;
if(align != 0) stride += 4 - align;
Run Code Online (Sandbox Code Playgroud)

并且scan0是指向我们的内存块的指针.

所以我建议在创建System.Drawing.BitmapEmgu.CV.Image使用这些构造函数之后将使用相同的内存块.如果没有,这意味着opencv或Bitmap或两者都提供了内存块和可能的解决方案(如果它存在)绝对不值得努力.