天天看点

C#调用 opencv cv::Mat 图像, 采用折中方法

C# 用于界面的制作要比MFC高效许多,但是有时候为了效率需要用C++程序,这样就涉及到了把C++核心算法程序做成dll,在C#中进行调用。

之前有将IplImage*  这类结构用于C#调用,  整体结构较为复杂,现在我将更方便有效的方法介绍给大家,如果有更好的方法可以分享给我。

将C++ IplImage 图像用C#读取,     将C++ IplImage 图像用C#读取(二)

实现机制:

当然这里需要注意一个问题,就是转换的本质都是采用IplImage*    但是之前处理可以采用cv::Mat  进行各种处理

后面需要用到  IplImage* dst = &IplImage(src); (浅拷贝)   需要通过深拷贝 得到dst1  (代码如下 :  cvCopy(dst,dst1);)  再通过后面文中的方式就可以轻松传递数据啦。

Mat  在C++中很好用,不用处理释放的问题,但是再制作dll调用的时候,内存释放就是多么的悲剧。这里的启示:有时候换一种方式处理问题更好。

下面我分别演示 彩色图像  和 灰度图像的读取。

需要添加的头文件等:

#include "stdafx.h"


#define DLL_API extern "C" _declspec(dllexport)     
 
#include <opencv2\opencv.hpp>  
           

彩色图像C++代码:

DLL_API uchar * _stdcall run1(char* filename, int & width, int & height, int & step )  
{  
  
        IplImage* uu = cvLoadImage(filename);  
	IplImage* dst1 = cvCreateImage(cvSize(uu->width,uu->height),8,1);
	cvCvtColor(uu,dst1,CV_RGB2GRAY);
	Mat ss(uu);
	uchar * data = new uchar[uu->width*uu->height*3];

	data= ss.data;
	width = ss.size().width;
	height = ss.size().height;
	step = ss.step;

	return data;
}
           

C#调用代码:

[DllImport("opencv.dll")]
        public static extern IntPtr run1(string a , out int width, out int height, out int step); 
        private void button1_Click(object sender, EventArgs e)
        {
            string filename;
            OpenFileDialog op = new OpenFileDialog();
            if (op.ShowDialog() == DialogResult.OK)
            {
                filename = op.FileName;
                int width, height, step;
                IntPtr dst =  run1(filename,out width,out height, out step);
               Bitmap img = new Bitmap(width, height, step, System.Drawing.Imaging.PixelFormat.Format24bppRgb, dst);
               pictureBox1.Image = img;

            }
        }
           

其中,opencv.dll 为自己制作的C++的dll,pictureBox1 为C#中的控件。

灰度图像C++代码:

DLL_API uchar * _stdcall run1(char* filename, int & width, int & height, int & step )  
{  
  
    IplImage* uu = cvLoadImage(filename);  
	IplImage* dst1 = cvCreateImage(cvSize(uu->width,uu->height),8,1);
	cvCvtColor(uu,dst1,CV_RGB2GRAY);
	Mat ss(dst1);
	uchar * data = new uchar[uu->width*uu->height*3];

	data= ss.data;
	width = ss.size().width;
	height = ss.size().height;
	step = ss.step;
	return data;

}
           

可以看到代码和彩色图像C++代码并没有太大区别, 但是C#中会有区别,代码如下:

[DllImport("raildetection.dll")]
        public static extern IntPtr run1(string a , out int width, out int height, out int step); 
        private void button1_Click(object sender, EventArgs e)
        {
            string filename;
            OpenFileDialog op = new OpenFileDialog();
            if (op.ShowDialog() == DialogResult.OK)
            {
                filename = op.FileName;
                int width, height, step;
                IntPtr dst =  run1(filename,out width,out height, out step);
               Bitmap img = new Bitmap(width, height, step, <strong>System.Drawing.Imaging.PixelFormat.Format8bppIndexed</strong>,dst);               
               <strong>img.Palette = CvToolbox.GrayscalePalette;</strong> 
               pictureBox1.Image = img;

            }
        }
           

注:颜色加粗部分为区别部分

这个CvToolbox的结构体如下:

public static class CvToolbox
    {

       // #region Color Pallette
        /// <summary>
        /// The ColorPalette of Grayscale for Bitmap Format8bppIndexed
        /// </summary>
        public static readonly ColorPalette GrayscalePalette = GenerateGrayscalePalette();

        private static ColorPalette GenerateGrayscalePalette()
        {
            using (Bitmap image = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
            {
                ColorPalette palette = image.Palette;
                for (int i = 0; i < 256; i++)
                {
                    palette.Entries[i] = Color.FromArgb(i, i, i);
                }
                return palette;
            }
        }
    }
           

总结:图像用IplImage 读取很重要,否则会报错。

这样大家就可以顺利读取cv::Mat 的中的数据啦!!!

C#调用 opencv cv::Mat 图像, 采用折中方法

有什么不明白的可以留言!!!!