全网图像转化源码C#版独一,为了弄清不同类型储存结构,我太难了!
一,认识HObject类型,HImage类型,Mat类型,Bitmap类型;(。。。没整理呢)
1. HObject类型
2. HImage类型
3. opencv之Mat数据类型,Mat类的定义,学习OpenCV2——Mat之通道的理解,Mat基本操作以及灰度图转化
data:Mat对象中的一个指针,指向内存中存放矩阵数据的一块内存 (uchar* data)
dims:Mat所代表的矩阵的维度,如 3 * 4 的矩阵为 2 维, 3 * 4 * 5 的为3维
channels:通道,矩阵中的每一个矩阵元素拥有的值的个数,比如说 3 * 4 矩阵中一共 12 个元素,如果每个元素有三个值,那么就说这个矩阵是 3 通道的,即 channels = 3。常见的是一张彩色图片有红、绿、蓝三个通道。
depth:深度,即每一个像素的位数(bits),在opencv的Mat.depth()中得到的是一个 0 – 6 的数字,分别代表不同的位数:enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 可见 0和1都代表8位, 2和3都代表16位,4和5代表32位,6代表64位;
step:是一个数组,定义了矩阵的布局,具体见下面图片分析,另外注意 step1 (step / elemSize1),M.step[m-1] 总是等于 elemSize,M.step1(m-1)总是等于 channels;
elemSize : 矩阵中每一个元素的数据大小,如果Mat中的数据的数据类型是 CV_8U 那么 elemSize = 1,CV_8UC3 那么 elemSize = 3,CV_16UC2 那么 elemSize = 4;记住另外有个 elemSize1 表示的是矩阵中数据类型的大小,即 elemSize / channels 的大小
4. Bitmap类型
二,不一定要转化(直接读文件的情况) 很简单,有点乱,整理出来再传
三,转化方法(避免 “存” “读”文件)
1.HObject<=>Bitmap(还未验证,会验证的)
(1)把Halcon的“HObject图像”转换到Bitmap图像

1 /// <summary> 2 /// 把halcon图像转换到bitmap图像 3 /// </summary> 4 /// <param name="image">HObject对象</param> 5 /// <param name="res">Bitmap对象</param> 6 private Bitmap HObjectToBitmap(HObject hImage) 7 { 8 HTuple hpoint, type, width, height; 9 Bitmap res; 10 const int Alpha = 255; 11 HOperatorSet.GetImagePointer1(hImage, out hpoint, out type, out width, out height); 12 13 14 res = new Bitmap(width, height, PixelFormat.Format8bppIndexed); 15 ColorPalette pal = res.Palette; 16 for (int i = 0; i <= 255; i++) 17 { 18 string insds = Color.FromArgb(Alpha, i, i, i).ToString(); 19 } 20 res.Palette = pal; 21 Rectangle rect = new Rectangle(0, 0, width, height); 22 BitmapData bitmapData = res.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 23 int PixelSize = Bitmap.GetPixelFormatSize(bitmapData.PixelFormat) / 8; 24 25 if (width % 4 == 0)//4的倍数的时候,直接复制 26 CopyMemory(bitmapData.Scan0, hpoint, width * height * PixelSize); 27 else//根据高循环 28 { 29 for (int i = 0; i < height - 1; i++) 30 { 31 CopyMemory(bitmapData.Scan0, hpoint, width * PixelSize); 32 hpoint.I += width; 33 bitmapData.Scan0 += bitmapData.Stride; 34 } 35 } 36 res.UnlockBits(bitmapData); 37 return res; 38 }
(2)把Bitmap图像转换到Halcon的“HObject图像”

1 /// <summary> 2 /// 把bitmap图像转换到halcon图像 3 /// </summary> 4 /// <param name="bmp"></param> 5 /// <returns></returns> 6 public HObject BitmapToHObject(Bitmap bmp) 7 { 8 try 9 { 10 11 Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 12 13 System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 14 IntPtr pointer = bmpData.Scan0; 15 16 byte[] dataBlue = new byte[bmp.Width * bmp.Height]; 17 unsafe 18 { 19 fixed (byte* ptrdata = dataBlue) 20 { 21 for (int i = 0; i < bmp.Height; i++) 22 { 23 CopyMemory((IntPtr)(ptrdata + bmp.Width * i), pointer + bmpData.Stride * i, bmp.Width); 24 } 25 HObject ho; 26 HOperatorSet.GenImage1(out ho, "byte", bmp.Width, bmp.Height, (int)ptrdata); 27 HImage himg = new HImage("byte", bmp.Width, bmp.Height, (IntPtr)ptrdata); 28 29 //HOperatorSet.DispImage(ho, hWindowControl1.HalconWindow); 30 31 bmp.UnlockBits(bmpData); 32 return ho; 33 } 34 } 35 } 36 catch (Exception exc) 37 { 38 return null; 39 } 40 41 }
2.Mat<=>Bitmap(还未写,会写的)
(1)把OpenCV的“Mat图像”转换到Bitmap图像
(2)把Bitmap图像转换到OpenCV的“Mat图像”
3.HObject<=>Mat
(1)把Halcon的“HObject图像”转换到OpenCV的“Mat图像”

