首先打开海康机器人-机器视觉-下载中心
下载最新版的 MVS
安装后打开目录找到
...\MVS\Development\Samples\Python
将MvImport内所有文件拷贝至工作目录
然后到
C:\Program Files (x86)\Common Files\MVS\Runtime
找到适合自己系统的版本,将整个文件夹拷贝至工作目录,并重命名为lib,方便后期移植
完成上述操作后,工作目录是这样的:
打开MvCameraControl_class.py 找到
由于python3.8往后的版本导入动态链接库的机制发生了改变,因此这里时常会导入失败(2025-4-5)
因此需要更改为
*动态链接库的位置在刚刚更改名字的lib文件夹内,需根据实际情况做更改*
创建一个新的py文件(我的叫HKCamera.py)用于创建相机类,方便进行相机任务
在这个新的py文件中,创建一个类,用于创建句柄、开启流等操作
class Camera:
#初始化
def __init__(self):
...
#打开相机
def _open(self):
...
#关闭相机
def _close(self):
...
#获取图像数据
def get_img(self):
...
初始化中,可以选择是否查看设备信息,并打开相机,方便取流
def __init__(self,camera_index):
"""
初始化参数
:param camera_index:相机索引,未装驱动电脑索引从0开始,装了驱动的从1开始
"""
#设备信息表初始化
self._deviceList = MV_CC_DEVICE_INFO_LIST()
#设备类型
self._tlayerType = MV_USB_DEVICE
#相机实例
self._cam = MvCamera()
#相机参数
self._stParam = None
#数据包大小
self._nPayloadSize = None
#数据流
self._data_buf = None
#相机索引
self._camera_index = camera_index
#相机型号等打印
self._Show_info = True
#获取设备信息
MvCamera.MV_CC_EnumDevices(self._tlayerType, self._deviceList)
#打印设备信息
if self._Show_info:
self._print_debug_info()
#打开相机流
self._open()
设备型号打印函数:
def _print_debug_info(self):
mvcc_dev_info = cast(self._deviceList.pDeviceInfo[self._camera_index], POINTER(MV_CC_DEVICE_INFO)).contents
if mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
print("\n设备列表: [%d]" % self._camera_index)
strModeName = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName:
if per == 0:
break
strModeName = strModeName + chr(per)
print("设备名称: %s" % strModeName)
strSerialNumber = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
if per == 0:
break
strSerialNumber = strSerialNumber + chr(per)
print("串行代号: %s" % strSerialNumber)
成功打开后会看到(先注释掉_open函数,再运行):
然后完善open函数,打开相机流
def _open(self):
"""
打开设备
:return:
"""
if int(self._camera_index) >= self._deviceList.nDeviceNum:
print("索引相机失败!")
sys.exit()
#创建相机实例
stDeviceList = cast(self._deviceList.pDeviceInfo[int(self._camera_index)], POINTER(MV_CC_DEVICE_INFO)).contents
ret = self._cam.MV_CC_CreateHandle(stDeviceList)
if ret != 0:
print("相机打开错误: 相机索引创建句柄失败! 错误码:[0x%x]" % ret)
sys.exit()
#打开设备
ret = self._cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
if ret != 0:
print("相机打开错误: 设备打开失败! 错误码:[0x%x]" % ret)
sys.exit()
ret = self._cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
if ret != 0:
print("相机打开错误: 触发模式设置失败! 错误码:[0x%x] ret[0x%x]" % ret)
sys.exit()
#获取数据包大小
self._stParam = MVCC_INTVALUE()
memset(byref(self._stParam), 0, sizeof(MVCC_INTVALUE))
ret = self._cam.MV_CC_GetIntValue("PayloadSize", self._stParam)
if ret != 0:
print("相机打开错误: 数据包大小获取失败! 错误码:[0x%x]" % ret)
sys.exit()
self._nPayloadSize = self._stParam.nCurValue
# ch:开始取流 | en:Start grab image
ret = self._cam.MV_CC_StartGrabbing()
if ret != 0:
print("取流失败: 开始取流失败! 错误码:[0x%x]" % ret)
sys.exit()
打开相机可以看作是一个流程,一个流程过完才能过下一个流程
分别是
创建相机实例 -> 打开设备 -> 获取数据包大小 -> 开始取流
然后就是get_img函数了,这个函数是获取相机图像的
将相机的图像buffer转化成opencv能够识别的图像数据
def get_img(self):
"""
获取一帧图像
:return:
"""
#创建图像信息表
stDeviceList = MV_FRAME_OUT_INFO_EX()
#初始化图像信息表
memset(byref(stDeviceList), 0, sizeof(stDeviceList))
#创建原始图像信息表
self._data_buf = (c_ubyte * self._nPayloadSize)()
#采用超时机制获取一帧图片,SDK内部等待直到有数据时返回
ret = self._cam.MV_CC_GetOneFrameTimeout(byref(self._data_buf), self._nPayloadSize, stDeviceList, 1000)
if ret == 0:
# print("get one frame: Width[%d], Height[%d], nFrameNum[%d]" % (stDeviceList.nWidth, stDeviceList.nHeight, stDeviceList.nFrameNum))
#配置图像参数
nRGBSize = stDeviceList.nWidth * stDeviceList.nHeight * 3
stConvertParam = MV_SAVE_IMAGE_PARAM_EX()
stConvertParam.nWidth = stDeviceList.nWidth
stConvertParam.nHeight = stDeviceList.nHeight
stConvertParam.pData = self._data_buf
stConvertParam.nDataLen = stDeviceList.nFrameLen
stConvertParam.enPixelType = stDeviceList.enPixelType
stConvertParam.nImageLen = stConvertParam.nDataLen
stConvertParam.nJpgQuality = 70
stConvertParam.enImageType = MV_Image_Jpeg
stConvertParam.pImageBuffer = (c_ubyte * nRGBSize)()
stConvertParam.nBufferSize = nRGBSize
# ret = cam.MV_CC_ConvertPixelType(stConvertParam)
# print(stConvertParam.nImageLen)
#覆盖上一帧图像
ret = self._cam.MV_CC_SaveImageEx2(stConvertParam)
if ret != 0:
print("convert pixel fail ! ret[0x%x]" % ret)
del self._data_buf
sys.exit()
#获取图像信息
img_buff = (c_ubyte * stConvertParam.nImageLen)()
cdll.msvcrt.memcpy(byref(img_buff), stConvertParam.pImageBuffer, stConvertParam.nImageLen)
# 将 ctypes 数组转换为 NumPy 数组
_img_array = np.frombuffer(img_buff, dtype=np.uint8)
# 使用 cv2.imdecode 解码图像
_image = cv2.imdecode(_img_array, cv2.IMREAD_COLOR)
return _image
(可选)
最后是关闭相机函数
def _close(self):
ret = self._cam.MV_CC_StopGrabbing()
if ret != 0:
print("相机关闭失败: 停止取流失败! 错误码:[0x%x]" % ret)
del self._data_buf
sys.exit()
ret = self._cam.MV_CC_CloseDevice()
if ret != 0:
print("相机关闭失败: 设别关闭失败! 错误码:[0x%x]" % ret)
del self._data_buf
sys.exit()
ret = self._cam.MV_CC_DestroyHandle()
if ret != 0:
print("相机关闭失败: 句柄销毁失败! 错误码:[0x%x]" % ret)
del self._data_buf
sys.exit()
del self._data_buf
至此相机已经可以调用并使用啦
#实例
def main():
camera = Camera(0)
while True:
img = camera.get_img()
cv2.imshow('img', img)
if cv2.waitKey(1) & 0xff == 27:
break
if __name__ == '__main__':
main()
感谢:
Python海康相机api---超简单入坑学习必看_python海康相机连接教程-CSDN博客
Python 实现海康机器人工业相机 MV-CU060-10GM 的实时显示视频流及拍照功能 - 龙凌云端 - 博客园
win11 python调用dll问题:FileNotFoundError: Could not find module ‘xxx.dll‘ (or one of its dependencies)_filenotfounderror: could not find module 'nvcuda.d-CSDN博客