OpenCV从字节数组创建Mat [英] OpenCV create Mat from byte array

查看:1075
本文介绍了OpenCV从字节数组创建Mat的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的C ++ dll中,我从字节数组创建Mat:

In my C++ dll I am creating Mat from byte array:

BYTE * ptrImageData;  //Image data is in this array passed to this function

Mat newImg = Mat(nImageHeight, nImageWidth, CV_8UC3, ptrImageData);

图像创建时带有一些灰色阴影,而不是原始的灰色阴影.

The image is created with some gray shade not the original one.

这是从字节数组创建Mat的正确方法吗?

Is this the proper way of creating Mat from byte array?

请参见代码

ptrImageData从C#代码传递到C ++ dll.

ptrImageData is passed to the C++ dll from C# code.

用于传递图像数据的C#代码

C# code to pass the image data

System.Drawing.Image srcImage //Has the image
MemoryStream ms = new MemoryStream(); 
Marshal.FreeHGlobal(ptrImageData); 
srcImage.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); 
byte[] imgArray = ms.ToArray();
ms.Dispose();


int size1 = Marshal.SizeOf(imgArray[0]) * imgArray.Length;
IntPtr ptrImageData = Marshal.AllocHGlobal(size1);
Marshal.Copy(imgArray, 0, ptrImageData, imgArray.Length);

//Calling C++ dll function
ProcessImage(ptrImageData, srcImage.Width, srcImage.Height);

Marshal.FreeHGlobal(ptrImageData);

推荐答案

C ++代码似乎正常,因为假定缓冲区在常规格式中,这会为提供的图像数据创建一个矩阵 wrapper RGB8格式.请注意,此构造函数不会复制缓冲区,因此该缓冲区必须在此Mat实例的持续时间内保持有效(或被复制).

The C++ code appears ok, in that this creates a matrix wrapper for the supplied image data, assuming the buffer is in the conventional RGB8 format. Note that this constructor does not copy the buffer, so the buffer must remain valid for the duration of this Mat instance (or be copied).

Mat newImg = Mat(nImageHeight, nImageWidth, CV_8UC3, ptrImageData);

问题似乎出在您的C#代码中.我不是C#开发人员,但我会尽力提供帮助.您正在创建一个内存流,并使用JPEG编解码器将图像的压缩版本写入缓冲区,就好像它是一个文件一样.但这不是cv::Mat期望的数据格式,因此您基本上会看到垃圾(压缩数据被解释为未压缩).

It appears the problem lies in Your C# code. I am not a C# developer, but I will do my best to help. You are creating a memory stream and using the JPEG codec to write a compressed version of the image into the buffer as if it were a file. But that is not the data format that cv::Mat is expecting, so you will basically see garbage (compressed data interpreted as uncompressed).

给出一个System.Image.Drawing.Image实例,您可以直接创建一个包装器Bitmap对象(或者可以使用as,因为它是一个简单的向下转换).然后,您可以使用 Bitmap.LockBits() 方法tog获得指向基础图像数据的指针.

Given a System.Image.Drawing.Image instance, you can create a wrapper Bitmap object directly (or maybe use as, since it is a simple downcast). Then you can just use the Bitmap.LockBits() method tog obtain a pointer to the underlying image data.

Bitmap bmp = new Bitmap(sourceImage);

// Lock the bitmap's bits.  
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
System.Drawing.Imaging.BitmapData bmpData =
    bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
    bmp.PixelFormat);

// Get the address of the first line.
IntPtr ptr = bmpData.Scan0;

// Declare an array to hold the bytes of the bitmap.
int bytes  = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbBuffer = new byte[bytes];

// Copy the RGB values into the array.
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbBuffer, 0, bytes);

// Do your OpenCV processing...
// ...

// Unlock the bits.
bmp.UnlockBits(bmpData);

,然后您可以将rgbBuffer传递给OpenCV.

and then you can pass the rgbBuffer to OpenCV.

我也不相信原始代码中的内存管理也是完全正确的,但是无论如何,只要缓冲区所有权的范围在lock和unlock方法调用之内,上述方法就可以工作.如果图像数据要超出此代码块的寿命,则必须复制缓冲区.

I'm not convinced that the memory management in the original code is entirely correct either, but anyway the above will work provided the scope of the buffer ownership is within the lock and unlock method calls. If the image data is to outlive this code block, you will have to copy the buffer.

也要小心像素格式-您需要确保Image/Bitmap实例确实包含RGB8数据. OpenCV的cv::Mat具有各种标志,因此您可以使用多种内存图像格式.但是请注意,它们与磁盘上(通常是压缩的)格式(例如PNG,TIFF等)不同.

Be careful with your pixel formats too - you need to make sure the Image/Bitmap instance really contains RGB8 data. OpenCV's cv::Mat has various flags so you can work with a variety of in-memory image formats. But note that these are not the same as the on-disk (typically compressed) formats, such as PNG, TIFF, and so forth.

这篇关于OpenCV从字节数组创建Mat的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