C# 相机内存复用(减少图像采集耗时)以及行数复用
背景
我们在做图像处理时,都会对一些相机的SDK进行开发完成图像采集的操作,为后续图像处理做准备。本文主要的目的是降低图像采集的耗时,应用在一些高速检测的场景下。利用循环队列+内存复用的方式,去掉或者减少新建内存的时间。
线扫描相机
线扫描相机会将采集到的1-N行打包回工控机中,由SDK将这些行的数据拷贝到内部的循环队列中。
正常流程:
1)相机SDK给出完成回调
2)软件拷贝根据图像大小和通道数拷贝指针数据
3)图像处理。
该流程在2)的时候需要执行 new memory / copy memory的操作,我们现在的步骤就是需要简化掉这两步,有以下两种优化方案。
优化方案一
新建循环队列,每次只执行copy动作,耗时减少一半
1)相机SDK给出完成回调
2)循环队列获取当前图像
3)拷贝内存至当前图像上
4)循环队列移至下一张图像
5)图像处理
优化方案二
新建循环队列,将循环队列个数和指针直接设置进SDK中(这个需要相机厂家支持,SDK内部队列可以由用户设置),整体耗时为0ms
拿IKAP(埃科)的相机举例,设置SDK内部队列的方式如下:
IKapBoardClassLibrary.IKapBoard.IKapSetBufferAddress(m_ptrBoard, ptrs.Count, ptr); //采集卡
1)相机SDK给出完成回调
2)直接根据相机给出的图像指针找到 循环队列中的图像
3)图像处理
4)只针对黑白图像,彩色图像还是执行新建吧,因为halcon的这个存储格式获取彩色图像指针时是三个指针,而相机SDK给出的指针一般是 RGBRGB这样的格式,去做这个拆包循环有点得不偿失了
注意事项
1)以上两种方式都需要用到循环队列,要注意一个循环内要把图像处理完成
2)建议把 queue的size开大一些,拿内存去换时间
3)需要长时间保留在内存的图片,建议直接执行copy再自行删除
面阵相机
面阵相机的方案跟线扫描的方案一是一致的,方案二的方式可以尝试一下(我没有试过,因为面阵一般来说图比较小,创建耗时比较低,没去特地做优化)
线扫描相机行数复用
优化方案
这个功能主要是用在循环拍摄时,当前图片需要上一张图像尾巴上的固定若干行信息,按照以下方式,整体的内存拷贝效率高,只需要拷贝复用的行数即可。
我们可以把这个步骤直接做到相机中,可以参考线扫描相机的优化的两个点,在这直接加一些逻辑。
先假设相机SDK设置的图像是 8192*3000,复用的行数是100.
1)首先,如果我们需要复用100行上一张的图像,我们在制作图像指针时要制作比SDK设置图像的高度+100,那么我们需要做 8192*3100的图像指针出来。
2)在设置指针给SDK时,需要对指针进行偏移 100行,这样相机能正常的采集图像并拷贝进指针中
3)每次采集完成回调后,需要将上一张图的尾巴100行的指针拷贝到当前图像的前100行中
4)图像处理
注意事项
1、第一张图头部几行会是全黑的,这里建议判断是否是第一张图像,如果是的话,给图的时候做指针偏移给3000行的图,这样可以避免第一张图的异常