系列文章目录

第一章 python调用海康工业相机并用opencv显示(整体实现)

第二章 python 调用海康工业相机图像获取方式之回调取流并用 opencv 显示

第三章 python 调用海康工业相机图像获取方式之主动取流(getoneframetimeout )并用 opencv 显示

第四章 python 调用海康工业相机图像获取方式之主动取流( getimagebuffer )并用 opencv 显示

第五章 python 调用海康工业相机调试后出现被占用问题


 


前言

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


一、使用前提

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

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

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

1.接口说明

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

接口:MV_CC_GetOneFrameTimeout()

对应于 C 语言接口如下:

MV_CAMCTRL_API int __stdcall MV_CC_GetOneFrameTimeout  ( IN void *  handle,  
                                                         IN OUT unsigned char *  pData,  
                                                         IN unsigned int  nDataSize,  
                                                         IN OUT MV_FRAME_OUT_INFO_EX *  pstFrameInfo,  
                                                         unsigned int  nMsec  
                                                       ) 

参数:

。handle :设备句柄

。pData :图像数据接收指针

。nDataSize :接收缓存大小

。pstFrameInfo : 图像信息结构体

。nMsec :等待超时时间

返回:

。调用成功,返回 MV_OK

。调用失败,返回错误码

注: 

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

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

    3、该接口的图像缓存是由我们自己去申请;

2.python 下接口实现

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

def work_thread(cam=0, pData=0, nDataSize=0):
    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))
        else:
            print ("no data[0x%x]" % ret)
        if g_bExit == True:
                break

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

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

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

def work_thread(cam=0, pData=0, nDataSize=0 , name = 0):
    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).reshape((stFrameInfo.nHeight, stFrameInfo.nWidth))
            cv2.imshow("show", image)
            k = cv2.waitKey(1) & 0xff
        else:
            print ("no data[0x%x]" % ret)
        if g_bExit == True:
                break

通过对官方例程中回调获取图像数据的代码修改,获取到相关图像的数据,如上代码中 data 即为该接口获取到的图像数据,并通过对图像数据进行 reshape 操作,最终实现显示;

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

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

基于第一章(python调用海康工业相机并用opencv显示)中,对于常用接口的封装,getoneframetimeout 也进行相关内容的封装,将该接口获取的图像数据解析部分封装为一体,获取图像部分具体代码如下所示:

    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.nCurValue
        pData = (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)

通过以上方式,将获取到的图像数据整块的获取到,获取到之后通过自定义韩式 image_control() 函数,将不同格式的图像数据分别进行通道转换,转换为可以被 opencv 显示的格式;

2.图像数据显示

有以上内容可知,获取到的图像数据块可能是多种像素格式类型的,不同的像素格式类型图像通道不同,不同的通道转换成 opencv 可以显示的格式转换方式不同,以下内容是对不同像素格式类型的图像数据的显示,代码如下:

# 显示图像
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 获取到的图像数据如何解析,相对比较重要,以上是对海康工业相机 python 下调用 getoneframetimeout 接口获取到的图像数据的解析;由于现阶段大部分工业相机的SDK底层是以 C 语言和 C# 为主要语言,所以 python 的调用,就选择了使用 C 语言为基础的接口转换后的 python 接口来调用相机,而这种方式在工业界相对比较常见。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