• Day 10 - C# 与 C++ opencv图像数据转换


    一、主要实现功能

    1. 通过C#传入路径,然后通过c++ opencv进行读取,并在C# winform窗口显示图像
    2. C# 图像数据传入C++,转换成opencv 可以处理的形式

    二、通过C#传入路径,然后通过c++ opencv进行读取,并在C# winform窗口显示图像

    1. c++ 的代码要编译成c#可调用的形式,需要在相应的.h文件中加入以下语句:
    #pragma once
    #define DLL_API extern "C" _declspec(dllexport)
    
    • 1
    • 2
    1. 然后在定义的函数前面加上“DLL_API”即可,记得编译时.exe要修改为.dl,最后将编译成功的dll文件放入c#项目的根目录下
    DLL_API void GetMat(char* filename, uchar* data, size_t& size)
    
    • 1
    1. 先定义一个GetMat函数,可以通过文件路径读取图像,先通过opencv进行读取,然后转换成C#可以接受的形式
    DLL_API void GetMat(char* filename, uchar* data, size_t& size)
    {
        std::vector<uchar> buffer;
        cv::Mat img = cv::imread(filename);
        cv::Mat imggray;
        cv::cvtColor(img, imggray, cv::COLOR_RGB2GRAY);
        cv::imencode(".bmp", imggray, buffer);
        size = buffer.size();
        for (uchar& var : buffer)
        {
            *data = var;
            data++;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    1. 在C# 中导入相应函数
        public partial class Form1 : Form
        {
            [DllImport("C++ToCSharpDll.dll")]
            public extern static void GetMat(string filename, ref byte data, out ulong size);
    
    • 1
    • 2
    • 3
    • 4
    1. 然后再winform的某个按钮事件中写入以下内容
            private void button2_Click(object sender, EventArgs e)
            {
                string filename = "4.jpg";//文件路径
                byte[] ptrData = new byte[1920 * 1080 * 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再传递给imag
    
                pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 运行结果如下
      在这里插入图片描述

    三、C# 图像数据传入C++,转换成opencv 可以处理的形式

    1. 首先在c++ 中定义一个函数
    DLL_API void IntPtrToMat(unsigned char* data, int height, int width, int stride)
    {
        cv::Mat img;
        if (stride / width == 3) img = cv::Mat(height, width, CV_8UC3, data, 0);  
        if (stride / width == 1) img = cv::Mat(height, width, CV_8UC1, data, 0);   
        if (stride / width == 4) img = cv::Mat(height, width, CV_8UC4, data, 0);   
        
        cv::imshow("image", img);
        cv::waitKey(0);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. 在C#中导入该函数
            [DllImport("C++ToCSharpDll.dll")]
            public extern static void IntPtrToMat(IntPtr byte1, int width, int height, int stride);
    
    • 1
    • 2
    1. 在winform的一个按钮事件中添加如下内容
            private void button3_Click(object sender, EventArgs e)
            {
                //这里面的内容要及其注意,计算不对的话会造成异常
                Bitmap bmp = (Bitmap)Bitmap.FromFile("4.jpg");
                BitmapData bmpdata = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
                int length = bmp.Width * bmp.Height * (bmpdata.Stride / bmp.Width);
                byte[] buffer = new byte[length];
                IntPtr ptr = bmpdata.Scan0;
                Marshal.Copy(ptr, buffer, 0, length);
                IntPtrToMat(ptr, bmp.Height, bmp.Width, bmpdata.Stride);
                bmp.UnlockBits(bmpdata);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5.运行结果
    在这里插入图片描述

    参考文章

    1. https://blog.csdn.net/qq_24003917/article/details/107425216
    2. https://blog.csdn.net/a19990412/article/details/78164243
    3. https://blog.csdn.net/mengsuifengc/article/details/109228725
    4. https://blog.csdn.net/zhizhengguan/article/details/106013828
    5. https://blog.csdn.net/zhoumoon/article/details/112681354
    6. https://blog.csdn.net/rome12/article/details/90025439
  • 相关阅读:
    Golang指针隐式间接引用
    [LeetCode] 128. 最长连续序列
    国内代码托管中心-码云(九)——Git
    Vue | Vue.js Composition API(二)
    软件过程与管理学习之(1)Project management Methodologies & Standards(项目管理方法和标准)
    获取文件最后修改时间
    【算法专题突破】双指针 - 和为s的两个数字(6)
    centos 7.7之后,无法远程ssh执行 java -jar 指令
    《React.js 中高质量应用程序的最佳实践和设计模式》(译文)
    离散数学_第8章 图__平面图
  • 原文地址:https://blog.csdn.net/ruotianxia/article/details/126574615