1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 调用海康工业相机图像获取方式之主动取流(getimagebuffer )

调用海康工业相机图像获取方式之主动取流(getimagebuffer )

时间:2024-03-12 20:23:07

相关推荐

调用海康工业相机图像获取方式之主动取流(getimagebuffer )

本文仅作记录!原文链接!:/qq_39570716/article/details/114304110

目录

一、使用前提

二、主动取流(官方例程说明)

1.接口说明

2.python 下接口实现

三、主动取流( getimagebuffer )对黑白图像数据解析并用 opencv 显示

1.主动取流( getimagebuffer )数据获取并解析 mono 格式的图像数据

2.图像数据显示

四、主动取流( getimagebuffer )获取多种像素格式的图像数据解析并用 opencv 显示

1.主动取流( getimagebuffer )数据获取并解析多种像素格式的数据

2.图像数据显示

五、主动取流(getoneframetimeout & getimagebuffer)的封装

海康工业相机的底层SDK中提供了两种不同方式的图像数据获取方式,一种是回调方式,一种是主动取流方式。但是官方示例中,只提供了相关数据获取到之后的打印信息,对于图像数据的解析并没有给出,基于以上情况,本文对主动取流方式( getimagebuffer )获取到的图像数据进行解析。

一、使用前提

需要先安装海康工业相机的底层SDK,在安装之后,会有相关例程在安装目录下,本文的代码调用需要在该目录下调用(未作移植使用);

基于第一章(python调用海康工业相机并用opencv显示)对于海康工业相机连接的内容,本文对于海康工业相机的主动取流方式(getimagebuffer )取到的图像解析进行说明。

二、主动取流(官方例程说明)

1.接口说明

在海康提供的底层SDK中,有相关主动取流之 getimagebuffer 取流的接口,并且在安装目录下的工业相机SDK开发指南中,有对该接口的具体介绍,具体如下:

接口:MV_CC_GetImageBuffer()

对应于 C 语言接口如下:

MV_CAMCTRL_API int __stdcall MV_CC_GetImageBuffer ( IN void * handle, OUT MV_FRAME_OUT * pstFrame, IN unsigned int nMsec)参数:handle :设备句柄pstFrame :图像数据和图像信息nMsec :等待超时时间,输入 INFINITE 时表示无限等待,直到收到一帧数据或者停止取流,返回:调用成功,返回 MV_OK调用失败,返回错误码

注:

1、调用该接口获取图像数据帧之前需要先调用 MV_CC_StartGrabbing() 启动图像采集,该接口为主动式获取帧数据,上层应用程序需要根据帧率,控制好调用该接口的频率。该接口支持设置超时时间,SDK内部等待直到有数据时返回,可以增加取流平稳性,适合用于对平稳性要求较高的场合。

2、该接口与 MV_CC_FreeImageBuffer() 接口配套使用,当处理完取到的数据后,需要用 MV_CC_FreeImageBuffer() 接口将 pstFrame 内的数据指针权限进行释放;

3、该接口与 MV_CC_GetOneFrameTimeout() 接口相比, 该接口有更高的效率,并且取流缓存的分配由 SDK 内部自动分配,而 MV_CC_GetOneFrameTimeout() 接口是需要我们自行分配的;

4、该接口在调用了 MV_CCDisplay() 接口后会无法取流;

5、该接口不支持 Cameralink 设备,仅支持 GigE 、USB 设备;

2.python 下接口实现

根据以上说明可知,MV_CC_GetImageBuffer() 接口需要在开始采集图像接口调用之后使用,即官方例程中的该接口调用,如下:

# 为线程定义一个函数def work_thread(cam=0, pData=0, nDataSize=0):stOutFrame = MV_FRAME_OUT() memset(byref(stOutFrame), 0, sizeof(stOutFrame))while True:ret = cam.MV_CC_GetImageBuffer(stOutFrame, 1000)if None != stOutFrame.pBufAddr and 0 == ret:print ("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))nRet = cam.MV_CC_FreeImageBuffer(stOutFrame)else:print ("no data[0x%x]" % ret)if g_bExit == True:break

在开启取流之后,通过该接口主动去抓取 SDK 底层的 buffer 中的图像数据和信息,通过该接口,可以将图像数据给到我们,但是官方例程中,并没有提供相关数据解析和显示的相关内容,这样就导致我们在此环节需要重新开发,本文第三部分将对图像数据的解析和显示做相关的代码实现;

并且在上面代码中可以看到该接口与 MV_CC_FreeImageBuffer()接口配套使用,在取到图像数据之后,在取下一张图像数据之前将 pstOutFrame 内的数据指针权限进行了释放;

三、主动取流( getimagebuffer )对黑白图像数据解析并用 opencv 显示

1.主动取流( getimagebuffer )数据获取并解析 mono 格式的图像数据

# 为线程定义一个函数def work_thread(cam=0, pData=0, nDataSize=0):stOutFrame = MV_FRAME_OUT() memset(byref(stOutFrame), 0, sizeof(stOutFrame))while True:ret = cam.MV_CC_GetImageBuffer(stOutFrame, 1000)if None != stOutFrame.pBufAddr and 0 == ret:print ("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)else:print ("no data[0x%x]" % ret)nRet = cam.MV_CC_FreeImageBuffer(stOutFrame)if g_bExit == True:break

通过对官方例程中 getimagebuffer 获取图像数据的代码修改,获取到相关图像的数据,如上代码中 data 即为回调获取到的图像数据,并通过自定义函数 image_control() 对图像数据进行 reshape 操作,获取到可以显示的数据;

