C#呼叫 opencv cv::Mat 影象, 採用折中方法
阿新 • • 發佈:2018-12-30
C# 用於介面的製作要比MFC高效許多,但是有時候為了效率需要用C++程式,這樣就涉及到了把C++核心演算法程式做成dll,在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 的中的資料啦!!!
有什麼不明白的可以留言!!!!