此前写了一篇基于C++开发海康威视相机的博客,貌似看的人还挺多,收藏量比较高,但其实当时就知道其实海康威视相机还可以使用python开发,但当时python水平不高,也没有深入了解,趁此机会,好好总结一下用python开发的一些要点。
上面的前期教程在资料查找部分已经讲得很清楚了,这里就不再赘述。重点看一下官方提供python例程:
这个路径下,只有MvImport文件夹是需要导入的库文件,其他的都是某个功能对应的例程,前面两个BasicDemo
是比较完善的例程,有图形界面。
先随便找一个例程看看:
重点是红框中的内容,可以看到这个例程其实包含了MvCameraControl_class
这个包,而这个包是在上面提到的MvImport
文件夹下,所以在import前要先用append包含进这个路径。
但是这样使用会存在一个问题,那就是如果在VS Code中开发,这样是不能通过静态检查的,也就没有了代码提示,用起来很不方便;而且从源码交互方面来说,这样要求运行这个代码的必须要有MVS环境,这个是很不优雅的。所以建议将MvImport文件夹复制到项目目录下,然后以from MvImport.MvCameraControl_class import *
这样的形式来导入包,这样不仅不再需要append路径操作,而且静态检查也能通过,代码提示也有了。
再来看看MvImport文件夹下的文件:
这里需要注意的是,如果将MvImport文件夹放到项目目录下,那么该目录下的文件在import同文件夹脚本时,要注意不能使用本文件的相对路径,而要使用项目的相对路径!! 这样才能静态检查通过。
另外还有这个导入的dll文件,使用的是绝对路径,感觉不够优雅,而且可移植性不强,还是建议将dll文件复制到项目目录下,但是这里需要注意的是,这里实际调用的dll文件不止这一个,所以还是把整个文件夹都复制进去,所以最后项目的整体结构如下:
project_direction:
|-- project.py
|-- ........
|-- MvImport
| |-- CameraParams_const.py
| |-- CameraParams_header.py
| |-- MvCameraControl_class.py
| |-- MvErrorDefine_const.py
| |-- PixelType_header.py
| |-- Win64_x64
| | |-- MvCameraControl.dll
| | |-- .......
然后在导入包时,所有的脚本均以项目目录为起点,以相对路径的形式导入包,这样不仅对静态检查有利,对后续导出执行程序也有很大帮助。
按照上面的步骤,配好了项目结构,接下来就是编程了。由于官方给的代码注释比较全面,这里就不再赘述了,主要是搞清楚相机的运行流程,然后按照官方给的例程和手册一步一步来就问题不大。
这里记录一个在使用过程中遇到的问题,那就是取图部分。根据官方的手册,取图主要有两种方式,如下图所示:
分别是 MV_CC_GetOneFrameTimeout()
和 MV_CC_GetImageBuffer()
这两种方式,根据官网提供的文档,使用后者的效率更高,但是问题在于官方提供的python 例程当中,
_MV_FRAME_OUT_
这个结构体下pBufAddr
数据类型错了,这种表示方法使得该变量只有一个unsigned char
类型,应该还需要乘上该字节的长度,但是由于相机的分辨率是可以自定义的,且不同相机型号分辨率不同,因此这里才没有设置乘数为多少。
总之因为这个原因,如果使用 MV_CC_GetImageBuffer()
这个函数来读取图像数据,只能得到一个字节,其实也就是空值。所以这里才使用MV_CC_GetOneFrameTimeout()
这种方式来读取图像数据,或者修改上面的代码,但这样牵一发动全身,不好掌握。
而且官方给出的BasicDemo例程也是基于MV_CC_GetOneFrameTimeout()
来取图,所以这里建议优先采用后者,具体的使用方式建议参考BasicDemo例程。
参考链接
//更新:
貌似使用MV_CC_GetImageBuffer()
也是可以正常取图的,需要使用ctypes这个包里面的一些操作,可以参考这个链接。
使用网口转USB模块连接到电脑无法识别设备:
需要明确的是,网口转USB相当于是一个有线网卡,没有连接到互联网,也就不具有DHCP功能,因此需要手动给这个网卡分配一个IP地址,这个IP地址在相机看来就是电脑的IP地址,这样相机就能正常找到电脑,即电脑也能找到相机了,另外,二者的IP最好在同一网段,即第三位相同。
MVS中识别到相机,但运行Python程序没有识别到,报错no data, ret = 80000007
:
这可能是因为防火墙的原因,不妨切换一下所连接WiFi的属性,比如公用还是专用(原来公用的换成专用,原来专用的换成公用):
总之最后保证python.exe公用和专用防火墙都允许,如下图所示:
参考链接
在开发过程中,使用到很多比较“底层”的包,有点新奇,这里附上一些学习链接。
msvcrt
:输入交互,参考链接threading
:多线程
ctypes
:架起c/c++和python之间的桥梁