我尝试为OpenCV编写一个CLI包装器,它从给定的OpenCV矩阵返回一个位图。我在包装器中使用带有修复映像的函数来测试它:
Bitmap^ GetImage()
{
Mat frame = imread("Image.png", 0);
return gcnew Bitmap(frame.cols, frame.rows, 4 * frame.rows, System::Drawing::Imaging::PixelFormat::Format24bppRgb, IntPtr(frame.data));
}
我的C#代码包含以下用于存储图像的代码:
Bitmap Test = Wrapper.GetImage();
Test.Save(@"C:\temp\Bla.bmp");
执行代码后,我遇到了这个例外:
我该如何解决?这个例外的原因是什么?
答案 0 :(得分:1)
这不会奏效。因为'框架'当函数返回时,变量超出范围。因此,指针已经死了,你有一个带有垃圾数据指针的GDI对象。
调用者负责分配和释放scan0参数指定的内存块。但是,在释放相关的Bitmap之前,不应释放内存。
我不确定这个Mat对象是什么,但你得到一维字节行并对预先分配的字节数组(数组^)执行Marshal :: Copy()。
我要么返回从Mat对象创建的数组,要在C#中创建位图,如下所示:
https://stackoverflow.com/a/21555447/887584
或者你可以在C ++代码中这样做,如果你想保持关注点的分离,在C ++中做同样的事情:
auto stream = gcnew MemoryStream(bytes);
auto bitmap = gcnew Bitmap(stream);
delete stream;
return bitmap;
答案 1 :(得分:0)
我在C ++中使用Marshal :: Copy()尝试过它,但仍然遇到同样的问题。我的新功能如下所示:
Bitmap^ GetImage()
{
Mat mat_frame = imread("Unbenannt.png", 0);
int size = mat_frame.total() * mat_frame.elemSize();
int cols = mat_frame.cols;
int rows = mat_frame.rows;
array<byte>^ managed_image = gcnew array<byte>(rows * cols);
Marshal::Copy(IntPtr((void *)mat_frame.data), managed_image, 0, size);
IntPtr ptr_managed_image = (IntPtr)GCHandle::Alloc(managed_image);
return gcnew Bitmap(cols, rows, 4 * rows, PixelFormat::Format24bppRgb, ptr_managed_image);
}