C++ 代码看起来不错,因为这创建了一个矩阵wrapper对于提供的图像数据,假设缓冲区是传统的 RGB8 格式。请注意,这个构造函数确实not复制缓冲区,因此缓冲区必须在此期间保持有效Mat
实例(或被复制)。
Mat newImg = Mat(nImageHeight, nImageWidth, CV_8UC3, ptrImageData);
看来问题出在您的 C# 代码中。我不是 C# 开发人员,但我会尽力提供帮助。您正在创建内存流并使用 JPEG 编解码器将图像的压缩版本写入缓冲区,就好像它是文件一样。但那就是not数据格式cv::Mat
正在等待,所以你基本上会看到垃圾(压缩数据解释为未压缩)。
Given a System.Image.Drawing.Image
实例,您可以创建一个包装器Bitmap
直接对象(或者可能使用as
,因为这是一个简单的沮丧)。然后你就可以使用Bitmap.LockBits()方法获取指向底层图像数据的指针。
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。
我也不相信原始代码中的内存管理是完全正确的,但无论如何,只要缓冲区所有权的范围在锁定和解锁方法调用内,上述方法就可以工作。如果图像数据的寿命超过此代码块,则必须复制缓冲区。
也要小心你的像素格式 - 你需要确保Image/Bitmap
实例确实包含 RGB8 数据。 OpenCV 的cv::Mat
具有各种标志,因此您可以使用各种内存中图像格式。但请注意,这些是not与磁盘上(通常是压缩的)格式相同,例如 PNG、TIFF 等。