【问题标题】:Passing cv::Mat from C++ to C# (managed)将 cv::Mat 从 C++ 传递到 C#(托管)
【发布时间】:2017-10-07 14:11:00
【问题描述】:

我正在为在 C# 中使用 C++ 代码编写一个包装器。

我有一个函数应该将 cv::Mat 返回给 C#,但我找不到将 Mat 传递给 C# 的方法。

示例:

我想要这样的东西:

cv::Mat MyProject::ReturnColorMat()
{
    return _colorMat;
}

我知道 C# 正在使用 Emgu,两者之间有转换吗?

我尝试传递Matbyte array,这很有效,但我想传递Mat 本身。

这可能吗?

【问题讨论】:

    标签: c# c++ opencv managed emgucv


    【解决方案1】:

    本机结构和托管结构在内存中的布局不同,因此跨托管/非托管边界成功传递结构需要额外的步骤来保持数据完整性。 (see here)

    一种可能性是在 C++ 端将 cv::Mat 转换为位图,然后使用 PInvoke 在 C# 中获取位图
    在 C++ 端你可以使用这个函数,取自here

    CBitmap* IplImageToCBitmap(IplImage* img) 
    {
        CDC dc;
        CDC memDC;
    
        if (!dc.CreateDC("DISPLAY", NULL, NULL, NULL))
            return NULL;
    
        if (!memDC.CreateCompatibleDC(&dc))
            return NULL;
    
        CBitmap* bmp = new CBitmap();
        CBitmap* pOldBitmap;
    
        bmp->CreateCompatibleBitmap(&dc, img->width, img->height);
        pOldBitmap = memDC.SelectObject(bmp);
    
        CvvImage cvImage; // you will need OpenCV_2.2.0- to use CvvImage 
        cvImage.CopyOf(img);
        cvImage.Show(memDC.m_hDC, 0, 0, img->width, img->height, 0, 0);
        cvImage.Destroy();
    
        memDC.SelectObject(pOldBitmap);
        memDC.DeleteDC();
        dc.DeleteDC();
    
        return bmp;
    }
    

    然后以这种方式包装你的函数

    extern "C" __declspec( dllexport) HRESULT WrappedFunction(HBITMAP * hBitmap);
    
    HRESULT WrappedFunction(/*[out]*/ HBITMAP * hBitmap)
    {
        cv::Mat aMat = YourFunction();
    
        CBitmap *bmp = IplImageToCBitmap((IplImage*) &aMat);
    
        *hBitmap = (HBITMAP)bmp->Detach();
    
        return S_OK;
    }
    

    然后,在 C# 方面你可以这样做:

    IntPtr ret;
    WrappedFunction( out ret );
    Bitmap b = Image.FromHbitmap( ret );
    

    【讨论】:

      【解决方案2】:

      您可以在 C# 中创建一个 COM 接口,并从中生成一个可在 C++ 中使用的 .tlb 文件 像这样,您可以使用相同的接口来引用托管对象。

      C#

        [ComVisible(true)]
      
         [Guid("12345678-3914-41F0-BB26-122986A93788")]
      
         [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
      
         public interface IMat
         {...}
      
         public class ManagedMat : IMat
         {...}
      
        [DllImport("cppProjectname.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
        public static extern int call2Cpp(IMat obj);
      

      C++

      #import "projectname.tlb" no_registry raw_interfaces_only
      
      // use IMat to access the ManagedMat object
      extern "C"  int __declspec(dllexport) call2Cpp( IMat obj )
      {...}
      

      【讨论】:

        猜你喜欢
        • 2010-12-18
        • 2019-01-20
        • 2015-05-31
        • 2011-09-15
        • 2013-09-02
        • 1970-01-01
        • 2020-02-04
        • 1970-01-01
        • 2013-02-09
        相关资源
        最近更新 更多