1 /// <summary> 2 /// 把Halcon图像转换到OpenCV图像 3 /// </summary> 4 /// <param name="hImage">Halcon图像_HObject</param> 5 /// <returns>OpenCV图像_Mat</returns> 6 public Mat HImageToMat(HObject hImage) 7 { 8 try 9 { 10 Mat mImage; // 返回值 11 HTuple htChannels; // 通道 12 HTuple cType = null; // 类型 13 HTuple width, height; // 宽,高 14 width = height = 0; 15 16 htChannels = null; 17 HOperatorSet.CountChannels(hImage, out htChannels); // 获取通道 18 19 // 通道存在值 20 if (htChannels.Length == 0) 21 { 22 return null; 23 } 24 if (htChannels[0].I == 1) // 单通道 25 { 26 HTuple ptr; // HTuple_单通道值指针 27 HOperatorSet.GetImagePointer1(hImage, out ptr, out cType, out width, out height); // 单通道取值方法(图片,输出“单通道值指针”,输出“类型”,输出“宽”,输出“高”) // (ptr=2157902018096 cType=byte width=830 height=822) 28 mImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, new Scalar(0)); // 实例化mImage(大小,MatType.CV_8UC1,new Scalar(0)) 29 int Width = width; 30 31 unsafe 32 { 33 //for (int i = 0; i < height; i++) // 循环赋值 34 //{ 35 // IntPtr start = IntPtr.Add(mImage.Data, i * width); // Mat的单通道_Data地址+偏移(start=0x000001f66d4df300 Data=0x000001f66d4df300 i * 830) 36 // CopyMemory(start, new IntPtr((byte*)ptr.IP + width * i), width); // CopyMemory(要复制到的地址,复制源的地址,复制的长度) 37 //} 38 CopyMemory(mImage.Data, new IntPtr((byte*)ptr.IP), width*height);// CopyMemory(要复制到的地址,复制源的地址,复制的长度) 39 } 40 return mImage; 41 } 42 else if (htChannels[0].I == 3) // 三通道 43 { 44 HTuple ptrRed; // HTuple_R通道值指针 45 HTuple ptrGreen; // HTuple_G通道值指针 46 HTuple ptrBlue; // HTuple_B通道值指针 47 48 HOperatorSet.GetImagePointer3(hImage, out ptrRed, out ptrGreen, out ptrBlue, out cType, out width, out height); // 三通道取值方法(图片,输出“R通道值指针”,输出“G通道值指针”,输出“B通道值指针”,输出“类型”,输出“宽”,输出“高”) 49 Mat pImageRed = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); // Mat_R通道值指针(大小,MatType.CV_8UC1) 50 Mat pImageGreen = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); // Mat_G通道值指针(大小,MatType.CV_8UC1) 51 Mat pImageBlue = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); // Mat_B通道值指针(大小,MatType.CV_8UC1) 52 mImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC3, new Scalar(0, 0, 0)); // Mat_图片(大小,MatType.CV_8UC1,new Scalar(0, 0, 0)) 53 unsafe 54 { 55 //for (int i = 0; i < height; i++) 56 //{ 57 // //long step = mImage.Step(); 58 // IntPtr startRed = IntPtr.Add(pImageRed.Data, i * width); // Mat的Red_Data地址+偏移(start=0x000001f66d4df300 Data=0x000001f66d4df300 i * 830) 59 // IntPtr startGreen = IntPtr.Add(pImageGreen.Data, i * width); // Mat的Green_Data地址+偏移(start=0x000001f66d4df300 Data=0x000001f66d4df300 i * 830) 60 // IntPtr startBlue = IntPtr.Add(pImageBlue.Data, i * width); // Mat的Blue_Data地址+偏移(start=0x000001f66d4df300 Data=0x000001f66d4df300 i * 830) 61 // CopyMemory(startRed, new IntPtr((byte*)ptrRed.IP + width * i), width); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Red 62 // CopyMemory(startGreen, new IntPtr((byte*)ptrGreen.IP + width * i), width); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Green 63 // CopyMemory(startBlue, new IntPtr((byte*)ptrBlue.IP + width * i), width); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Blue 64 //} 65 CopyMemory(pImageRed.Data, new IntPtr((byte*)ptrRed.IP), width*height); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Red 66 CopyMemory(pImageGreen.Data, new IntPtr((byte*)ptrGreen.IP), width * height); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Green 67 CopyMemory(pImageBlue.Data, new IntPtr((byte*)ptrBlue.IP), width * height); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Blue 68 } 69 Mat[] multi = new Mat[] { pImageBlue, pImageGreen, pImageRed }; // 存储rgb三通道 70 Cv2.Merge(multi, mImage); // rgb三通道合成一张图 71 pImageRed.Dispose(); // Mat_R通道值指针销毁 72 pImageGreen.Dispose(); // Mat_G通道值指针销毁 73 pImageBlue.Dispose(); // Mat_B通道值指针销毁 74 return mImage; 75 } 76 else 77 { 78 return null; 79 } 80 } 81 catch (Exception ex) 82 { 83 throw ex; 84 } 85 }
(2)把OpenCV的”Mat图像“转换到Halcon的“HObject图像”

