python opencv 调用 海康威视工业相机(又全又细又简洁)_工业相机接python
1.准备工作
准备一个海康相机
下载MVS 和SDK
海康机器人-机器视觉-下载中心
2.python MVS示例
(说明:MVS里有很多python示例,可以直接运行,但没有用opencv)
下载完MVS后,我们打开路径安装路径
我的:
D:\\soft\\MVS\\MVS\\Development\\Samples\\Python\\BasicDemo
D:\\soft\\MVS\\MVS\\Development\\Samples\\Python\\MvImport
可以看到有很多现成的示例。
我们借用一下\"D:\\soft\\MVS\\MVS\\Development\\Samples\\Python\\BasicDemo\\BasicDemo.py\"
创建 python项目test_HKcamera
复制BasicDemo.py
发现一片红,
我们把
D:\\soft\\MVS\\MVS\\Development\\Samples\\Python\\BasicDemo
D:\\soft\\MVS\\MVS\\Development\\Samples\\Python\\MvImport
里面的文件都复制过来
复制后,如图所示:
没有装pyqt的安装一下
安装:pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple
运行后:
成功输出画面。
3. python opencv 调用
创建test_HKcamera_opencv文件夹
创建test_hk_opecv.py文件
把第二节的文件复制进来
如图:
test_hk_opecv.py完整代码如下:
import cv2import numpy as npfrom MvCameraControl_class import *from CameraParams_header import *#-------------------opencv操作部分--------------------------------------def opencv_action(img): #自己定义操作 result_img = img return result_img#-----------------------海康相机设置部分---------------------------------------ret = MvCamera.MV_CC_Initialize()if ret != 0: print(f\"初始化SDK失败,错误码: {ret}\") exit()# 枚举设备deviceList = MV_CC_DEVICE_INFO_LIST()n_layer_type = MV_GIGE_DEVICE | MV_USB_DEVICE | MV_GENTL_CAMERALINK_DEVICEret = MvCamera.MV_CC_EnumDevices(n_layer_type, deviceList)if ret != 0: print(\"枚举设备失败\") exit()print(f\"找到 {deviceList.nDeviceNum} 台设备\")if deviceList.nDeviceNum == 0: exit()stDeviceList = cast(deviceList.pDeviceInfo[0], POINTER(MV_CC_DEVICE_INFO)).contentscamera = MvCamera()ret = camera.MV_CC_CreateHandle(stDeviceList)# 打开设备(使用已创建的句柄)ret = camera.MV_CC_OpenDevice()if ret != 0: print(f\"打开设备失败,错误码: {ret}\") exit()# 获取相机参数width = c_uint()height = c_uint()pixel_format = c_uint()payload_size = c_uint()stParam = MVCC_INTVALUE()ret = camera.MV_CC_GetIntValue(\"PayloadSize\", stParam)if ret != 0: print(f\"获取PayloadSize失败,错误码: {ret}\") exit()payload_size.value = stParam.nCurValue# 获取宽度ret = camera.MV_CC_GetIntValue(\"Width\", stParam)if ret != 0: print(f\"获取宽度失败,错误码: {ret}\") exit()width.value = stParam.nCurValue# 获取高度ret = camera.MV_CC_GetIntValue(\"Height\", stParam)if ret != 0: print(f\"获取高度失败,错误码: {ret}\") exit()height.value = stParam.nCurValueprint(width.value,height.value)pixel_format.value = 17301505 # RGB8# 或#pixel_format.value = 17301514 # Mono8#曝光时间exposure_time = 15000 # 单位:微秒ret = camera.MV_CC_SetFloatValue(\"ExposureTime\", exposure_time)# 开始抓图ret = camera.MV_CC_StartGrabbing()if ret != 0: print(f\"开始抓图失败,错误码: {ret}\") exit()# 分配缓冲区data_buf = (c_ubyte * payload_size.value)()data_size = c_uint(payload_size.value)stFrameInfo = MV_FRAME_OUT_INFO_EX()#-----------------------------------------------运行部分---------------------------# 创建OpenCV窗口cv2.namedWindow(\"Camera\", cv2.WINDOW_NORMAL)try: while True: data_buf = (c_ubyte * payload_size.value)() ret = camera.MV_CC_GetOneFrameTimeout( byref(data_buf), payload_size.value, stFrameInfo, 1000 ) if ret == 0: #print(f\"获取到帧: 宽度={stFrameInfo.nWidth}, 高度={stFrameInfo.nHeight}, \"f\"像素格式={stFrameInfo.enPixelType}, 帧大小={stFrameInfo.nFrameLen}\") frame = np.frombuffer(data_buf, dtype=np.uint8) actual_width = stFrameInfo.nWidth actual_height = stFrameInfo.nHeight if stFrameInfo.enPixelType == 17301505: # RGB8 expected_size = actual_width * actual_height * 3 if len(frame) != expected_size: print(f\"数据大小不匹配: 期望 {expected_size}, 实际 {len(frame)}\") continue frame = frame.reshape((actual_height, actual_width, 3)) frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) elif stFrameInfo.enPixelType == 17301514: # Mono8 expected_size = actual_width * actual_height if len(frame) != expected_size: print(f\"数据大小不匹配: 期望 {expected_size}, 实际 {len(frame)}\") continue frame = frame.reshape((actual_height, actual_width)) elif stFrameInfo.enPixelType == 17301513: # 可能是 Bayer 格式 expected_size = actual_width * actual_height if len(frame) != expected_size: print(f\"数据大小不匹配: 期望 {expected_size}, 实际 {len(frame)}\") continue frame = frame.reshape((actual_height, actual_width)) frame = cv2.cvtColor(frame, cv2.COLOR_BayerGB2BGR) frame = opencv_action(frame) else: print(f\"不支持的像素格式: {stFrameInfo.enPixelType}\") break cv2.imshow(\"Camera\", frame) if cv2.waitKey(1) & 0xFF == ord(\"q\"): break else: print(f\"获取图像失败,错误码: {ret}\") breakfinally: # 停止抓图 camera.MV_CC_StopGrabbing() # 关闭设备 camera.MV_CC_CloseDevice() # 销毁句柄 camera.MV_CC_DestroyHandle() # 销毁窗口 cv2.destroyAllWindows()
其中,比较复杂的就是格式的转换。
海康SDK返回的数据类型(RGB8、Mono8、Bayer格式)转成NumPy数组。
流程:
A[SDK原始数据] --> B{像素格式判断}
B -->|RGB8| C[3通道重塑] C --> F[RGB转BGR] F --> I[OpenCV显示]
B -->|Mono8| D[单通道重塑] D --> G[灰度图] G --> I
B -->|Bayer| E[颜色插值转换] E --> H[Bayer转BGR] H --> I
运行后
=========================================================
完整代码如下:
通过网盘分享的文件:py_opencv_HK
链接:https://pan.baidu.com/s/1DmrVSV1LT9zGBCRx3nIKAQ
提取码: usii
===================================
4.花絮
不知道哪个教程教的=-=
# 创建设备句柄handle = c_void_p()stDeviceList = cast(deviceList.pDeviceInfo[0], POINTER(MV_CC_DEVICE_INFO)).contents# 创建相机实例并调用方法(关键修正点)camera = MvCamera() # 实例化 MvCamera 类#方法一:ret = camera.MV_CC_CreateHandle(stDeviceList)#报错:TypeError: MvCamera.MV_CC_GetIntValue() takes 3 positional arguments but 4 were given#方法二:#ret = MvCamera.MV_CC_CreateHandle(byref(handle), stDeviceList)#报错AttributeError: \'_ctypes.CArgObject\' object has no attribute \'handle\'#方法三:#ret = MvCamera.MV_CC_CreateHandle(byref(stDeviceList))#报错TypeError: MvCamera.MV_CC_CreateHandle() missing 1 required positional argument: \'stDevInfo\'#方法四:#ret = camera.MV_CC_OpenDevice(byref(handle),byref(stDeviceList))#报错TypeError: MvCamera.MV_CC_CreateHandle() missing 1 required positional argument: \'stDevInfo\'# 打开设备(使用已创建的句柄)ret = MvCamera.MV_CC_OpenDevice(handle)if ret != 0: print(f\"打开设备失败,错误码: {ret}\") exit()
创建
handle = c_void_p()
就疯狂报错。