我正在编写一个用于在 C# 中使用C++代码的包装器(。
我有一个函数应该将cv::Mat
返回到 C#,但我找不到将Mat
传递给 C# 的方法。
例:
我想要这样的东西:
cv::Mat MyProject::ReturnColorMat()
{
return _colorMat;
}
我知道C#正在使用Emgu
,两者之间有转换吗?
我尝试通过Mat
的byte array
,这奏效了,但我想通过Mat
本身。
这可能吗?
您可以在 C# 中创建 COM 接口,并从中生成一个可用于C++像这样,您可以使用相同的接口来引用托管对象。
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 )
{...}
本机结构和托管结构在内存中的布局不同,因此成功跨托管/非托管边界传递结构需要额外的步骤来保持数据完整性。(看这里(
一种可能性是在C++端将 cv::Mat 转换为位图,然后使用 PInvoke
在 C# 中获取位图在C++方面,您可以使用此功能,从这里获取
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 );