【2】C#调用c++DLL图像处理库(OpenCV)以及图像数据数据转换

tech2022-11-25  91

【1】配置环境

电脑配置:w764+vs2017+opencv4.3.0(选择的就是普通的c++空项目文件,参考:C#调用c++的图像处理库(OpenCV))

解决方案配置:debug+x64(注意c++中的配置环境要和c#中的环境保持一致)

有些网友是在QT环境下编写的,有些是在clr环境下编写的,没有说明很难区分,本文是在纯c++环境下调用OpenCV编写的。

【2】实现思路

(1)c#中读入一个图片的路径。

(2)c#中调用c++的dll库,将图片路径传送到dll库中的函数。

(3)dll中的函数作用,完成图像处理,并将结果传送给c#中。

 注意要点:(1)环境配置  (2)参数对应,c#的参数好c++里面的参数对应的不一样。

特别注意一点参数的对应,最容易出受访问的内存受保护问题

C#和C++对应参数转换

将string转为IntPtr:IntPtr System.Runtime.InteropServices.Marshal.StringToCoTaskMemAuto(string) 将IntPtr转为string:string System.Runtime.InteropServices.MarshalPtrToStringAuto(IntPtr) c++ <----------> c# BSTR --------- StringBuilder LPCTSTR --------- StringBuilder LPCWSTR --------- IntPtr handle---------IntPtr hwnd-----------IntPtr char *----------string int * -----------ref int int &-----------ref int void *----------IntPtr unsigned char *-----ref byte Struct需要在C#里重新定义一个Struct CallBack回调函数需要封装在一个委托里,delegate static extern int FunCallBack(string str); 注意在每个函数的前面加上public static extern +返回的数据类型,如果不加public ,函数默认为私有函数,调用就会出错。

/*本文参数对应          @filename: 图片的路径名;------------在c#中类型为string ,在c++dll中对应的是char*          @data: 返回图片存放的数组,dll在使用时调用C#申明的这段内存,然后在c++将数据存放到此数组中;----------在c#中类型为byte ,在c++dll中对应的是 uchar*          @size: 图像的宽高信息。-------- 在c#中类型为ulong  c++中为size_t类型         */

【3】编写dll库

步骤参考:C#调用c++的图像处理库(OpenCV)

本次dll代码:

.cpp文件

#include"unmanage.h" #include<opencv.hpp> #include<opencv2/highgui.hpp> #include "opencv2/imgproc/imgproc_c.h"//IplImage头文件 #include <opencv2/core.hpp> #include<iostream> #include <opencv2/imgproc/imgproc.hpp> #include "opencv2/highgui/highgui.hpp" #include<algorithm> #include<vector> #include<typeinfo> using namespace std; using namespace cv; //自己编写的图像处理函数 void GrayImage(Mat & image, Mat & grayimage) { cvtColor(image, grayimage, COLOR_BGR2GRAY); } //需要导出的dll函数 DLL_API void GetMat(char * filename ,uchar *data, size_t&size) { //【1】图像打开 std::vector<uchar> buf; //cv::Mat src = cv::imread("C:\\Users\\Administrator\\Pictures\\opencvpicture\\beads.jpg"); //读入一个Mat cv::Mat src = cv::imread(filename); cv::Mat grayimage; //【2】图像处理 //调用自己OpenCV编写的函数 GrayImage(src, grayimage); //【3】图像数据导出 cv::imencode(".bmp", grayimage, buf); //将Mat以bmp格式存入内存中,转换为uchar数组 size = buf.size(); for (uchar &var : buf) { *data = var; data++; } }

.h文件

#pragma once #define DLL_API extern "C" _declspec(dllexport)

.def文件

LIBRARY unmanaged EXPORTS GetMat

【4】c#文件

(1)创建窗体应用

(2)创建界面

(3)单击灰度化按钮,在里面复制一下代码

 

[DllImport("unmanaged.dll")] private extern static void GetMat(string filename, ref byte data, out ulong size); /* @filename: 图片的路径名;------------在c#中类型为string ,在c++dll中对应的是char* @data: 返回图片存放的数组,dll在使用时调用C#申明的这段内存,然后在c++将数据存放到此数组中;----------在c#中类型为byte ,在c++dll中对应的是 uchar* @size: 图像的宽高信息。-------- 在c#中类型为ulong c++中为size_t类型 */ private void button4_Click(object sender, EventArgs e) { string filename = "C:\\Users\\Administrator\\Pictures\\opencvpicture\\arrow2.jpg";//文件路径 byte[] ptrData = new byte[2048 * 2048 * 3]; //尽可能大的byte[],一般大于显示的最大图片内存即可 ulong size = new ulong(); GetMat(filename, ref ptrData[0], out size); //调用dll库中的函数,将C++的内存数据转入C#的内存中 pictureBox1.Image = Image.FromStream(new MemoryStream(ptrData, 0, (int)size));//将byte[]转化为MemoryStream再传递给image }

(4)效果展示

最新回复(0)