这里有两种方案,第一种方案是采用OpencvCSharp,最后OpencvCSharp.Mat.CvPtr即是Mat **img
接下来可以采用C#调用c++ dll的方法实现交互
第二种方案即将OpencvCSharp 的转换方法提取出来,Mat对应的C#中的就是一个Intptr;
以下是C#的核心Src:
public static Bitmap GetBitmapfromImgptr(IntPtr imgptr)
{
int w = 0;
int h = 0;
int channel = 0;
int type = 0;
IntPtr ptr = GetDataAndInfo(imgptr,ref w,ref h,ref channel, ref type);
int stride = channel * w;
PixelFormat format;
switch (type)
{
case 1:
format = PixelFormat.Format8bppIndexed;
break;
case 3:
format = PixelFormat.Format24bppRgb;
break;
default:
return null;
}
return getBitmapByData(ptr, w, h, stride, format);
}
public static void BitmaptoImgptr(Bitmap bitmap,out IntPtr intPtr)
{
int stride;
byte[] source = GetBGRValues(bitmap, out stride);
int channel = Image.GetPixelFormatSize(bitmap.PixelFormat) / 8;
GetImg(source, bitmap.Width, bitmap.Height, channel,out intPtr);
}
[DllImport("opencvbase.dll", EntryPoint = "GetImg", CharSet = CharSet.Auto)]
public static extern void GetImg(byte[] src, int w, int h, int channel, out IntPtr intPtr);
[DllImport("opencvbase.dll", EntryPoint = "GetDataAndInfo", CharSet = CharSet.Auto)]
public static extern IntPtr GetDataAndInfo(IntPtr imgptr, ref int w, ref int h, ref int channel, ref int type);
public static Bitmap getBitmapByData(IntPtr ptr, int w, int h, int stride, PixelFormat format)
{
int rowBytes = w * Image.GetPixelFormatSize(format) / 8;
byte[] rgbValues = new byte[stride * h];
for (var i = 0; i < h; i++)
{
Marshal.Copy(ptr, rgbValues, i * stride, rowBytes);
ptr += rowBytes; // next row
}
GCHandle hObject = GCHandle.Alloc(rgbValues, GCHandleType.Pinned);
IntPtr ptrnew= hObject.AddrOfPinnedObject();
Bitmap bitmap = new Bitmap(w, h, stride, format, ptrnew);
if (format == PixelFormat.Format8bppIndexed)
{
bitmap.Palette = getGrayPalette();
}
hObject.Free();
return bitmap;
}
public static byte[] GetBGRValues(Bitmap bmp, out int stride)
{
var rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
var bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
stride = bmpData.Stride;
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; // next row
}
bmp.UnlockBits(bmpData);
return rgbValues;
}
C++ Dll 核心Src:
extern "C" DLL_EXPORY void* GetDataAndInfo(void *imgptr,int &w,int &h,int &channel,int &imgtype)
{
Mat *img = (Mat *)imgptr;
w = img->cols;
h = img->rows;
channel = img->channels();
switch (img->type())
{
case CV_8UC1:
imgtype = 1;
break;
case CV_8UC3:
imgtype = 3;
break;
case CV_8UC2:
imgtype = 2;
break;
case CV_8UC4:
imgtype = 4;
break;
}
return img->data;
}
extern "C" DLL_EXPORY void GetImg(unsigned char* src, int w, int h, int channel, cv::Mat **img)
{
int format;
switch (channel)
{
case 1:
format = CV_8UC1;
break;
case 2:
format = CV_8UC2;
break;
case 3:
format = CV_8UC3;
break;
default:
format = CV_8UC4;
break;
}
if (*img !=nullptr)
{
delete *img;
}
*img= new Mat(h, w, format, src);
}
以上只实现的常用CV_8U系的图片转换,对于其他类型,可以查看OpencvCSharp.extensions.BitmapConverter