Python OpenCV 调用海康威视工业相机
介绍使用 Python 结合 OpenCV 调用海康威视工业相机的完整流程。首先准备海康 MVS 软件及 SDK,参考官方示例搭建基础环境。接着通过 MvCamera 类初始化设备、枚举相机并打开句柄。核心步骤在于获取图像数据后,根据像素格式(RGB8、Mono8、Bayer)将原始字节流转换为 NumPy 数组,并利用 OpenCV 进行显示和处理。文中还包含常见报错处理,如创建句柄时的参数传递问题,确保代码可运行。

介绍使用 Python 结合 OpenCV 调用海康威视工业相机的完整流程。首先准备海康 MVS 软件及 SDK,参考官方示例搭建基础环境。接着通过 MvCamera 类初始化设备、枚举相机并打开句柄。核心步骤在于获取图像数据后,根据像素格式(RGB8、Mono8、Bayer)将原始字节流转换为 NumPy 数组,并利用 OpenCV 进行显示和处理。文中还包含常见报错处理,如创建句柄时的参数传递问题,确保代码可运行。

准备一台海康威视工业相机。
下载 MVS 软件及 SDK: 海康机器人 - 机器视觉 - 下载中心
MVS 安装路径下包含 Python 示例,但部分未集成 OpenCV。
打开安装目录下的 Samples 文件夹:
D:\soft\MVS\MVS\Development\Samples\Python\BasicDemo
D:\soft\MVS\MVS\Development\Samples\Python\MvImport
复制 BasicDemo.py 到新建项目文件夹中。若缺少依赖,需安装 PyQt5:
pip install PyQt5 -i https://pypi.tuna.tsinghua.edu.cn/simple
运行后可成功输出画面。
创建新文件夹并编写脚本,整合 MVS SDK 与 OpenCV。
完整代码如下:
import cv2
import numpy as np
from ctypes import cast, POINTER, c_ubyte, c_uint, c_void_p
from 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_DEVICE
ret = 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)).contents
camera = 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.nCurValue
print(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()
# ----------------------------------------------- 运行部分 ---------------------------
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:
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:
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:
continue
frame = frame.reshape((actual_height, actual_width))
elif stFrameInfo.enPixelType == 17301513: # Bayer
expected_size = actual_width * actual_height
if len(frame) != expected_size:
continue
frame = frame.reshape((actual_height, actual_width))
frame = cv2.cvtColor(frame, cv2.COLOR_BayerGB2BGR)
else:
print(f"不支持的像素格式:{stFrameInfo.enPixelType}")
break
frame = opencv_action(frame)
cv2.imshow("Camera", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
print(f"获取图像失败,错误码:{ret}")
break
finally:
# 停止抓图
camera.MV_CC_StopGrabbing()
# 关闭设备
camera.MV_CC_CloseDevice()
# 销毁句柄
camera.MV_CC_DestroyHandle()
# 销毁窗口
cv2.destroyAllWindows()
核心难点在于数据格式转换。海康 SDK 返回原始字节流,需根据像素类型判断并重塑为 NumPy 数组,再经 OpenCV 转换显示。
流程说明:
在创建设备句柄时,常见报错及修正方法如下:
错误现象:
调用 MV_CC_CreateHandle 时报错 TypeError 或 AttributeError。
正确做法:
MvCamera 类。cast 获取设备信息指针。handle = c_void_p()
stDeviceList = cast(deviceList.pDeviceInfo[0], POINTER(MV_CC_DEVICE_INFO)).contents
camera = MvCamera()
# 创建相机实例并调用方法
ret = camera.MV_CC_CreateHandle(stDeviceList)
if ret != 0:
print("创建句柄失败")
exit()
# 打开设备(使用已创建的句柄)
ret = camera.MV_CC_OpenDevice()
if ret != 0:
print(f"打开设备失败,错误码:{ret}")
exit()
避免直接传递 byref(handle) 给 CreateHandle 导致参数不匹配。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online