Как получить растровое изображение .NET и изображение OpenCV для указания на один и тот же кусок памяти? - PullRequest
1 голос
/ 27 мая 2010

Как получить растровое изображение .NET и изображение OpenCV для указания на один и тот же кусок памяти? Я знаю, что могу копировать с одного на другое, но я бы предпочел, чтобы они просто указывали на одни и те же пиксели.

Бонусные баллы за решение с использованием Emgu.

Ответы [ 3 ]

5 голосов
/ 04 июня 2010

Ниже приведена теория, которая может не сработать, я не очень разбираюсь в 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 или оба предоставленных копии блока памяти и возможное решение (если оно существует) определенно не стоит усилий.

2 голосов
/ 05 января 2011

Из источника 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;
0 голосов
/ 29 сентября 2010

Не уверен, поможет ли это, но вы можете получить указатель с изображения Emgu, используя .Ptr

например. IntPtr ip = img1.Ptr;

...