2017-05-09 5 views
0

Ich schreibe einen Wrapper für die Verwendung von C++ - Code in C#).Weitergabe von cv :: Mat von C++ nach C# (verwaltet)

Ich habe eine Funktion, die cv::Mat zurück zu C# zurückgeben sollte, aber ich kann keinen Weg finden, um die an C# zu übergeben.

Beispiel:

Ich möchte so etwas haben:

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

Ich weiß, dass C# mit Emgu arbeiten, gibt es eine Konvertierung zwischen den beiden?

Ich versuchte, die byte array der Mat übergeben, und das hat funktioniert, aber ich würde gerne die Mat selbst übergeben.

Ist das überhaupt möglich?

Antwort

0

Sie können eine COM-Schnittstelle in C# erstellen und daraus eine TLB-Datei generieren, die in C++ verwendet werden kann. So können Sie dieselbe Schnittstelle für die Bezugnahme auf ein verwaltetes Objekt verwenden.

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) 
{...} 
0

native und verwaltete Strukturen sind unterschiedlich im Speicher angelegt, so erfolgreich Strukturen über die verwaltete/nicht verwaltete Grenze vorbei erfordert zusätzliche Schritte, um die Datenintegrität zu bewahren. (see here)

Eine Möglichkeit ist cv :: Mat zu konvertieren in der C++ Seite Bitmap und als die Bitmap in C# erhält unter Verwendung von PInvoke
in der C++ Seite Sie diese Funktion nutzen zu können, genommen von 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; 
} 

und dann wickeln Sie Ihre Funktion auf diese Weise

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

dann wird in der # Seite C Sie tun könnten:

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