python通过调用海康SDK打开工业相机(全流程)

python通过调用海康SDK打开工业相机(全流程)

首先打开海康机器人-机器视觉-下载中心

下载最新版的 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) for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName: if per == 0: break strModeName = strModeName + chr(per) print("设备名称: %s" % strModeName) 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海康相机连接教程-ZEEKLOG博客

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-ZEEKLOG博客

Read more

【C/C++】Linux epoll详解与实战

Linux epoll 详解与实战 一、什么是 epoll epoll 是 Linux 内核提供的高性能 I/O 事件通知机制(I/O event notification facility),专门用于监控大量文件描述符上的事件。它是 select 和 poll 的改进版本,解决了它们在处理大量并发连接时的性能瓶颈,是现代 Linux 高并发服务器的基石。 I/O 多路复用的演进 在理解 epoll 之前,我们需要了解 I/O 多路复用的背景。传统的阻塞 I/O 模型中,每个连接需要一个线程来处理,当并发连接数达到数万甚至数十万时,线程切换的开销会变得不可接受。I/O 多路复用允许单个线程同时监控多个文件描述符,当任何一个文件描述符就绪时,程序得到通知并进行处理。

By Ne0inhk

C++七级GESP所有知识点超详细指南

论文的主要内容如下: * GESP C++七级考试概述:介绍考试的基本情况、考核目标和能力要求,使用列表说明考试形式和时间分配。 * 数学库函数的高级应用:详细介绍三角函数、对数函数和指数函数的使用方法和应用场景,包含代码示例和表格对比。 * 复杂动态规划算法精解:分析二维动态规划、经典问题模型和优化技巧,通过实例讲解状态定义和转移方程。 * 图论算法的深入解析:阐述图的基本概念、遍历算法、最短路径算法和实际应用,包含多种存储结构的对比。 * 哈希表的原理与应用:讲解哈希表的工作原理、冲突解决方法和在C++中的实际应用,提供性能分析表格。 C++七级GESP所有知识点超详细指南 1 引言 1.1 GESP C++七级考试概述 GESP(Grade Examination of Software Programming)C++七级考试是中国计算机学会推出的软件编程能力等级认证中的高级别考试,旨在评估考生对C++编程语言和算法设计的深入理解以及实际应用能力。该考试面向已经掌握C++基础语法和常用数据结构,并希望进一步学习高级算法和复杂程序设计的学习者。通过七级考试的

By Ne0inhk
C++新手入门学习教程(完整版)

C++新手入门学习教程(完整版)

以下教程覆盖了 C++ 学习的各个方面,适合初学者循序渐进地学习。学习过程中,建议初学者多做练习和项目,以加深对理论知识的理解。希望这个教程能为你提供一个清晰的学习路径。 目录 第一章:C++ 简介 1.1 C++ 的历史与演变 1.2 C++ 的特点和优势 1.3 C++ 的应用领域 1.4 C++ 的未来展望 第二章:环境搭建 2.1 安装 C++ 编译器与 IDE Windows Linux Mac 2.2 配置开发环境 2.3 编译与运行示例程序 第三章:基本语法 3.1 C+

By Ne0inhk
C++幻象:内存序、可见性与指令重排

C++幻象:内存序、可见性与指令重排

C++ 井发的假象:内存序、可见性与指令重排 写在前面:当你第一次把 std::atomic、memory_order 这些词读到手软时,可能会觉得这是 OS 或硬件工程师的专属领域。但其实理解内存模型并不需要掌握每一条 CPU 手册的汇编,只要抓住核心概念与工程实践,你就能写出既高效又安全的并发代码。 本文面向有一定 C++ 并发基础的读者(知道线程、互斥量、基本的 std::atomic 用法),但想把“为什么这样”弄清楚。我们会从 std::atomic 的语义出发,讲清 CPU cache coherence、内存屏障(fence)、指令重排 和 happens-before 的关系——不是空洞的定义,而是大量实战例子、容易踩的坑和调试技巧。文风尽量自然、通俗,

By Ne0inhk