因为实验室统一用C#,最近一直在思考如何将写好的C++代码转化为C#。
众所周知,OpenCV是一个图形图像处理方面的库,里边封装了许多针对C、C++有用的函数。有时候用C++实现了某些功能,但C#不能直接调用OpenCV,因此两种语言不能直接混合编程。要实现C#调用OpenCV函数,可以将本机C++代码(指非托管C++)编译成一个dll,供C#调用。调用方法为 [DllImport(×××.dll)] 。(还有其他的方法,大家可以通过某度搜索)
下面详细演示一下这种方法实现的过程。
运行环境:VS2013+OpenCV3.0
(1)打开VS2013,新建一个Visual C++空项目,文件名称和位置可以自己修改。
(2)在解决方案资源管理器中新建一个头文件(.h)。
(3)在新建的头文件中,输入以下内容
extern "C" __declspec(dllexport) void AutoFocus();
extern "C"外部声明,表示函数和变量是按照C语言的方式编译和链接的。
_decspec(dllexport)的目的是为了将对应的函数放入到DLL动态库中。
extern "C" _declspec(dllexport)的目的是为了使用DllImport调用非托管C++的DLL文件。因为使用DllImport只能调用由C语言函数做的DLL。
(4)在源文件文件夹下新建C++文件(.cpp)
(5)在新建的demo.cpp中输入代码
#include
#include
#include "opencv2/core/core.hpp"
#include
#include "opencv2/highgui/highgui.hpp"
#include
#include"demo.h" //这里对应你新建的那个头文件
using namespace std;
using namespace cv;
void AutoFocus()
{
string pattern = "D:/皮卡丘最可爱/*.jpg"; //test的图片放在D盘
vector images;
vector pic; // 必须cv的String
glob(pattern, pic, false);
size_t count = pic.size();
cout << count << endl; //显示一共有多少张图片
for (int i = 0; i < count; i++)
{
images.push_back(imread(pic[i]));
Mat imageSource = images[i];
Mat imageGrey;
cvtColor(imageSource, imageGrey, COLOR_RGB2GRAY);
Mat imageSobel;
Laplacian(imageGrey, imageSobel, CV_16U); //Laplacian梯度法,数值越大表示图像越清晰
double meanValue = 0.0;
meanValue = mean(imageSobel)[0]; //图片清晰度
//double to string
stringstream meanValueStream;
string meanValueString; //字符串
meanValueStream << meanValue;
meanValueStream >> meanValueString;
meanValueString = "Articulation(Laplacian Method): " + meanValueString;
putText(imageSource, meanValueString, Point(20, 20), FONT_HERSHEY_COMPLEX, 0.7, Scalar(255, 0, 0), 2);
imshow("Articulation", imageSource);
waitKey(1000);
cout << meanValue << endl; //显示图片的清晰度
//将清晰度数据存为xml文件
FileStorage mul_wr("D:\\pikaqiu.xml", FileStorage::APPEND);
mul_wr << "meanValue" << meanValue;
mul_wr.release();
}
}
出现红色波浪线是因为没有添加OpenCV配置文件,加上即可。
(配置方法可参考:https://blog.csdn.net/poem_qianmo/article/details/19809337)
(6)在源文件文件夹下新建模块定义文件(.def)
(7)模块定义文件demo.def里内容如下:
代码:
LIBRARY demo
EXPORTS AutoFocus
EXPORTS后面的就是你要调用的方法名,生成.dll文件的同时也会生成.lib库。
(8)重新生成解决方案,可能会出现以下错误:
这是运行库设置的问题,几个工程的运行库设置不一样。解决方法:
【项目属性】→ 【配置属性】→ 【C/C++ 】→ 【代码生成】→ 【运行库】→ 【多线程调试(/MTd)】
再重新生成解决方案。
(9)再重新生成整个解决方案,可能又会出现以下错误:
这是因为输出文件拓展名的问题,解决方法如下:
【项目属性】→ 【配置属性】→【常规】→【目标文件扩展名】,将.exe,改为.dll
这时再重新生成解决方案就可以啦~
(10)找到解决方案所在目录,在Debug目录下即可找到生成的 .dll 文件。要注意的是,要到整个解决方案的目录下找Debug文件夹,如下图
(1)新建一个C#项目。(把装有照片的文件夹放在D盘,并命名为“皮卡丘最可爱”。ps:照片在博文最后)
(2)把demo.dll文件复制到该工程的Debug目录下。
(3)在C#文件中引用该 .dll 文件,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices; //新增
using System.Text;
using System.Threading.Tasks;
namespace test
{
class Program
{
[DllImport("demo.dll")] //新增
private extern static void AutoFocus(); //新增
static void Main(string[] args)
{
Console.WriteLine("C#调用dll");
AutoFocus();
Console.Read();
}
}
}
(4)点击运行,大功告成啦!!!
PS:“皮卡丘最可爱”图片,4张图片清晰度不同。