如何将托管位图从 C# 传递到包装的非托管 OpenCV 的 Mat

How to pass managed Bitmap from C# to wrapped unmanaged OpenCV's Mat

本文关键字:包装 Mat OpenCV 位图      更新时间:2023-10-16

我有一个由三部分组成的项目:

  1. 托管的C#项目有一个回调,它给了我一个位图(它应该有PixelFormat=Format24bppRgb)。我已经尝试了几种方法来将位图转换为我可以传递到第2部分的东西,这是我尝试的最后一件事:

    public int BufferCB(IntPtr pBuffer, int BufferLen)
    {
        byte[] aux = new byte[BufferLen];
        Marshal.Copy(pBuffer, aux, 0, BufferLen);
        String s_aux = System.Text.Encoding.Default.GetString(aux);
        wrappedClassInstance.GetBitmap(s_aux);
    }
    
  2. 托管C++/CLI包装项目3:

    int WrappedClass::GetBitmap(array<System::Byte>^ s_in) {
        pin_ptr<unsigned char> pin = &s_in[0];
        unsigned char* p = pin;
        return privateImplementation->GetBitmap(p);
    }
    
  3. 使用OpenCV的非托管C++应用程序。我想用将这些数据加载到Mat中

    Mat myMat;
    int NativeClass::GetBitmap(unsigned char *s_in) {
        // If there's no input:
        if (!s_in) {
            return -1;
        }
        /* h and w are defined elsewhere */
        myMat = Mat(h, w, CV_8UC3, (void *)s_in, Mat::AUTO_STEP));
        imwrite("test.bmp", myMat);
        return 0;
    }
    

当到达imwrite函数时,将引发异常:"System.Runtime.InteropServices.SEHException(0x80004005)"。它没有说太多,但我猜我传递到Mat的数据在整理时已经损坏了。

以前,我试图在没有包装器的情况下传递数据:

[DllImport("mydll.dll", ...)]
static extern void GetBitmap(IntPtr pBuffer, int h, int w);
void TestMethod(IntPtr pBuffer, int BufferLen)
{
    // h and w defined elsewhere
    // GetBitmap is essentially the same as in item 3.
    GetBitmap(pBuffer, BufferLen, h, w);
}

这起到了作用(它将位图保存到文件中),但由于DLL在我终止进程之前一直处于附加状态,因此该解决方案对我来说不够好。我也不想将Mat类"镜像"到我的项目中,因为我知道Mat应该接受来自某些字符*的数据。

请帮忙,我该怎么做?我是否进行了错误的类型转换?

谢谢。

我已经将第2部分从memcpy非托管内存更改为本机内存,只是为了确保这一点。但我的代码真正的问题是,每次我想得到一个新的Mat时,我都会调用Mat构造函数:

Mat myMat;
int MyClass::GetBitmap(unsigned char* s_in) {
    myMat = Mat(...)
}

相反,我做了:

Mat myMat;
int MyClass::GetBitmap(unsigned char* s_in) {
    Mat aux;
    aux = Mat(...)
    aux.copyTo(myMat);
    aux.release();
}

现在我的代码运行得很好。

编辑:删除了一些使用new Mat(...)的部分,这是一个拼写错误,它无法编译,因为我使用的是Mat,而不是Mat*。