海康工业相机Python+OpenCV调用实现取流
前言
随着python这们语言不断深入发展,那么python调用工业相机也成为了一项流行的需求;
本文了就简单梳理下海康工业相机python的使用
参考链接
搬砖了一些写的好的文章做参考
海康机器人工业相机sdk简介
python语言调用海康机器人(hikrobotics)工业相机
利用python加opencv与海康工业相机交互
海康工业相机参数设置与获取
环境设置
- 先安装MVS,下载地址 海康机器人官网,SDK简介也可以看看上面的引用博客
- 条件:Python+海康官方的mvs文件下的development/samples下的python文件夹
- 注意:相机连接后不要用官方app打开相机,不然python代码检测不到设备,代码在pycharm会提示报错,亲测能跑并能截取到图片(这个就是说,相机不要被其他软件链接占用啦,同一时刻,一个相机只能被一个软件链接)
- 需要添加模块MvImport的路径: 这是整个代码的核心,文件里面内容如下,具体可以下载MVS里面例程里面有:
import sys
sys.path.append("C:\Program Files (x86)\MVS\Development\Samples\Python\MvImport")
相机控制与数据获取
我们可以把工业相机sdk调用,分成两个部分,相机控制与图像数据获取
- 相机控制
参考其SDK提供的流程图我们可以看出,相机控制分成枚举、打开、参数设置、关闭,销毁句柄五个步骤
那么就分别调用对应的python接口就能实现
枚举相机
# ch:枚举设备 | en:Enum device
ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
if ret != 0:
print ("enum devices fail! ret[0x%x]" % ret)
sys.exit()
打开相机
# 创建句柄
ret = cam.MV_CC_CreateHandle(stDeviceList)
if ret != 0:
print ("create handle fail! ret[0x%x]" % ret)
sys.exit()
# ch:打开设备 | en:Open device
ret = cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
if ret != 0:
print ("open device fail! ret[0x%x]" % ret)
sys.exit()
参数设置
更多的参数设置,可以去看看通用接口是如何使用的参数设置与获取
# ch:设置触发模式为off | en:Set trigger mode as off
ret = cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
if ret != 0:
print ("set trigger mode fail! ret[0x%x]" % ret)
sys.exit()
关闭相机
# ch:停止取流 | en:Stop grab image
ret = cam.MV_CC_StopGrabbing()
if ret != 0:
print ("stop grabbing fail! ret[0x%x]" % ret)
sys.exit()
# ch:关闭设备 | Close device
ret = cam.MV_CC_CloseDevice()
if ret != 0:
print ("close deivce fail! ret[0x%x]" % ret)
sys.exit()
销毁句柄
# ch:销毁句柄 | Destroy handle
ret = cam.MV_CC_DestroyHandle()
if ret != 0:
print ("destroy handle fail! ret[0x%x]" % ret)
sys.exit()
- 图像数据获取
图像数据获取,有两种方法:
一种,使用回调函数获取,参考Grab_Callback.py;
另一种,使用主动取流接口获取,参考GrabImage;
两种方法有其不同的使用场景;(那种场景??)
以其官方提供的示例程序Grab_Callback.py为例子,它的主要目的是在回调函数中,函数接口数据地址pData,pData是一个C*ubyte的数据类型,是没有办法直接用python-opencv进行直接读取,即:不能直接转成numpy array的形式
回调函数
def image_callback(pData, pFrameInfo, pUser):
stFrameInfo = cast(pFrameInfo, POINTER(MV_FRAME_OUT_INFO_EX)).contents
if stFrameInfo:
print ("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nFrameNum))
CALL_BACK_FUN = FrameInfoCallBack(image_callback)
主动取流
# 注意:MV_CC_GetOneFrameTimeout 老式用法,在新版MVS中使用MV_CC_GetImageBuffer()方法
# MVS老式API用法
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))
# MVS新式API用法
数据格式转换
如何将pdata转opencv的数据格式呢
第一步,获取图像数据。我们通过上面介绍的两种不同的取流函数可以获取到pdata指针,但是pdata是POINTER(c_ubyte)类型的指针,我们要转化成asarray*
第二步,图像格式判断与转化。我们要了解到相机输出pdata的是什么图像格式,以及opencv能够处理什么格式。
海康彩色工业相机图像格式转换方法(Bayer转RGB);
黑白单通道还好,彩色就需要转成BGR三通道数据啦
第三步,opencv显示
#实现GetImagebuffer函数取流,HIK格式转换函数
def work_thread_1(cam=0, pData=0, nDataSize=0):
stFrameInfo = MV_FRAME_OUT_INFO_EX() # 定义变量
memset(byref(stFrameInfo), 0, sizeof(stFrameInfo)) # 初始化变量 采用C的方式
# byref(stFrameInfo) 获得stFrameInfo变量的指针,但是指针不能改变,不能取地址操作
print("work_thread_1!\n")
img_buff = None
while True:
ret = cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)
if ret == 0:
print ("MV_CC_GetOneFrameTimeout: Width[%d], Height[%d], nFrameNum[%d]" % (stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nFrameNum))
time_start = time.time()
stConvertParam = MV_CC_PIXEL_CONVERT_PARAM()
memset(byref(stConvertParam), 0, sizeof(stConvertParam))
if IsImageColor(stFrameInfo.enPixelType) == 'mono':
print("mono!")
stConvertParam.enDstPixelType = PixelType_Gvsp_Mono8
nConvertSize = stFrameInfo.nWidth * stFrameInfo.nHeight
elif IsImageColor(stFrameInfo.enPixelType) == 'color':
print("color!")
stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed # opecv要用BGR,不能使用RGB
nConvertSize = stFrameInfo.nWidth * stFrameInfo.nHeight* 3
else:
print("not support!!!")
if img_buff is None:
img_buff = (c_ubyte * stFrameInfo.nFrameLen)()
# ---
stConvertParam.nWidth = stFrameInfo.nWidth
stConvertParam.nHeight = stFrameInfo.nHeight
stConvertParam.pSrcData = cast(pData, POINTER(c_ubyte))
stConvertParam.nSrcDataLen = stFrameInfo.nFrameLen
stConvertParam.enSrcPixelType = stFrameInfo.enPixelType
stConvertParam.pDstBuffer = (c_ubyte * nConvertSize)()
stConvertParam.nDstBufferSize = nConvertSize
ret = cam.MV_CC_ConvertPixelType(stConvertParam)
if ret != 0:
print("convert pixel fail! ret[0x%x]" % ret)
del stConvertParam.pSrcData
sys.exit()
else:
print("convert ok!!")
# 转OpenCV
# 黑白处理
if IsImageColor(stFrameInfo.enPixelType) == 'mono':
img_buff = (c_ubyte * stConvertParam.nDstLen)()
cdll.msvcrt.memcpy(byref(img_buff), stConvertParam.pDstBuffer, stConvertParam.nDstLen)
img_buff = np.frombuffer(img_buff,count=int(stConvertParam.nDstLen), dtype=np.uint8)
img_buff = img_buff.reshape((stFrameInfo.nHeight, stFrameInfo.nWidth))
print("mono ok!!")
image_show(image=img_buff) # 显示图像函数
# 彩色处理
if IsImageColor(stFrameInfo.enPixelType) == 'color':
img_buff = (c_ubyte * stConvertParam.nDstLen)()
cdll.msvcrt.memcpy(byref(img_buff), stConvertParam.pDstBuffer, stConvertParam.nDstLen)
img_buff = np.frombuffer(img_buff, count=int(stConvertParam.nDstBufferSize), dtype=np.uint8)
img_buff = img_buff.reshape(stFrameInfo.nHeight,stFrameInfo.nWidth,3)
print("color ok!!")
image_show(image=img_buff) # 显示图像函数
time_end = time.time()
print('time cos:', time_end - time_start, 's')
else:
print ("no data[0x%x]" % ret)
if g_bExit == True:
break
# 显示图像
def image_show(image):
image = cv2.resize(image, (600, 400), interpolation=cv2.INTER_AREA)
cv2.imshow('test', image)
k = cv2.waitKey(1) & 0xff
# 判读图像格式是彩色还是黑白
def IsImageColor(enType):
dates = {
PixelType_Gvsp_RGB8_Packed: 'color',
PixelType_Gvsp_BGR8_Packed: 'color',
PixelType_Gvsp_YUV422_Packed: 'color',
PixelType_Gvsp_YUV422_YUYV_Packed: 'color',
PixelType_Gvsp_BayerGR8: 'color',
PixelType_Gvsp_BayerRG8: 'color',
PixelType_Gvsp_BayerGB8: 'color',
PixelType_Gvsp_BayerBG8: 'color',
PixelType_Gvsp_BayerGB10: 'color',
PixelType_Gvsp_BayerGB10_Packed: 'color',
PixelType_Gvsp_BayerBG10: 'color',
PixelType_Gvsp_BayerBG10_Packed: 'color',
PixelType_Gvsp_BayerRG10: 'color',
PixelType_Gvsp_BayerRG10_Packed: 'color',
PixelType_Gvsp_BayerGR10: 'color',
PixelType_Gvsp_BayerGR10_Packed: 'color',
PixelType_Gvsp_BayerGB12: 'color',
PixelType_Gvsp_BayerGB12_Packed: 'color',
PixelType_Gvsp_BayerBG12: 'color',
PixelType_Gvsp_BayerBG12_Packed: 'color',
PixelType_Gvsp_BayerRG12: 'color',
PixelType_Gvsp_BayerRG12_Packed: 'color',
PixelType_Gvsp_BayerGR12: 'color',
PixelType_Gvsp_BayerGR12_Packed: 'color',
PixelType_Gvsp_Mono8: 'mono',
PixelType_Gvsp_Mono10: 'mono',
PixelType_Gvsp_Mono10_Packed: 'mono',
PixelType_Gvsp_Mono12: 'mono',
PixelType_Gvsp_Mono12_Packed: 'mono'}
return dates.get(enType, '未知')
效果展示:
彩色:
黑白:
更多推荐
所有评论(0)