将cv :: Mat从C ++传递给C#(托管)

时间:2017-05-09 10:04:32

标签: c# c++ opencv managed emgucv

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

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

示例:

我想要这样的事情:

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

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

我尝试传递byte array的{​​{1}},但这有效,但我想通过Mat本身。

这甚至可能吗?

2 个答案:

答案 0 :(得分:0)

您可以在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 )
{...}

答案 1 :(得分:0)

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

一种可能性是在C ++端将cv :: Mat转换为Bitmap,而不是使用PInvoke获取C#中的Bitmap 在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 );