Ниже приведена теория, которая может не сработать, я не очень разбираюсь в opencv / emgucv
Оба System.Drawing.Bitmap
и Emgu.CV.Image
имеют конструкторы, принимающие scan0
в качестве аргумента. Вы можете выделить память для изображения и передать этот указатель этим конструкторам.
память может быть выделена с помощью var ptr = Marshal.AllocHGlobal(stride*height)
(не забудьте освободить от нее) или путем выделения управляемого массива достаточного размера и получения его адреса. Адрес можно получить следующим образом:
var array = new byte[stride*height];
var gch = GCHandle.Alloc(array, GCHandleType.Pinned);
var ptr = gch.AddrOfPinnedObject();
Это также массив "pins", поэтому он не может быть перемещен сборщиком мусора и адрес не изменится.
Мы будем использовать эти конструкторы:
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
- количество байтов для одной строки изображения, оно также должно быть выровнено (кратно 4). Вы можете получить это так:
var stride = (width * 3);
var align = stride % 4;
if(align != 0) stride += 4 - align;
И scan0
- указатель на наш блок памяти.
Поэтому я предлагаю, чтобы после создания System.Drawing.Bitmap
и Emgu.CV.Image
с использованием этих конструкторов использовался один и тот же блок памяти. Если нет, то это означает, что opencv или Bitmap или оба предоставленных копии блока памяти и возможное решение (если оно существует) определенно не стоит усилий.