自制OpenCV的C++ dll文件,C#调用OpenCV函数

因为实验室统一用C#,最近一直在思考如何将写好的C++代码转化为C#

众所周知,OpenCV是一个图形图像处理方面的库,里边封装了许多针对C、C++有用的函数。有时候用C++实现了某些功能,但C#不能直接调用OpenCV,因此两种语言不能直接混合编程。要实现C#调用OpenCV函数,可以将本机C++代码(指非托管C++)编译成一个dll,供C#调用。调用方法为 [DllImport(×××.dll)] 。(还有其他的方法,大家可以通过某度搜索)

下面详细演示一下这种方法实现的过程。

运行环境:VS2013+OpenCV3.0

第一步:将C++代码编译成一个dll文件

(1)打开VS2013,新建一个Visual C++空项目,文件名称和位置可以自己修改。

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第1张图片

(2)在解决方案资源管理器中新建一个头文件(.h)。

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第2张图片

(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)

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第3张图片

(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)

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第4张图片

(7)模块定义文件demo.def里内容如下:

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第5张图片

代码:

LIBRARY demo 
EXPORTS AutoFocus 

EXPORTS后面的就是你要调用的方法名,生成.dll文件的同时也会生成.lib库。

(8)重新生成解决方案,可能会出现以下错误:

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第6张图片

这是运行库设置的问题,几个工程的运行库设置不一样。解决方法:

【项目属性】→ 【配置属性】→ 【C/C++ 】→ 【代码生成】→ 【运行库】→ 【多线程调试(/MTd)】

再重新生成解决方案。 

(9)再重新生成整个解决方案,可能又会出现以下错误:

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第7张图片

这是因为输出文件拓展名的问题,解决方法如下:

【项目属性】→ 【配置属性】→【常规】→【目标文件扩展名】,将.exe,改为.dll

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第8张图片

这时再重新生成解决方案就可以啦~

(10)找到解决方案所在目录,在Debug目录下即可找到生成的 .dll 文件。要注意的是,要到整个解决方案的目录下找Debug文件夹,如下图

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第9张图片

第二步:C#调用dll文件

(1)新建一个C#项目。(把装有照片的文件夹放在D盘,并命名为“皮卡丘最可爱”。ps:照片在博文最后)

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第10张图片

(2)把demo.dll文件复制到该工程的Debug目录下。 

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第11张图片

(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)点击运行,大功告成啦!!!

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第12张图片

 

 

 

 

 

PS:“皮卡丘最可爱”图片,4张图片清晰度不同。

自制OpenCV的C++ dll文件,C#调用OpenCV函数_第13张图片自制OpenCV的C++ dll文件,C#调用OpenCV函数_第14张图片自制OpenCV的C++ dll文件,C#调用OpenCV函数_第15张图片自制OpenCV的C++ dll文件,C#调用OpenCV函数_第16张图片

你可能感兴趣的:(C#)