1 /// <summary> 2 /// 把OpenCV图像转换到Halcon图像 3 /// </summary> 4 /// <param name="mImage">OpenCV图像_Mat</param> 5 /// <returns>Halcon图像_HObject</returns> 6 public HObject MatToHImage(Mat mImage) 7 { 8 try 9 { 10 HObject hImage; 11 int matChannels = 0; // 通道数 12 Type matType = null; 13 int width, height; // 宽,高 14 width = height = 0; // 宽,高初始化 15 16 // 获取通道数 17 matChannels = mImage.Channels(); 18 if (matChannels == 0) 19 { 20 return null; 21 } 22 if (matChannels == 1) // 单通道 23 { 24 IntPtr ptr; // 灰度图通道 25 Mat[] mats = mImage.Split(); 26 27 // 改自:Mat.GetImagePointer1(mImage, out ptr, out matType, out width, out height); // ptr=2157902018096 cType=byte width=830 height=822 28 ptr = mats[0].Data; // 取灰度图值 29 matType = mImage.GetType(); // byte 30 height = mImage.Rows; // 高 31 width = mImage.Cols; // 宽 32 33 // 改自:hImage = new HObject(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, new Scalar(0)); 34 byte[] dataGrayScaleImage = new byte[width * height]; //Mat dataGrayScaleImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); 35 36 unsafe 37 { 38 fixed (byte* ptrdata = dataGrayScaleImage) 39 { 40 #region 按行复制 41 //for (int i = 0; i < height; i++) 42 //{ 43 // CopyMemory((IntPtr)(ptrdata + width * i), new IntPtr((long)ptr + width * i), width); 44 //} 45 #endregion 46 47 CopyMemory((IntPtr)ptrdata, new IntPtr((long)ptr), width * height); 48 HOperatorSet.GenImage1(out hImage, "byte", width, height, (IntPtr)ptrdata); 49 50 } 51 } 52 return hImage; 53 } 54 else if (matChannels == 3) // 三通道 55 { 56 IntPtr ptrRed; // R通道图 57 IntPtr ptrGreen; // G通道图 58 IntPtr ptrBlue; // B通道图 59 Mat[] mats =mImage.Split(); 60 61 ptrRed = mats[0].Data; // 取R通道值 62 ptrGreen = mats[1].Data; // 取G通道值 63 ptrBlue = mats[2].Data; // 取B通道值 64 matType = mImage.GetType(); // 类型 65 height = mImage.Rows; // 高 66 width = mImage.Cols; // 宽 67 68 // 改自:hImage = new HObject(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, new Scalar(0)); 69 byte[] dataRed = new byte[width * height]; //Mat dataGrayScaleImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); 70 byte[] dataGreen = new byte[width * height]; 71 byte[] dataBlue = new byte[width * height]; 72 73 unsafe 74 { 75 fixed (byte* ptrdataRed = dataRed , ptrdataGreen = dataGreen, ptrdataBlue = dataBlue) 76 { 77 #region 按行复制 78 //HImage himg = new HImage("byte", width, height, (IntPtr)ptrdataRed); 79 //for (int i = 0; i < height; i++) 80 //{ 81 // CopyMemory((IntPtr)(ptrdataRed + width * i), new IntPtr((long)ptrRed + width * i), width); 82 // CopyMemory((IntPtr)(ptrdataGreen + width * i), new IntPtr((long)ptrGreen + width * i), width); 83 // CopyMemory((IntPtr)(ptrdataBlue + width * i), new IntPtr((long)ptrBlue + width * i), width); 84 //} 85 #endregion 86 87 CopyMemory((IntPtr)ptrdataRed , new IntPtr((long)ptrRed ), width* height); // 复制R通道 88 CopyMemory((IntPtr)ptrdataGreen , new IntPtr((long)ptrGreen ), width* height); // 复制G通道 89 CopyMemory((IntPtr)ptrdataBlue , new IntPtr((long)ptrBlue ), width* height); // 复制B通道 90 HOperatorSet.GenImage3(out hImage, "byte", width, height, (IntPtr)ptrdataRed, (IntPtr)ptrdataGreen, (IntPtr)ptrdataBlue); // 合成 91 } 92 } 93 return hImage; 94 } 95 else 96 { 97 return null; 98 } 99 } 100 catch (Exception ex) 101 { 102 throw ex; 103 } 104 105 }
4.HObject=>HImage(灰度/彩色)
(1)灰度图像 HObject -> HImage

1 /// <summary> 2 /// 灰度图像 HObject -> HImage 3 /// </summary> 4 public HImage HObjectToHImage1(HObject hObj) 5 { 6 HImage image = new HImage(); 7 HTuple type, width, height, pointer; 8 HOperatorSet.GetImagePointer1(hObj, out pointer, out type, out width, out height); 9 image.GenImage1(type, width, height, pointer); 10 return image; 11 }
(2)彩色图像 HObject -> HImage

1 /// <summary> 2 /// 彩色图像 HObject -> HImage 3 /// </summary> 4 public HImage HObjectToHImage3(HObject hObj) 5 { 6 HImage image = new HImage(); 7 HTuple type, width, height, pointerRed, pointerGreen, pointerBlue; 8 HOperatorSet.GetImagePointer3(hObj, out pointerRed, out pointerGreen, out pointerBlue, 9 out type, out width, out height); 10 image.GenImage3(type, width, height, pointerRed, pointerGreen, pointerBlue); 11 return image; 12 }
5.灰度图HObject->彩图HObject

1 /// <summary> 2 /// 灰度图像 HObject -> 三通道HObject 3 /// </summary> 4 public HObject HObject1ToHObject3(HObject hObj) 5 { 6 HObject image = new HObject(); 7 HTuple type, width, height, pointer; 8 HOperatorSet.GetImagePointer1(hObj, out pointer, out type, out width, out height); 9 HOperatorSet.GenImage3(out image, "byte", width, height, (IntPtr)pointer, (IntPtr)pointer, (IntPtr)pointer); // 合成 10 return image; 11 }
5.附录_全部代码:
(1)用到的NuGet包:OpenCvSharp3-AnyCPU 4.0.0.20181129
(2)全部代码:

