本文仅作记录!原文链接!:https://blog.csdn.net/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)

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

  1. 调用海康视频接口获取预览取流的URL

    开始之前请参考海康官方SDK文档 鉴于前段时间刚接触视频这一块,整理了自己的一些经验,具体的你们还是参考文档来吧 附上文档地址 https://open.hikvision.com/docs/docI ...

  2. python调用海康工业相机并用opencv显示(整体实现)

    python语言调用海康机器人(hikrobotics)工业相机 系列文章目录 第一章 python调用海康工业相机并用opencv显示(整体实现) 第二章 python 调用海康工业相机图像获取方式 ...

  3. (一)Qt+OpenCV调用海康工业相机SDK示例开发

    系列文章目录 提示:这里是该系列文章的所有文章的目录 第一章: (一)Qt+OpenCV调用海康工业相机SDK示例开发 第二章: (二)Qt多线程实现海康工业相机图像实时采集 文章目录 系列文章目录 ...

  4. QT+opencv调用海康工业相机

    这里写自定义目录标题 QT+opencv调用海康工业相机 开发环境 引用海康开发文件 直接上代码 QT+opencv调用海康工业相机 最近在使用Opencv调用海康工业相机的程序,从网上查了好多资料, ...

  5. Python调用海康工业相机:包含相机参数修改、彩色原图显示(不失真)

    [引言] 海康相机作为目前工业检测.视觉定位等领域应用较为广泛的国产品牌相机,其搭配有一套专用视觉软件VM,而在完成具有复杂场景.复杂任务的科研项目时依靠其VM算法平台提供的视觉算法往往无法满足项目要 ...

  6. c++ 海康工业相机回调方式抓图片

    1.MVS 软件 下载地址:百度网盘 请输入提取码   k6a7 MVS 是海康工业相机官方提供的调试软件,可以对相机进行修改IP,配置相关的相机参数 注意事项: mvs配置有三种模式   大师 &g ...

  7. qt调用海康工业相机踩坑全纪录

    方法一,使用qt中的QCameraInfo::availableCameras()调用海康摄像头 结论,失败 想的太天真 #include "mainwindow.h" #incl ...

  8. WIN10 C++调用海康工业相机

    1.安装海康工业相机套件MVS,需要下载的MVS如下图所示.链接为https://www.hikrobotics.com/cn/machinevision/service/download?modul ...

  9. python 调用海康工业相机调试后出现被占用问题

    问题描述: 在使用海康工业网口相机开发过程中,调试阶段异常结束程序调试时,经常出现相机被占用的异常情况,无论是使用海康的客户端界面连接相机还是使用调试代码连接相机,都没有权限再次打开相机,需要相机断电 ...

最新文章

  1. amazeui学习笔记--css(常用组件4)--关闭按钮Close
  2. 微信新增“炸屎”功能,被好友玩坏了。。
  3. 第三次作业-介绍一款原型设计工具
  4. Android 性能优化 之谈谈Java内存区域
  5. 阿里云服务器安装JDK指南
  6. 面向对象(OOP)五大基本原则
  7. eviews如何处理缺失数据填补_平衡面板数据和eviews非平衡面板数据的区别
  8. 三分钟教你学Git(十二) 之 fast-forward
  9. 常见函数泰勒公式展开(清晰)
  10. html富强民主鼠标特效,给网站添加鼠标点击特效富强、民主、和谐 js效果 - 寒星皓月...
  11. win10系统每天凌晨3点左右,自动关机重启
  12. 我的言论05-04-06
  13. 罗切斯特大学排名计算机排名,2020年罗切斯特大学QS世界排名
  14. java 转成数字,java汉字转成数字
  15. 一文读懂 WebSocket 通信过程与实现
  16. Zabbix 5.4.12 源码编译安装
  17. python实验原理_【python】《统计学原理实验教程(Python)》书中代码实现
  18. 将因式展开 matlab,关于Matlab中符号运算的因式分解、展开与合并
  19. AweCleaner for Mac(一体式Mac系统清理应用)
  20. 在学期初小结本学期要做的事情

热门文章

  1. 原厂电源IC芯片HD7100A23E-42HD7100A23E-43HD7100A23F-42HD7100A23F-43HD7100AESH-42 HD7100AESH-43
  2. 零基础如何学习电子技术【转】
  3. 芯片供应商如何看待国际十大芯片制作公司的排名
  4. 中国高强度不锈钢行业供需状况及竞争趋势预测报告(2022-2027年)
  5. 梯度之上:Hessian 矩阵
  6. 交通领域类SCI期刊
  7. 数据分析 第五讲 numpy
  8. 智慧交通大数据可视化
  9. latex编译时报错:runaway argument?
  10. Android音频录制、播放,这一篇就够了