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

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

一、创建C#工程

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

 然后简单测试一下工程

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

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

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

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

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

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

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

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

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

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

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

测试图片代码

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#显示、保存_第8张图片

 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
#include 
#include 
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#显示、保存_第9张图片

(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#显示、保存_第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#显示、保存_第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
#include 
#include 
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#显示、保存_第15张图片

你可能感兴趣的:(C/C++基础知识,图像处理,c#,c++)