近期在用线扫相机进行一些视觉检测,针对线扫相机的特性,对其输出的图像进行拼接,例如拼接上一张图像的最后64行到下本次图像中。
最开始的思路是在halcon中进行操作,利用paint_region进行重绘,发现效率极低。后来想起来不就是矩阵操作,数组拷贝之类的操作吗,最后直接在C#中进行拼接,对图像指针进行操作(效率还是不如C++)。分享代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | /// <summary> /// 将两个指针拼接成一个数组 /// </summary> /// <param name="lastPtr">上一次数据指针</param> /// <param name="curPtr">本次数据指针</param> /// <param name="imgWidth">图片宽度</param> /// <param name="imgHeight">图片长度</param> /// <param name="concatRowCount">拼接行数</param> /// <param name="outputBytes">输出数组</param> public static void ConcatGrayIntptr(IntPtr lastPtr, IntPtr curPtr, int imgWidth, int imgHeight, int concatRowCount, out byte[] outputBytes) { outputBytes = new byte[(imgHeight + concatRowCount) * imgWidth]; IntPtr offsetLastPtr = IntPtr.Zero; if (lastPtr != IntPtr.Zero) { if (IntPtr.Size == sizeof(Int64)) offsetLastPtr = new IntPtr(lastPtr.ToInt64() + imgWidth * (imgHeight - concatRowCount)); else offsetLastPtr = new IntPtr(lastPtr.ToInt32() + imgWidth * (imgHeight - concatRowCount)); } if (offsetLastPtr != IntPtr.Zero) { System.Runtime.InteropServices.Marshal.Copy(offsetLastPtr, outputBytes, 0, concatRowCount * imgWidth); } System.Runtime.InteropServices.Marshal.Copy(curPtr, outputBytes, concatRowCount * imgWidth, imgWidth * imgHeight); } /// <summary> /// 把多个指针拼接成一个数组,其中忽略掉重叠部分 /// </summary> /// <param name="ptrs"></param> /// <param name="imgWidth"></param> /// <param name="imgHeight"></param> /// <param name="concatRowCount"></param> /// <param name="outputBytes"></param> public static void ConcatGrayContinuesIntptr(IntPtr[] ptrs,int imgWidth,int imgHeight,int concatRowCount,out byte[] outputBytes) { int oneImageSize = imgWidth * (imgHeight - concatRowCount); outputBytes = new byte[oneImageSize * ptrs.Length]; int iCopyIndex = 0; foreach(IntPtr ptr in ptrs) { if (ptr != IntPtr.Zero) { IntPtr offsetPtr; if (IntPtr.Size == sizeof(Int64)) offsetPtr = new IntPtr(ptr.ToInt64() + imgWidth * concatRowCount); else offsetPtr = new IntPtr(ptr.ToInt32() + imgWidth * concatRowCount); System.Runtime.InteropServices.Marshal.Copy(offsetPtr, outputBytes, iCopyIndex, oneImageSize); } iCopyIndex += oneImageSize; } } /// <summary> /// 拼接连续的几张图片成一张图片 /// </summary> /// <param name="images">图片集合</param> /// <param name="concatRowCount">其中每张图片重合的行数</param> /// <param name="concatedImage">拼接后的图片</param> /// <returns></returns> public static bool ConcatGrayImage(HImage[] images,int concatRowCount,out HImage concatedImage) { if(images.Length == 0) { concatedImage = null; return false; } List<IntPtr> ptrs = new List<IntPtr>(); string type; int width = 0, height= 0; foreach(HImage img in images) { if (img == null) { ptrs.Add(IntPtr.Zero); } else { IntPtr ptr = img.GetImagePointer1(out type,out width, out height); ptrs.Add(ptr); } } byte[] pixelBytes; ConcatGrayContinuesIntptr(ptrs.ToArray(), width, height, concatRowCount, out pixelBytes); new Lhxzn.Halcon.CameraImageData2HImage().Transform( new CameraImageDataByte(width, images.Length *(height-concatRowCount), PixelType.Mono8, pixelBytes), out concatedImage); return true; } /// <summary> /// 拼接上一张图片的最后几行到本次图片中并输出 /// </summary> /// <param name="lastImage">上一张图片</param> /// <param name="curImage">本次的图片</param> /// <param name="concatRowCount">需拼接的行数</param> /// <param name="concatedImage">输出的图像</param> /// <returns></returns> public static bool ConcatGrayImage(HImage lastImage, HImage curImage, int concatRowCount, out HImage concatedImage) { if (curImage == null || (lastImage == null && curImage == null)) { concatedImage = null; return false; } else { string last_type, cur_type; int last_width, last_height, cur_width, cur_height; IntPtr lastPtr = IntPtr.Zero; if (lastImage != null) lastPtr = lastImage.GetImagePointer1(out last_type, out last_width, out last_height); IntPtr curPtr = curImage.GetImagePointer1(out cur_type, out cur_width, out cur_height); int new_width = cur_width, new_height = cur_height + concatRowCount; byte[] pixelBytes; ConcatGrayIntptr(lastPtr, curPtr, cur_width, cur_height, concatRowCount, out pixelBytes); DateTime start = DateTime.Now; new Lhxzn.Halcon.CameraImageData2HImage().Transform( new CameraImageDataByte(cur_width, new_height, PixelType.Mono8, pixelBytes), out concatedImage); double inter = (DateTime.Now - start).TotalMilliseconds; return true; } } |