关于c ++:将opencv图像cv :: Mat格式转换为C#BitmapImage

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);
}

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


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