Converting an opencv image cv::Mat Format to a C# BitmapImage
我编写了这个示例代码来解释我的问题。我在VS 2013中有一个解决方案,包含一个C项目和一个C++项目。我尝试用C++在OpenCV(x86)中读取图像。并希望将C_x86项目(使用clr模式)传递给位图对象,然后将BitmapImage对象用作WPF图像源。我的C++代码:
1 2 3 4 5 6 7 8 9 | Bitmap^ SomeClass::Test(System::String^ imgFileName) { auto fileName = msclr::interop::marshal_as<string>(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代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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++Pr.PNG)保存的文件是完美的,而另一个在C语言中表示位图对象的只是一个具有该图像高度和宽度的灰色矩形。问题出在哪里?如何将图像传递给我的C项目?
我认为这是一个很古老的问题,但我刚刚遇到了一个类似的任务。我认为最好将数据复制到托管堆并让clr处理它,而不是让非托管资源保持活动状态并在托管代码中使用它。以下是我的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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<System::Byte>(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); } |
也许它能帮助将来偶然发现它的人。
似乎问题在于共享内存。