如何在带有 VB.net GUI 的 C++ OpenCV 项目中使用 C# 库?
Posted
技术标签:
【中文标题】如何在带有 VB.net GUI 的 C++ OpenCV 项目中使用 C# 库?【英文标题】:How do I use a C# library in C++ OpenCV project with a VB.net GUI? 【发布时间】:2011-04-01 10:42:20 【问题描述】:我开发了一个使用 OpenCV 的非托管 C++ 编写的应用程序,直到现在我一直在使用内置的 highgui 库来显示结果。
我现在想与 VB.net 开发人员一起将其打包成适合销售的产品。
我决定做的两个改进是添加一个 GUI,其次通过用 3rdParty 解决方案替换人脸识别模块来改进它。
问题是3rdParty SDK只有一个C# API,显然其他程序员想用VB实现接口。
我可以将我的代码移植到 C# 并使用 EmguCV 一石二鸟,但是代码库非常大,我认为我没有时间,但这是一个选择。
我想知道从这里到哪里去。我是否移植到 MC++、使用混合的 Native 和 Managed 程序集、自己在 Qt 中编写 GUI 等等
另外,如何在 .NET WinForm 控件中显示 Iplimage 流?
【问题讨论】:
【参考方案1】:是否可以在您的情况下实现一些简单的 OpenCV 本机代码的高级 API,以便使用 PInvoke 与 C# 轻松互操作?过去我遇到过类似的问题,我所做的是将我的本机代码与大约 15 个可从 C# 轻松使用的函数打包(使用 PInvoke)。我不知道在你的情况下是否可以轻松地做到这一点,如果没有,你可以尝试在 MC++ 中编写几个类并尝试使用 MC++ 编译你的 OpenCV 代码,毕竟 C++/CLI 的主要用途是创建一个本机 C++ 和托管语言之间的桥梁(尽管如此,我个人仍然更喜欢制作好的本机 API 并从 C# 中 PInvoke。
至于 IplImage,如果您使用的是 EmguCV,则有一个 .Bitmap
属性可以为您提供可以使用的托管 System.Drawing.Bitmap
类,而无需复制底层缓冲区(我在我的应用程序中渲染了来自摄像机的 5 个实时流,它工作得很好)。另一方面,如果您想在不使用 EmguCV 的情况下手动完成,我鼓励您检查他们的源代码并查看他们如何实现此功能并自己完成(基本上,您需要获取指向内存的指针并获取一些属性,例如图像的步幅、宽度、高度,并使用它们自己创建Bitmap
类)。
编辑:我找到了一些用于渲染在 OpenCV 中处理的图像的代码:
C++ 代码:
void __stdcall GetRectifiedImage(Calibration* calib, int left, int** dataPtr, int* stride)
CvMat* mat = ((CalibrationImpl*)calib)->imagesRectified[left > 0 ? 0 : 1];
*dataPtr = mat->data.i;
*stride = mat->step;
这段代码基本上是填充dataPtr和stride(假设宽高已知)
C# PInvoke:
[DllImport("Stereo.dll")]
public static extern void GetRectifiedImage(IntPtr calib, int left, out IntPtr data, out int stride);
C# 用法(使用 EmguCV):
StereoNative.GetDepthImage(calib, out ptr, out stride);
pictureBox5.Image = new Image<Gray, byte>(640, 480, stride, ptr).Bitmap;
如果没有 Emgu,您将需要了解它们如何实现 .Bitmap
属性,然后自己动手制作自己的 Bitmap
对象。
【讨论】:
.Bitmap
看起来很有希望。第二个开发人员可以使用 EmguCV 在他的界面中显示流。至于您的第一个建议,应用程序后端是用我最熟悉的语言 c++ 编写的,我要做的就是添加一个 C# 组件,本质上是在非托管 c++ 中使用托管 dll,或者移植到 MC++,然后调用dll。你的想法?
这里有 Kenny 提到的 COM 方式,你也可以使用 C++/CLI 作为桥梁,你可以有两种不同的使用方式:将你的 c++ 代码移植到 MC++ 并调用 c# 组件,或者创建桥接库:正在使用 c# 组件并具有本机 API(您可以在本机 c++ 中使用而无需将其移植到 MC++)-此类解决方案创建了第三个库,作为桥梁,但允许您“保持本机”与您的核心代码。如果你想这样做,你需要创建一个托管 c++ 库,它具有导出某些功能的函数(通过模块 *.def 文件),而这些函数可以使用管理代码。
谢谢,我会看看这两种解决方案,但根据 kenny 和您的评论,我会尝试走 MC++ 路线。如果我想保持原生状态,可能出于性能原因,我会退后一步尝试桥接。【参考方案2】:
我用过 EmguCV,效果很好。我还将我的 OpenCV C++ 代码放在托管 DLL 中,并且效果也很好。您还可以将 .NET 代码源和接收到您可以在 C++ 端调用的 COM 接口。
【讨论】:
我从未使用过 COM 接口,但那是我倾向于做的事情。话虽如此,您如何看待将我的代码移植到托管 C++ 以使事情变得更简单?还是我错过了什么? @expelledboy,如果是我,我会移植到托管 C++,它几乎可以只是您想要公开的 API 的包装器。虽然 COM 可以工作,但我会尽量避免使用 .NET 接口。 谢谢。我会尝试迁移到 MC++!据我所知,这个过程相对轻松。 最后我使用了 EmguCV。不得不重写一切。 :(【参考方案3】:虽然我已经决定移植到 MC++ 以确保完整性,并且因为我已经完成了研究,但我还可以使用其他两种解决方案。
首先,我可以通过 embedding the mono runtime 从本机 C++ 调用 C# 组件到项目中。看起来很有趣,我将研究它以用于其他项目。
或者我可以使用CLR Hosting API。看起来更像是 hack,然后是第一个但可行的。
最后,对于有兴趣查找将 C++ 移植到其托管形式所需的信息的任何人,请参阅this 链接。看起来本机 C++ 是唯一可以在不修改代码的情况下编译为托管的语言。如果我错了,请纠正我。编辑:我是wrong..
【讨论】:
以上是关于如何在带有 VB.net GUI 的 C++ OpenCV 项目中使用 C# 库?的主要内容,如果未能解决你的问题,请参考以下文章
我如何在 vb.net 中从 Internet 下载文件(zip)
如何从 C++ 调用 VB.NET DLL(也调用函数 - 不仅仅是 DLL 文件)