并且在一帧图像数据获取显示之后通过调用 MV_CC_FreeImageBuffer() 接口的调用,将数据指针权限进行了释放;

2.图像数据显示

def image_show(image):image = cv2.resize(image, (600, 400), interpolation=cv2.INTER_AREA)cv2.imshow('fgmask', image)k = cv2.waitKey(1) & 0xffdef image_control(data , stFrameInfo):image = data.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth))image_show(image = image)

以上代码时对使用 getimagebuffer 接口获取到的图像数据进行显示的代码,但是以上代码仅在使用海康工业相机黑白模式下使用,因为没有考虑像素格式以及通道等信息,下面第四部分对多种像素格式图像数据进行解析并显示;

四、主动取流( getimagebuffer )获取多种像素格式的图像数据解析并用 opencv 显示

1.主动取流( getimagebuffer )数据获取并解析多种像素格式的数据

具体代码如下所示:

if active_way == "getImagebuffer":stOutFrame = MV_FRAME_OUT()memset(byref(stOutFrame), 0, sizeof(stOutFrame))while True:ret = cam.MV_CC_GetImageBuffer(stOutFrame, 1000)if None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 17301505:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 17301514:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 35127316:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight*3)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight*3)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight*3),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 34603039:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)else:print("no data[0x%x]" % ret)nRet = cam.MV_CC_FreeImageBuffer(stOutFrame)

以上部分因为与主动取流中的 getoneframetimeout 接口的调用封装到一起,所以是以 if 开头,并调用的,后续会将这两部分的代码全部放到一起;

因为工业相机总有不同的像素格式,也就对应有不同的通道数,所以在图像解析过程中就会出现不同分支的解析方式,以上内容是根据海康提供的官方定义中获取到的像素格式对应的数字,进行判定,具体的定义在海康 SDK 目录下:../MVS/Development/Samples/Python/MvImport/PixelType_header.py 文件中,如需要其他像素格式,请自行查询;

2.图像数据显示

由以上内容可以知道,通过 getimagebuffer 获取到的图像数据是多种像素格式类型的,不同像素格式类型图像通道不同,自然也会导致显示时,不同通道配置的代码,以下内容是对不同像素格式类型的图像数据的显示,代码如下:

# 显示图像def image_show(image):image = cv2.resize(image, (600, 400), interpolation=cv2.INTER_AREA)cv2.imshow('fgmask', image)k = cv2.waitKey(1) & 0xff# 需要显示的图像数据转换def image_control(data , stFrameInfo):if stFrameInfo.enPixelType == 17301505:image = data.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth))image_show(image=image)elif stFrameInfo.enPixelType == 17301514:data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)image = cv2.cvtColor(data, cv2.COLOR_BAYER_GB2RGB)image_show(image=image)elif stFrameInfo.enPixelType == 35127316:data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)image = cv2.cvtColor(data, cv2.COLOR_RGB2BGR)image_show(image=image)elif stFrameInfo.enPixelType == 34603039:data = data.reshape(stFrameInfo.nHeight, stFrameInfo.nWidth, -1)image = cv2.cvtColor(data, cv2.COLOR_YUV2BGR_Y422)image_show(image = image)

五、主动取流(getoneframetimeout & getimagebuffer)的封装

主动取流在海康提供的 SDK 底层接口中有两种,分别是 getoneframetimeout 和 getimagebuffer 两种,以下代码是对这两种取流方式的封装函数代码,如下:

# 主动图像采集def access_get_image(cam , active_way = "getImagebuffer"):""":param cam: 相机实例:active_way:主动取流方式的不同方法 分别是(getImagebuffer)(getoneframetimeout):return:"""if active_way == "getImagebuffer":stOutFrame = MV_FRAME_OUT()memset(byref(stOutFrame), 0, sizeof(stOutFrame))while True:ret = cam.MV_CC_GetImageBuffer(stOutFrame, 1000)if None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 17301505:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 17301514:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 35127316:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight*3)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight*3)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight*3),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)elif None != stOutFrame.pBufAddr and 0 == ret and stOutFrame.stFrameInfo.enPixelType == 34603039:print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stOutFrame.stFrameInfo.nWidth, stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nFrameNum))pData = (c_ubyte * stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2)()cdll.msvcrt.memcpy(byref(pData), stOutFrame.pBufAddr,stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2)data = np.frombuffer(pData, count=int(stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 2),dtype=np.uint8)image_control(data=data, stFrameInfo=stOutFrame.stFrameInfo)else:print("no data[0x%x]" % ret)nRet = cam.MV_CC_FreeImageBuffer(stOutFrame)elif active_way == "getoneframetimeout":stParam = MVCC_INTVALUE_EX()memset(byref(stParam), 0, sizeof(MVCC_INTVALUE_EX))ret = cam.MV_CC_GetIntValueEx("PayloadSize", stParam)if ret != 0:print("get payload size fail! ret[0x%x]" % ret)sys.exit()nDataSize = stParam.nCurValuepData = (c_ubyte * nDataSize)()stFrameInfo = MV_FRAME_OUT_INFO_EX()memset(byref(stFrameInfo), 0, sizeof(stFrameInfo))while True:ret = cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)if ret == 0:print("get one frame: Width[%d], Height[%d], nFrameNum[%d] " % (stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nFrameNum))image = np.asarray(pData)image_control(data=image, stFrameInfo=stFrameInfo)else:print("no data[0x%x]" % ret)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。