1 using System.Runtime.InteropServices; 2 using System.Drawing.Imaging; 3 using HalconDotNet; 4 using System.Drawing; 5 using OpenCvSharp; 6 using System; 7 8 namespace Bll.SaveImage 9 { 10 public class HObjectBitmap 11 { 12 /// <summary> 13 /// 把source指针长度为size的数据复制到指针dest 14 /// </summary> 15 /// <param name="dest">要复制到的地址</param> 16 /// <param name="source">复制源的地址</param> 17 /// <param name="size">复制的长度</param> 18 /// <returns></returns> 19 [DllImport("kernel32.dll")] 20 public extern static long CopyMemory(IntPtr dest, IntPtr source, int size); 21 22 /// <summary> 23 /// 把halcon图像转换到bitmap图像 24 /// </summary> 25 /// <param name="image">HObject对象</param> 26 /// <param name="res">Bitmap对象</param> 27 private Bitmap HObjectToBitmap(HObject hImage) 28 { 29 HTuple hpoint, type, width, height; 30 Bitmap res; 31 const int Alpha = 255; 32 HOperatorSet.GetImagePointer1(hImage, out hpoint, out type, out width, out height); 33 34 35 res = new Bitmap(width, height, PixelFormat.Format8bppIndexed); 36 ColorPalette pal = res.Palette; 37 for (int i = 0; i <= 255; i++) 38 { 39 string insds = Color.FromArgb(Alpha, i, i, i).ToString(); 40 } 41 res.Palette = pal; 42 Rectangle rect = new Rectangle(0, 0, width, height); 43 BitmapData bitmapData = res.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed); 44 int PixelSize = Bitmap.GetPixelFormatSize(bitmapData.PixelFormat) / 8; 45 46 if (width % 4 == 0)//4的倍数的时候,直接复制 47 CopyMemory(bitmapData.Scan0, hpoint, width * height * PixelSize); 48 else//根据高循环 49 { 50 for (int i = 0; i < height - 1; i++) 51 { 52 CopyMemory(bitmapData.Scan0, hpoint, width * PixelSize); 53 hpoint.I += width; 54 bitmapData.Scan0 += bitmapData.Stride; 55 } 56 } 57 res.UnlockBits(bitmapData); 58 return res; 59 } 60 61 /// <summary> 62 /// 把bitmap图像转换到halcon图像 63 /// </summary> 64 /// <param name="bmp"></param> 65 /// <returns></returns> 66 public HObject BitmapToHObject(Bitmap bmp) 67 { 68 try 69 { 70 71 Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); 72 73 System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed); 74 IntPtr pointer = bmpData.Scan0; 75 76 byte[] dataBlue = new byte[bmp.Width * bmp.Height]; 77 unsafe 78 { 79 fixed (byte* ptrdata = dataBlue) 80 { 81 for (int i = 0; i < bmp.Height; i++) 82 { 83 CopyMemory((IntPtr)(ptrdata + bmp.Width * i), pointer + bmpData.Stride * i, bmp.Width); 84 } 85 HObject ho; 86 HOperatorSet.GenImage1(out ho, "byte", bmp.Width, bmp.Height, (int)ptrdata); 87 HImage himg = new HImage("byte", bmp.Width, bmp.Height, (IntPtr)ptrdata); 88 89 //HOperatorSet.DispImage(ho, hWindowControl1.HalconWindow); 90 91 bmp.UnlockBits(bmpData); 92 return ho; 93 } 94 } 95 } 96 catch (Exception exc) 97 { 98 return null; 99 } 100 101 } 102 103 /// <summary> 104 /// 把Halcon图像转换到OpenCV图像 105 /// </summary> 106 /// <param name="hImage">Halcon图像_HObject</param> 107 /// <returns>OpenCV图像_Mat</returns> 108 public Mat HImageToMat(HObject hImage) 109 { 110 try 111 { 112 Mat mImage; // 返回值 113 HTuple htChannels; // 通道 114 HTuple cType = null; // 类型 115 HTuple width, height; // 宽,高 116 width = height = 0; 117 118 htChannels = null; 119 HOperatorSet.CountChannels(hImage, out htChannels); // 获取通道 120 121 // 通道存在值 122 if (htChannels.Length == 0) 123 { 124 return null; 125 } 126 if (htChannels[0].I == 1) // 单通道 127 { 128 HTuple ptr; // HTuple_单通道值指针 129 HOperatorSet.GetImagePointer1(hImage, out ptr, out cType, out width, out height); // 单通道取值方法(图片,输出“单通道值指针”,输出“类型”,输出“宽”,输出“高”) // (ptr=2157902018096 cType=byte width=830 height=822) 130 mImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, new Scalar(0)); // 实例化mImage(大小,MatType.CV_8UC1,new Scalar(0)) 131 int Width = width; 132 133 unsafe 134 { 135 //for (int i = 0; i < height; i++) // 循环赋值 136 //{ 137 // IntPtr start = IntPtr.Add(mImage.Data, i * width); // Mat的单通道_Data地址+偏移(start=0x000001f66d4df300 Data=0x000001f66d4df300 i * 830) 138 // CopyMemory(start, new IntPtr((byte*)ptr.IP + width * i), width); // CopyMemory(要复制到的地址,复制源的地址,复制的长度) 139 //} 140 CopyMemory(mImage.Data, new IntPtr((byte*)ptr.IP), width*height);// CopyMemory(要复制到的地址,复制源的地址,复制的长度) 141 } 142 return mImage; 143 } 144 else if (htChannels[0].I == 3) // 三通道 145 { 146 HTuple ptrRed; // HTuple_R通道值指针 147 HTuple ptrGreen; // HTuple_G通道值指针 148 HTuple ptrBlue; // HTuple_B通道值指针 149 150 HOperatorSet.GetImagePointer3(hImage, out ptrRed, out ptrGreen, out ptrBlue, out cType, out width, out height); // 三通道取值方法(图片,输出“R通道值指针”,输出“G通道值指针”,输出“B通道值指针”,输出“类型”,输出“宽”,输出“高”) 151 Mat pImageRed = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); // Mat_R通道值指针(大小,MatType.CV_8UC1) 152 Mat pImageGreen = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); // Mat_G通道值指针(大小,MatType.CV_8UC1) 153 Mat pImageBlue = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); // Mat_B通道值指针(大小,MatType.CV_8UC1) 154 mImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC3, new Scalar(0, 0, 0)); // Mat_图片(大小,MatType.CV_8UC1,new Scalar(0, 0, 0)) 155 unsafe 156 { 157 //for (int i = 0; i < height; i++) 158 //{ 159 // //long step = mImage.Step(); 160 // IntPtr startRed = IntPtr.Add(pImageRed.Data, i * width); // Mat的Red_Data地址+偏移(start=0x000001f66d4df300 Data=0x000001f66d4df300 i * 830) 161 // IntPtr startGreen = IntPtr.Add(pImageGreen.Data, i * width); // Mat的Green_Data地址+偏移(start=0x000001f66d4df300 Data=0x000001f66d4df300 i * 830) 162 // IntPtr startBlue = IntPtr.Add(pImageBlue.Data, i * width); // Mat的Blue_Data地址+偏移(start=0x000001f66d4df300 Data=0x000001f66d4df300 i * 830) 163 // CopyMemory(startRed, new IntPtr((byte*)ptrRed.IP + width * i), width); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Red 164 // CopyMemory(startGreen, new IntPtr((byte*)ptrGreen.IP + width * i), width); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Green 165 // CopyMemory(startBlue, new IntPtr((byte*)ptrBlue.IP + width * i), width); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Blue 166 //} 167 CopyMemory(pImageRed.Data, new IntPtr((byte*)ptrRed.IP), width*height); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Red 168 CopyMemory(pImageGreen.Data, new IntPtr((byte*)ptrGreen.IP), width * height); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Green 169 CopyMemory(pImageBlue.Data, new IntPtr((byte*)ptrBlue.IP), width * height); // CopyMemory(要复制到的地址,复制源的地址,复制的长度)_Blue 170 } 171 Mat[] multi = new Mat[] { pImageBlue, pImageGreen, pImageRed }; // 存储rgb三通道 172 Cv2.Merge(multi, mImage); // rgb三通道合成一张图 173 pImageRed.Dispose(); // Mat_R通道值指针销毁 174 pImageGreen.Dispose(); // Mat_G通道值指针销毁 175 pImageBlue.Dispose(); // Mat_B通道值指针销毁 176 return mImage; 177 } 178 else 179 { 180 return null; 181 } 182 } 183 catch (Exception ex) 184 { 185 throw ex; 186 } 187 } 188 189 /// <summary> 190 /// 把OpenCV图像转换到Halcon图像 191 /// </summary> 192 /// <param name="mImage">OpenCV图像_Mat</param> 193 /// <returns>Halcon图像_HObject</returns> 194 public HObject MatToHImage(Mat mImage) 195 { 196 try 197 { 198 HObject hImage; 199 int matChannels = 0; // 通道数 200 Type matType = null; 201 int width, height; // 宽,高 202 width = height = 0; // 宽,高初始化 203 204 // 获取通道数 205 matChannels = mImage.Channels(); 206 if (matChannels == 0) 207 { 208 return null; 209 } 210 if (matChannels == 1) // 单通道 211 { 212 IntPtr ptr; // 灰度图通道 213 Mat[] mats = mImage.Split(); 214 215 // 改自:Mat.GetImagePointer1(mImage, out ptr, out matType, out width, out height); // ptr=2157902018096 cType=byte width=830 height=822 216 ptr = mats[0].Data; // 取灰度图值 217 matType = mImage.GetType(); // byte 218 height = mImage.Rows; // 高 219 width = mImage.Cols; // 宽 220 221 // 改自:hImage = new HObject(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, new Scalar(0)); 222 byte[] dataGrayScaleImage = new byte[width * height]; //Mat dataGrayScaleImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); 223 224 unsafe 225 { 226 fixed (byte* ptrdata = dataGrayScaleImage) 227 { 228 #region 按行复制 229 //for (int i = 0; i < height; i++) 230 //{ 231 // CopyMemory((IntPtr)(ptrdata + width * i), new IntPtr((long)ptr + width * i), width); 232 //} 233 #endregion 234 235 CopyMemory((IntPtr)ptrdata, new IntPtr((long)ptr), width * height); 236 HOperatorSet.GenImage1(out hImage, "byte", width, height, (IntPtr)ptrdata); 237 238 } 239 } 240 return hImage; 241 } 242 else if (matChannels == 3) // 三通道 243 { 244 IntPtr ptrRed; // R通道图 245 IntPtr ptrGreen; // G通道图 246 IntPtr ptrBlue; // B通道图 247 Mat[] mats =mImage.Split(); 248 249 ptrRed = mats[0].Data; // 取R通道值 250 ptrGreen = mats[1].Data; // 取G通道值 251 ptrBlue = mats[2].Data; // 取B通道值 252 matType = mImage.GetType(); // 类型 253 height = mImage.Rows; // 高 254 width = mImage.Cols; // 宽 255 256 // 改自:hImage = new HObject(new OpenCvSharp.Size(width, height), MatType.CV_8UC1, new Scalar(0)); 257 byte[] dataRed = new byte[width * height]; //Mat dataGrayScaleImage = new Mat(new OpenCvSharp.Size(width, height), MatType.CV_8UC1); 258 byte[] dataGreen = new byte[width * height]; 259 byte[] dataBlue = new byte[width * height]; 260 261 unsafe 262 { 263 fixed (byte* ptrdataRed = dataRed , ptrdataGreen = dataGreen, ptrdataBlue = dataBlue) 264 { 265 #region 按行复制 266 //HImage himg = new HImage("byte", width, height, (IntPtr)ptrdataRed); 267 //for (int i = 0; i < height; i++) 268 //{ 269 // CopyMemory((IntPtr)(ptrdataRed + width * i), new IntPtr((long)ptrRed + width * i), width); 270 // CopyMemory((IntPtr)(ptrdataGreen + width * i), new IntPtr((long)ptrGreen + width * i), width); 271 // CopyMemory((IntPtr)(ptrdataBlue + width * i), new IntPtr((long)ptrBlue + width * i), width); 272 //} 273 #endregion 274 275 CopyMemory((IntPtr)ptrdataRed , new IntPtr((long)ptrRed ), width* height); // 复制R通道 276 CopyMemory((IntPtr)ptrdataGreen , new IntPtr((long)ptrGreen ), width* height); // 复制G通道 277 CopyMemory((IntPtr)ptrdataBlue , new IntPtr((long)ptrBlue ), width* height); // 复制B通道 278 HOperatorSet.GenImage3(out hImage, "byte", width, height, (IntPtr)ptrdataRed, (IntPtr)ptrdataGreen, (IntPtr)ptrdataBlue); // 合成 279 } 280 } 281 return hImage; 282 } 283 else 284 { 285 return null; 286 } 287 } 288 catch (Exception ex) 289 { 290 throw ex; 291 } 292 293 } 294 295 /// <summary> 296 /// 灰度图像 HObject -> HImage 297 /// </summary> 298 public HImage HObjectToHImage1(HObject hObj) 299 { 300 HImage image = new HImage(); 301 HTuple type, width, height, pointer; 302 HOperatorSet.GetImagePointer1(hObj, out pointer, out type, out width, out height); 303 image.GenImage1(type, width, height, pointer); 304 return image; 305 } 306 307 /// <summary> 308 /// 彩色图像 HObject -> HImage 309 /// </summary> 310 public HImage HObjectToHImage3(HObject hObj) 311 { 312 HImage image = new HImage(); 313 HTuple type, width, height, pointerRed, pointerGreen, pointerBlue; 314 HOperatorSet.GetImagePointer3(hObj, out pointerRed, out pointerGreen, out pointerBlue, 315 out type, out width, out height); 316 image.GenImage3(type, width, height, pointerRed, pointerGreen, pointerBlue); 317 return image; 318 } 319 } 320 }
四,C#MAT图像与C++MAT图像的相互传输
C++:
dlltest.h

1 #pragma once 2 // dlltest.h 头文件,使用动态链接库时需要包含头文件 3 4 #ifdef __DLLEXPORT 5 #define __DLL_EXP _declspec(dllexport) // 导出函数 - 生成dll文件时使用 6 #else 7 #define __DLL_EXP _declspec(dllimport) // 导入函数 -使用dll是使用 8 #endif // __DLLEXPORT 9 10 // 判断是否是c++ 11 #if defined(__cplusplus)||defined(c_plusplus) 12 extern "C" 13 { 14 #endif 15 __DLL_EXP int add(int a, int b); 16 __DLL_EXP int sub(int a, int b); 17 18 #if defined(__cplusplus)||defined(c_plusplus) 19 } 20 #endif
dlltest.cpp

1 #include "pch.h" 2 #include "dlltest.h" 3 #include<stdio.h> 4 5 int add(int a, int b) 6 { 7 return a + b; 8 } 9 10 int sub(int a, int b) 11 { 12 return a - b; 13 }
CppMatToCsMat.h

1 #pragma once 2 #include "pch.h" 3 #include<vector> 4 #include <opencv2/opencv.hpp> //头文件 5 using namespace cv; //包含cv命名空间 6 using namespace std; 7 // 头文件,使用动态链接库时需要包含头文件 8 9 #ifdef __DLLEXPORT 10 #define __DLL_EXP _declspec(dllexport) // 导出函数 - 生成dll文件时使用 11 #else 12 #define __DLL_EXP _declspec(dllimport) // 导入函数 -使用dll是使用 13 #endif // __DLLEXPORT 14 15 // 判断是否是c++ 16 #if defined(__cplusplus)||defined(c_plusplus) 17 extern "C" 18 { 19 #endif 20 //__DLL_EXP void Getmat(uchar *data, size_t &size); 21 __DLL_EXP extern "C" _declspec(dllexport) void Getmat(uchar *data, size_t &size); 22 #if defined(__cplusplus)||defined(c_plusplus) 23 } 24 #endif
CppMatToCsMat.cpp

1 #include "pch.h" 2 #include "CppMatToCsMat.h" 3 #include<vector> 4 #include <opencv2/opencv.hpp> //头文件 5 using namespace cv; //包含cv命名空间 6 using namespace std; 7 8 //void Getmat(uchar *data, size_t &size) 9 extern "C" _declspec(dllexport) void Getmat(uchar *data, size_t &size) 10 { 11 vector<uchar>buf; // uchar数组 12 Mat img = imread("C:\\2.jpg"); // 读入图片 13 imencode(".bmp", img, buf); // 将Mat以BMP格式存入uchar的buf数组中 14 size = buf.size(); 15 for (auto it = buf.begin(); it != buf.end(); it++) // 将buf拷贝到C#的byte[]中 16 { 17 *data = *it; 18 data++; 19 } 20 }
CsMatToCppMat.h

1 #pragma once 2 #include "pch.h" 3 #include<vector> 4 #include <opencv2/opencv.hpp> //头文件 5 using namespace cv; //包含cv命名空间 6 using namespace std; 7 // 头文件,使用动态链接库时需要包含头文件 8 9 #ifdef __DLLEXPORT 10 #define __DLL_EXP _declspec(dllexport) // 导出函数 - 生成dll文件时使用 11 #else 12 #define __DLL_EXP _declspec(dllimport) // 导入函数 -使用dll是使用 13 #endif // __DLLEXPORT 14 15 // 判断是否是c++ 16 #if defined(__cplusplus)||defined(c_plusplus) 17 extern "C" 18 { 19 #endif 20 __DLL_EXP extern "C" _declspec(dllexport) const void Setmat(long* ImageBuffer, int imageWedth, int imageHeigth); 21 #if defined(__cplusplus)||defined(c_plusplus) 22 } 23 #endif
CsMatToCppMat.cpp

1 #include "pch.h" 2 #include "CsMatToCppMat.h" 3 #include<vector> 4 #include <opencv2/opencv.hpp> //头文件 5 using namespace cv; //包含cv命名空间 6 using namespace std; 7 8 // CsMat->CppMat 9 extern "C" _declspec(dllexport) const void Setmat(long* ImageBuffer, int imageWedth, int imageHeigth) 10 { 11 Mat compMat = Mat(imageHeigth, imageWedth, CV_8UC3, ImageBuffer); 12 // 在窗口中显示载入的图片 13 imshow("[载入的图片]", compMat); 14 // 等待6000 ms后窗口自动关闭 15 //waitKey(6000); 16 17 }
CsMatToCppMatToCsMat.h

1 #pragma once 2 #include "pch.h" 3 #include<vector> 4 #include <opencv2/opencv.hpp> //头文件 5 using namespace cv; //包含cv命名空间 6 using namespace std; 7 // 头文件,使用动态链接库时需要包含头文件 8 9 #ifdef __DLLEXPORT 10 #define __DLL_EXP _declspec(dllexport) // 导出函数 - 生成dll文件时使用 11 #else 12 #define __DLL_EXP _declspec(dllimport) // 导入函数 -使用dll是使用 13 #endif // __DLLEXPORT 14 15 // 判断是否是c++ 16 #if defined(__cplusplus)||defined(c_plusplus) 17 extern "C" 18 { 19 #endif 20 __DLL_EXP extern "C" _declspec(dllexport) const void SetmatRuselt(long* ImageBuffer, int imageHeigth, int imageWidth, long* &imgdata, int &imgHeigth, int &imgWidth); 21 #if defined(__cplusplus)||defined(c_plusplus) 22 } 23 #endif
CsMatToCppMatToCsMat.cpp

1 #include "pch.h" 2 #include "CsMatToCppMatToCsMat.h" 3 #include<vector> 4 #include <opencv2/opencv.hpp> //头文件 5 using namespace cv; //包含cv命名空间 6 using namespace std; 7 8 // CsMat->CppMat->CsMat 9 extern "C" _declspec(dllexport) const void SetmatRuselt(long* ImageBuffer, int imageHeigth, int imageWidth, long* &imgdata,int &imgHeigth,int &imgWidth) 10 { 11 Mat compMat = Mat(imageHeigth, imageWidth, CV_8UC3, ImageBuffer); 12 //// 在窗口中显示载入的图片 13 //imshow("[载入的图片1]", compMat); 14 //// 等待6000 ms后窗口自动关闭 15 //waitKey(6000); 16 17 //返回值 18 imgdata = (long*)compMat.data; 19 imgHeigth = compMat.rows; 20 imgWidth = compMat.cols; 21 22 //Mat compMat2 = Mat(imageHeigth, imageWidth, CV_8UC3, imgdata); 23 //// 在窗口中显示载入的图片 24 //imshow("[载入的图片2]", compMat2); 25 //// 等待6000 ms后窗口自动关闭 26 //waitKey(6000); 27 }
CsMatToCppMatToCsMat新,解决“指向内存不对“的问题

//long* ImageBuffer, int imageWedth, int imageHeigth extern "C" _declspec(dllexport) const char* ocrmain(long* ImageBuffer, int imageHeigth, int imageWidth) { //获取mat cv::Mat srcimg = cv::Mat(imageHeigth, imageWidth, CV_8UC3, ImageBuffer); //返回值 ....// img.data是处理完的新图片通道数据 memcpy(ImageBuffer, img.data, sizeof(unsigned char)*img.rows*img.cols*img.channels()); const char* test; test = "1"; return test; }
//返回值
memcpy(ImageBuffer, img.data, sizeof(unsigned char)*img.rows*img.cols*img.channels());
const char* test;
test = ocrstring.c_str();
return test;
C#:

1 using Bll.SaveImage; 2 using OpenCvSharp; 3 using System; 4 using System.Collections.Generic; 5 using System.ComponentModel; 6 using System.Data; 7 using System.Drawing; 8 using System.IO; 9 using System.Linq; 10 using System.Runtime.InteropServices; 11 using System.Text; 12 using System.Threading.Tasks; 13 using System.Windows.Forms; 14 15 namespace repo.素材 16 { 17 public partial class 调用dll : Form 18 { 19 /// <summary> 20 /// 把source指针长度为size的数据复制到指针dest 21 /// </summary> 22 /// <param name="dest">要复制到的地址</param> 23 /// <param name="source">复制源的地址</param> 24 /// <param name="size">复制的长度</param> 25 /// <returns></returns> 26 [DllImport("kernel32.dll")] 27 public extern static long CopyMemory(IntPtr dest, IntPtr source, int size); 28 29 HObjectMatBitmap hObjectMatBitmap21 = new HObjectMatBitmap(); 30 31 // OpencvSharp的图片显示类 32 SharpWindows Imgwindow; 33 // 全局图片Mat类型 34 Mat rawimg; 35 public 调用dll() 36 { 37 InitializeComponent(); 38 // 委托 39 Imgwindow = new SharpWindows(this.pic_ShowPic, "MainUIwindow"); 40 } 41 42 // OCR接口 43 [DllImport("main.dll")] 44 //public extern static void ocrmainone(); 45 public extern static IntPtr ocrmain(IntPtr ImageBuffer, int imageHeigth, int imageWidth); 46 private void button1_Click(object sender, EventArgs e) 47 { 48 //try 49 //{ 50 var filename = OpenfileDlg(); 51 if (filename != null && filename != "") 52 { 53 Mat img = Cv2.ImRead(filename); 54 // 图像数据,高度,宽度 55 IntPtr ptr1 = img.Data; 56 int imageHeigth = img.Height; 57 int imageWidth = img.Width; 58 59 IntPtr ocrStr =ocrmain(new IntPtr((long)ptr1), imageHeigth, imageWidth); 60 Mat lam = new Mat(imageHeigth, imageWidth, MatType.CV_8UC3, ptr1); 61 Cv2.ImShow("[载入的图片3]", lam); 62 Imgwindow.Showimg(lam); 63 string myString = Marshal.PtrToStringAnsi(ocrStr); 64 65 #region 转换为utf-8编码 66 byte[] bytes = Encoding.Default.GetBytes(myString); 67 string myStringr = Encoding.UTF8.GetString(bytes); 68 #endregion 69 70 textBox2.Text = myStringr; 71 } 72 //} 73 //catch (Exception ex) 74 //{ 75 // throw (ex); 76 //} 77 } 78 79 #region 通过路径取文件方法 80 /// <summary> 81 /// 通过路径取文件方法 82 /// </summary> 83 /// <param name="Defaultpath"></param> 84 /// <returns></returns> 85 private static string OpenfileDlg(string Defaultpath = null) 86 { 87 OpenFileDialog ofd = new OpenFileDialog(); 88 ofd.Title = "请选择要打开的文件"; 89 //多选 90 ofd.Multiselect = true; 91 //初始目录 92 ofd.InitialDirectory = Defaultpath; 93 //设定文件类型 94 // ofd.Filter = "*.bmp | *.jpg"; 95 96 ofd.ShowDialog(); 97 98 //获得在打开文件对话框中选择的文件的路径 99 string path = ofd.FileName; 100 return path; 101 } 102 #endregion 103 104 // 求和 105 [DllImport("main.dll")] 106 public extern static int sum(int a, int b); 107 private void button3_Click(object sender, EventArgs e) 108 { 109 int i1 = 10, i2 = 5; 110 int sumruselt = sum(i1, i2); 111 txt1.Text = sumruselt.ToString(); 112 } 113 114 [DllImport("Dlltext.dll")] 115 /// <summary> 116 /// Dlltext 117 /// </summary> 118 /// <param name="data"></param> 119 /// <param name=""> </param> 120 /// <param name=""> </param> 121 /// <returns></returns> 122 public extern static int add(int a, int b); 123 private void button4_Click(object sender, EventArgs e) 124 { 125 int iruselt = add(3, 5); 126 textBox1.Text = iruselt.ToString(); 127 } 128 129 // CppMat->CsMat 130 [DllImport("Dlltext.dll")] 131 public static extern void Getmat(ref byte data, out ulong size); 132 private void button5_Click(object sender, EventArgs e) 133 { 134 //Mat Csmat; 135 //byte[] imgdata = new byte[width * height * 3]; // 存储图片的数组,必须大于等于图片分辨率 136 byte[] imgdata = new byte[3200 * 2400 * 3]; // 存储图片的数组,必须大于等于图片分辨率 137 ulong size = new ulong(); 138 Getmat(ref imgdata[0], out size); 139 textBox1.Text = size.ToString(); 140 pictureBox1.Image = Image.FromStream(new MemoryStream(imgdata, 0, (int)size)); 141 } 142 143 // CsMat->CppMat 144 [DllImport("Dlltext.dll")] 145 public static extern void Setmat(IntPtr bytedata, int width, int height); 146 private void button6_Click(object sender, EventArgs e) 147 { 148 // 图像实际宽度,高度 149 int imgWidth, imgHeigth; 150 //try 151 //{ 152 var filename = OpenfileDlg(); 153 if (filename != null && filename != "") 154 { 155 // 读取Mat图像 156 Mat img = Cv2.ImRead(filename); 157 158 // 取高宽 159 imgWidth = img.Width; 160 imgHeigth = img.Height; 161 IntPtr ptr1 = img.Data; 162 163 //Mat lacalMat = new Mat(imgHeigth, imgWidth, MatType.CV_8UC3, ptr1); 164 //Cv2.ImShow("[载入的图片]", lacalMat); 165 Setmat(new IntPtr((long)ptr1), imgWidth, imgHeigth); 166 } 167 //} 168 //catch (Exception ex) 169 //{ 170 // throw (ex); 171 //} 172 } 173 174 // CsMat->CppMat->CsMat 175 [DllImport("Dlltext.dll")] 176 public static extern void SetmatRuselt(IntPtr ImageBuffer, int imageHeigth, int imageWidth, out IntPtr imgdata, out int imgHeigth, out int imgWidth); 177 private void button7_Click(object sender, EventArgs e) 178 { 179 try 180 { 181 var filename = OpenfileDlg(); 182 if (filename != null && filename != "") 183 { 184 // 读取Mat图像 185 Mat img = Cv2.ImRead(filename); 186 187 // 图像数据,高度,宽度 188 IntPtr ptr1 = img.Data; 189 int imageHeigth = img.Height; 190 int imageWidth = img.Width; 191 192 SetmatRuselt(new IntPtr((long)ptr1), imageHeigth, imageWidth, out IntPtr imgdata, out int imgHeigth, out int imgWidth); 193 194 Mat lacalMatr = new Mat(imgHeigth, imgWidth, MatType.CV_8UC3, imgdata); 195 Cv2.ImShow("[载入的图片3]", lacalMatr); 196 } 197 } 198 catch (Exception ex) 199 { 200 throw (ex); 201 } 202 } 203 204 private void button2_Click(object sender, EventArgs e) 205 { 206 207 } 208 // CsMat->CppMat->CsMat 209 [DllImport("main.dll")] 210 public static extern void SetmatRuselt1(IntPtr ImageBuffer, int imageHeigth, int imageWidth, out IntPtr imgdata, out int imgHeigth, out int imgWidth); 211 private void button8_Click(object sender, EventArgs e) 212 { 213 var filename = OpenfileDlg(); 214 if (filename != null && filename != "") 215 { 216 // 读取Mat图像 217 Mat img = Cv2.ImRead(filename); 218 219 // 图像数据,高度,宽度 220 IntPtr ptr1 = img.Data; 221 int imageHeigth = img.Height; 222 int imageWidth = img.Width; 223 224 SetmatRuselt1(new IntPtr((long)ptr1), imageHeigth, imageWidth, out IntPtr imgdata, out int imgHeigth, out int imgWidth); 225 226 Mat lacalMatr = new Mat(imgHeigth, imgWidth, MatType.CV_8UC3, imgdata); 227 Cv2.ImShow("[载入的图片3]", lacalMatr); 228 } 229 } 230 } 231 }