**
C# OpenCvSharp与Opencv4.x(DLL)混合开发
**
**
这里只能解决宽度为4的倍数图片,不是4的倍数会出现图片扭曲,网上找了很多都不能解决,一般工业相机都是4的倍数,不是也可以自定义调节
第一部分:开发环境
**
1.Win10 X64
2.vs2019
3.Opencv4.5.2
4.OpenCvSharp4.0
**
第二部分:c++ Opencv4.5.2 动态库
**
#include<opencv2/opencv.hpp>
using namespace cv;
extern "C" _declspec(dllexport) uchar * ReadImage(char*, int&, int&, int&);
extern "C" _declspec(dllexport) uchar * ShowImage(uchar*, int&, int&, int&);
extern "C" _declspec(dllexport) void ReleaseUChar(uchar*);
uchar* ReadImage(char* ImagePath, int& Width, int& Height, int& Channels)
{
Mat src = imread(ImagePath);
if (src.empty()) return NULL;
Width = src.size().width;
Height = src.size().height;
Channels = src.channels();
size_t memsize = (long long)Width * (long long)Height * (long long)Channels;
//不能直接返回src.data
//重新申请内存,然后将src.data拷贝到申请的内存空间再返回
//由于不能在这里释放内存,所以加一个释放内存函数ReleaseUChar,C#使用完再调用释放函数
uchar* data = new uchar[memsize];//ReleaseUChar释放内存
memcpy(data, src.data, memsize);//拷贝
return data;
}
uchar* ShowImage(uchar* ImageData, int& Width, int& Height, int& Channels)
{
Mat src;
switch (Channels)
{
case 1:
src = Mat(Height, Width, CV_8UC1, ImageData);
break;
case 3:
src = Mat(Height, Width, CV_8UC3, ImageData);
break;
default:
return NULL;
}
Mat dst;
cvtColor(src, dst, COLOR_BGR2GRAY);
if (dst.empty()) return NULL;
Width = dst.size().width;
Height = dst.size().height;
Channels = dst.channels();
size_t memsize = (long long)Width * (long long)Height * (long long)Channels;
uchar* data = new uchar[memsize];//ReleaseUChar释放内存
memcpy(data, src.data, memsize);//拷贝
return data;
}
void ReleaseUChar(uchar* p)
{
delete[] p;//释放
}
**
第二部分:c# OpenCvSharp4.0 开发
**
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using OpenCvSharp;
using OpenCvSharp.Extensions;
[DllImport("xxx.dll")]
private extern static IntPtr ReadImage(string ImagePath, ref int Width, ref int Height, ref int Channels);
[DllImport("xxx.dll")]
private extern static IntPtr ShowImage(byte[] ImgData, ref int Width, ref int Height, ref int Channels);
//ReadImage ShowImage函数的返回都要使用ReleaseUChar释放
[DllImport("xxx.dll")]
private extern static void ReleaseUChar(IntPtr p);
//加载图片 C++ Mat数据传递给C#
void FunctionReadImage()
{
IntPtr ImgData = IntPtr.Zero;
int Width = 0, Height = 0, Channels = 0;
ImgData = ReadImage("宽度为4的倍数.jpg", ref Width, ref Height, ref Channels);
if (ImgData == IntPtr.Zero) return;
//Channels表示通道数 如果为1 MatType.CV_8UC1
using (Mat src = new Mat(Height, Width, MatType.CV_8UC3, ImgData))
{
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Image = null;
pictureBox1.Image = BitmapConverter.ToBitmap(src);
}
ReleaseUChar(ImgData);//释放内存
}
//将图片转灰度图 主要体现C++ Mat与c# Mat互调
void FunctionShowImage()
{
using (Mat img = new Mat("宽度为4的倍数.jpg"))
{
using (Bitmap bmp = BitmapConverter.ToBitmap(img))
{
int Width = bmp.Width, Height = bmp.Height;
BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
IntPtr ptr = bmpdata.Scan0;
int Channels = bmpdata.Stride / Width;
int bytes = Width * Height * Channels;
byte[] rgbvalues = new byte[bytes];
Marshal.Copy(ptr, rgbvalues, 0, bytes);
IntPtr ImgData = IntPtr.Zero;
ImgData = ShowImage(rgbvalues, ref Width, ref Height, ref Channels);
if (ImgData == IntPtr.Zero) return;
//Channels表示通道数 如果为1 MatType.CV_8UC1
using (Mat src = new Mat(Height, Width, MatType.CV_8UC1, ImgData))
{
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.Image = null;
pictureBox1.Image = BitmapConverter.ToBitmap(src);
}
ReleaseUChar(ImgData);//释放内存
}
}
}