将opencv图像cv :: Mat格式转换为C#BitmapImage

我写了这个示例代码来解释我的问题。 我在VS 2013中有一个解决方案,包含一个C#项目和一个C ++项目。 我尝试用C ++(x86)中的OpenCV读取图像。 并希望将C#x86项目(使用CLR模式)传递给Bitmap Object和BitmapImage对象以用作WPF ImageSource。
我的C ++代码:

Bitmap^ SomeClass::Test(System::String^ imgFileName) { auto fileName = msclr::interop::marshal_as(imgFileName); Mat img = imread(fileName); //Do something auto bmp = gcnew Bitmap(img.cols, img.rows, img.step, Imaging::PixelFormat::Format24bppRgb, (IntPtr)img.data); bmp->Save("InC++Side.png"); return bmp; } 

我的C#代码:

 private void ImageTester(object sender, RoutedEventArgs e) { var image = testClass.Test("test.png"); image.Save("InC#Side.png"); bg.Source = ConvertToBitmapImageFromBitmap(image); } public static BitmapImage ConvertToBitmapImageFromBitmap(Bitmap image) { using(var ms = new MemoryStream()) { image.Save(ms, System.Drawing.Imaging.ImageFormat.Png); BitmapImage bImg = new BitmapImage(); bImg.BeginInit(); bImg.StreamSource = new MemoryStream(ms.ToArray()); bImg.EndInit(); return bImg; } } 

问题是C ++(InC ++ Side.png)保存的文件是完美的; 但是在C#中呈现Bitmap对象的另一个只是一个灰色矩形,具有该图像的高度和宽度。
问题出在哪儿?
我如何将Image传递给我的C#项目?

我认为这是一个相当古老的问题,但我刚刚遇到了类似的任务。 我认为最好将数据复制到托管堆并让CLR处理它,而不是让非托管资源保持活动并在托管代码中使用它。 这是我的方法:

 System::Windows::Media::ImageSource^ ManagedCppClass::GetLatestImage() { cv::Mat frame; if (!videoSrc->read(frame)) return nullptr; int totSize = frame.total() * frame.elemSize(); auto managedArray = gcnew array(totSize); System::Runtime::InteropServices::Marshal::Copy(System::IntPtr((void*)frame.data), managedArray, 0, totSize); //assume isContinuous is always true at this point (?) return System::Windows::Media::Imaging::BitmapImage::Create( frame.cols, frame.rows, 96, 96, System::Windows::Media::PixelFormats::Bgr24, //Rgb24, System::Windows::Media::Imaging::BitmapPalettes::WebPalette, managedArray, frame.step); } 

也许它会帮助将来偶然发现它的人。

似乎问题在于共享内存。
MatBitmapC++中共享内存。 因此,当Mat对象销毁时, Bitmap对象无法访问数据。 这就是为什么它的数据在C ++方面是正确的,但在C#方面没有任何内容。
为了解决这个问题,我使用了static Mat 。 它永远不会释放,但可以解决我的问题。