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

发布于:2023-01-04 ⋅ 阅读:(249) ⋅ 点赞:(0)

一、主要实现功能

  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. 然后在定义的函数前面加上“DLL_API”即可,记得编译时.exe要修改为.dl,最后将编译成功的dll文件放入c#项目的根目录下
DLL_API void GetMat(char* filename, uchar* data, size_t& size)
  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. 在C# 中导入相应函数
    public partial class Form1 : Form
    {
        [DllImport("C++ToCSharpDll.dll")]
        public extern static void GetMat(string filename, ref byte data, out ulong size);
  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. 运行结果如下
    在这里插入图片描述

三、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. 在C#中导入该函数
        [DllImport("C++ToCSharpDll.dll")]
        public extern static void IntPtrToMat(IntPtr byte1, int width, int height, int stride);
  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);
        }

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
本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到