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

【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)效果展示

  • 10
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在C#调用C++编写的OpenCV dll,可以使用Platform Invoke(P/Invoke)技术。下面是一个简单的示例,演示如何在C#调用C++编写的OpenCV dll: 1. 创建一个新的C#控制台应用程序。 2. 在项目文件夹中创建一个名为“opencv”的子文件夹。 3. 将OpenCV dll文件复制到该子文件夹中。 4. 在Visual Studio中打开项目,并添加以下代码: ```C# using System; using System.Runtime.InteropServices; class Program { [DllImport("opencv\\opencv_core320.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr cvCreateImage( [MarshalAs(UnmanagedType.Struct)] CvSize size, int depth, int channels); static void Main(string[] args) { // 创建一个256x256的8位单通道图像 var size = new CvSize(256, 256); var image = cvCreateImage(size, 8, 1); // 在控制台中输出图像信息 Console.WriteLine("Image created: {0}x{1}, depth={2}, channels={3}", size.Width, size.Height, 8, 1); Console.ReadKey(); } } [StructLayout(LayoutKind.Sequential)] public struct CvSize { public int Width; public int Height; public CvSize(int width, int height) { Width = width; Height = height; } } ``` 上面的代码创建了一个256x256的8位单通道图像,并在控制台中输出了图像信息。 在上面的代码中,我们使用DllImport属性来指定要导入的OpenCV dll的名称和调用约定。在本例中,我们使用Cdecl调用约定。 我们还定义了一个结构体CvSize,用于传递图像大小参数。在C++中,CvSize结构体定义在opencv_core.hpp头文件中。我们在C#中重新定义了这个结构体,以便我们可以在C#中使用它来传递参数。 需要注意的是,由于C++C#使用不同的内存管理机制,因此您需要确保在C#中正确处理从C++返回的指针。在本例中,我们使用IntPtr类型来表示从C++返回的指针,并使用Marshal类中的相关方法来管理它们。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值