近期在用线扫相机进行一些视觉检测,针对线扫相机的特性,对其输出的图像进行拼接,例如拼接上一张图像的最后64行到下本次图像中。
最开始的思路是在halcon中进行操作,利用paint_region进行重绘,发现效率极低。后来想起来不就是矩阵操作,数组拷贝之类的操作吗,最后直接在C#中进行拼接,对图像指针进行操作(效率还是不如C++)。分享代码如下:
/// <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;
}
}