0
点赞
收藏
分享

微信扫一扫

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存


基本思想:使用c#调用c++的动态包,进行图像帧传入和处理,然后返回结果;这样就可以独立的写c++算法,使用c#进行前端界面和布局开发了 

一、创建C#工程

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_图像处理

 然后简单测试一下工程

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_c++_02

 二、在C#中先把OpenCV调用起来

(1)在C#中打开搜索NuGet(库程序包管理器)

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_图像处理_03

安装最新的OpenCVSharp4和OpenCVSharp4。runtime.win两个包

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_ide_04

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_c#_05

修改一下工程类型,选择X64,若没有在“配置管理器”中,新建一个x64平台即可

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_c++_06

然后测试一下,C#可以正常读取图片和显示图片

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_c#_07

测试图片代码

using System;
using OpenCvSharp;
namespace ConsoleAppDemo
{
class Program
{
static void Main(string[] args)
{

Mat source = new Mat(@"G:\\1.jpg", ImreadModes.Color);
Cv2.Resize(source, source, new OpenCvSharp.Size(480, 480), 0);
Cv2.ImShow("Demo", source);
Console.WriteLine("show image");
Cv2.WaitKey(0);

}
}
}

测试视频

using System;
using OpenCvSharp;
namespace ConsoleAppDemo
{
class Program
{
static void Main(string[] args)
{

VideoCapture cap = new VideoCapture("G:\\1.avi");
VideoWriter writer = new VideoWriter("G:\\save.avi", FourCC.DIVX, 20, new Size(cap.FrameWidth, cap.FrameHeight));

if (!cap.IsOpened())
{
Console.WriteLine("Open video failed!");
return;
}

Mat frame=new Mat();
while(true)
{
cap.Read(frame);
if (frame.Empty() )
break;
writer.Write(frame);
Cv2.ImShow("Demo", frame);
Cv2.WaitKey(1);
}
Console.WriteLine("show image");


}
}
}

三、打包一个c++静态包,对C#传过来的帧进行灰度处理并返回给C#保存

(1) 使用Visual Studio2019 配置opencv工程在这,就不具体叙述了,只贴一下创建工程的属性"空项目",没必要创建动态库类型的工程

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_c++_08

 main.cpp

#include "processImage.h"
int main()
{
cv::Mat img = cv::imread("G:\\1.jpg");
cv::Mat result;
cv::resize(img, img, cv::Size(480, 720));
int ok= bitwiseImage(img,result);
cv::imshow("demo",result);
cv::waitKey(0);
return 0;
}

processImage.h

#include<iostream>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui.hpp>
int bitwiseImage(cv::Mat img, cv::Mat& result);

processImage.cpp

#include "processImage.h"
int bitwiseImage(cv::Mat img, cv::Mat &result)
{
cv::Mat mask(img.rows, img.cols, CV_8UC3, cv::Scalar(255, 255, 255));
cv::bitwise_xor(img, mask, result);
return 0;
}

测试一下, 没问题

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_c++_09

(2) 生成动态库lib文件 ,需要将 "生成-->属性--->配置类型 .exe"修改为.lib类型 ;然后点击左侧的工程名-->重新生成

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_图像处理_10

然后在输出目录R中生成Bitwise.lib文件

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_c++_11

(3) 然后在将"配置类型" 修改回原来的.exe;在"vc++目录"--->库目录---->添加 生成的.lib的目录(上述目录为--输出目录R) 同时链接器中填入Bitwise.lib

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_图像处理_12

 静态库包含

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_图像处理_13

 同时将本地的processImage.cpp代码全部注释掉,调用Bitwise.lib测试一下 

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_c++_14

 调用成功,然后使用C#调用一下 (查询微软手册发现C#是不能调用lib的,所以只能改一下生成dll,方法是一样的,修改配置类型即可,如果现实中遇到第三方的lib 可以写个函数调用第三方的lib,然后在生成dll)

(4)、因为C#调用c++的动态包需要以unsigned char * 的数据格式传入,所以需要提前修改一下数据格式 逐在原基础上重新修改写一个例子

main.cpp

#include "processImage.h"
int main()
{
cv::Mat img = cv::imread("G:\\1.jpg");
cv::resize(img, img, cv::Size(480, 720));
unsigned char* src = img.data;
cv::Mat result = cv::Mat(img.rows, img.cols, CV_8UC3, src);
unsigned char* dest = result.data;
int ok = bitwiseImage(src, dest,img.rows,img.cols);
cv::imshow("demo", result);
cv::waitKey(0);
img.release();
result.release();
return 0;
}

processImage.h

#include<iostream>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui.hpp>
extern "C" _declspec(dllexport) int bitwiseImage(unsigned char* ImageBuffer, unsigned char* ImageResult, int imageWedth, int imageHeight);
//extern "C" _declspec(dllexport) 为了生成动态库之后,函数名字不要发生变化

processImage.cpp

#include "processImage.h"

int bitwiseImage(unsigned char* ImageBuffer, unsigned char* ImageResult, int imageWedth, int imageHeight)
{
cv::Mat result;
cv::Mat img = cv::Mat(imageHeight, imageWedth, CV_8UC3, ImageBuffer);
cv::Mat mask(img.rows, img.cols, CV_8UC3, cv::Scalar(255, 255, 255));
cv::bitwise_xor(img, mask, result);
int length = (int)(result.total() * result.elemSize());
unsigned char* buffer = new unsigned char[length];
memcpy(ImageResult, result.data, length * sizeof(unsigned char));
return 0;
}

重新生成一下demo.dll动态库

四、使用C#调用c++的静态包  【代码中含有mat--->bitmap--->byte 】【byte---->bitmap--->mat】

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using OpenCvSharp;
using System.Runtime.InteropServices;
using System.Drawing;
using OpenCvSharp.Extensions;
using System.IO;
using System.IO.Compression;
using System.Drawing.Imaging;

namespace ConsoleApp1
{
class Program
{
[DllImport(@"C:\Users\Administrator\source\repos\demo\x64\Release\demo.dll")]
public static extern int bitwiseImage(byte[] ImageBuffer, byte[] ImageResult, int imageWedth, int imageHeight);



static void Main(string[] args)
{
VideoCapture cap = new VideoCapture("E:\\test.mp4");
VideoWriter writer = new VideoWriter("E:\\save.avi", FourCC.DIVX, 20, new OpenCvSharp.Size(cap.FrameWidth, cap.FrameHeight));

if (!cap.IsOpened())
{
Console.WriteLine("Open video failed!");
return;
}

Mat frame = new Mat();
while (true)
{
cap.Read(frame);
if (frame.Empty())
break;
Bitmap bmp = frame.ToBitmap();
byte[] source = GetBGRValues(bmp);
byte[] dest = source;
bitwiseImage(source, dest, bmp.Width, bmp.Height);
Bitmap bmpConvert = Byte2Bitmap(dest, bmp.Width, bmp.Height);
Mat mat = OpenCvSharp.Extensions.BitmapConverter.ToMat(bmpConvert);

writer.Write(mat);
Cv2.ImShow("Demo", mat);
Cv2.WaitKey(1);
}
Console.WriteLine("show image");


}
public static byte[] GetBGRValues(Bitmap bmp)
{
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
var bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
var rowBytes = bmpData.Width * Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
var imgBytes = bmp.Height * rowBytes;
byte[] rgbValues = new byte[imgBytes];
IntPtr ptr = bmpData.Scan0;
for (var i = 0; i < bmp.Height; i++)
{
Marshal.Copy(ptr, rgbValues, i * rowBytes, rowBytes);
ptr += bmpData.Stride;
}
bmp.UnlockBits(bmpData);
return rgbValues;
}
public static Bitmap Byte2Bitmap(Byte[] data, int width, int height)
{
Bitmap image = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);

BitmapData bmData = image.LockBits(rect, ImageLockMode.ReadWrite, image.PixelFormat);
IntPtr ptr = bmData.Scan0;

for (int i = 0; i < image.Height; i++)
{
Marshal.Copy(data, i * image.Width * 3, ptr, image.Width * 3);
ptr = (IntPtr)(ptr.ToInt64() + bmData.Stride);
}

image.UnlockBits(bmData);

return image;
}
}
}

结果图

58、Visual studio 2019+C#传递Mat数据给C++动态包处理,并将处理结果Mat返回给C#显示、保存_ide_15

举报

相关推荐

0 条评论