记录PyQt5 开发(一)QCamera

最近在帮导师做一个项目,需求要用Python做一个桌面软件。如果做正式项目用tk肯定是不行的,所以第一个想到的就是PyQt5

这是我做了两个月后,才知道,PyQt其实并不是Qt的官方Python支持。官方的Qt for python是PySide2,这两者在我使用上主要是Signal(信号槽)部分不太一样,PySide2用的是和C++ Qt相似的语法结构,而PyQt则用了自己的pyqtSignal,其他部分两家都继承了C++的接口,区别不是很大。

项目要用到摄像头视频监控,一开始我就想到了用QCamera,但怎么都开启不了(可能是太菜了)后面进度在催,没办法用了第二种方案,OpenCV的cv2.Videocapture()。这下好了,给我整的生活不能自理,不知道cv2 Videocapture这个库到底是怎么实现的,bug一堆不说,运行起来还各种闪退,不稳定。最后不得不用了Capture Thread+ Fetch Thread的方案,即一个线程不停地去抓取摄像头的数据帧,另一个线程和主线程沟通,才勉强维持稳定(中间还用了一堆Mutex同步线程,头发都要掉光)。

但后来发现,这样做资源开销大的离谱。尤其是当我们项目用到了4K分辨率的摄像头时,主线程基本卡死不能动了(光一个摄像头就占用了8核CPU的40%,这还是4GHz x86的CPU啊)项目还要用四个摄像头,这要跑起来难道得用服务器?

痛定思痛,就算cv2的解决方案维护了两个月,也只能放弃,转头认真研究QCamera。

QCamera是Qt对于摄像设备的一个抽象,所以它首先初始化需要锁定一个摄像头。这就需要QCameraInfo类提供系统中可用摄像头的信息。

const QList cameras =QCameraInfo::availableCameras();

for (const QCameraInfo&cameraInfo : cameras) qDebug() << cameraInfo.deviceName();

然后,初始化QCamera。

下面,要给QCamera找一个视频输出的区域QCameraViewFinder。QCamera支持QVideoWidget,QGraphicsVideoItem,QAbstractVideoSurface三种接口,感兴趣的小伙伴可以去了解一下区别。这三种在QtDesigner里都找不到,没关系,我们可以在界面里先预留一个QGridLayout,用来动态添加view。

接下来,就是保存图片了。QCamera需要拍摄图片,用的是QCameraImageCapture类。这个类初始化用QCamera对象作为参数,然后就可以进行capture操作。但是capture必须写入硬盘(我也不知道为什么,但是如果需要高性能或者快速拍摄,这个肯定行不通,因为写入硬盘是非常非常缓慢的,甚至需要界面中添加等待提示,因为我们摄像头4K拍出来有10MB,保存要十几秒,这也是我认为Qt做的不够好的地方,为什么不能加一个capture到QImage的接口)但是好在项目刚好需要保存在本地。

这里有一个细节,因为capture()写入硬盘和其他线程是异步的,你不能capture()完了立马cam.stop(),否则会capture失败。所以我加了个简单的计数判断,达到finish计数才stop。这个后面可以再改进。

    到这里QCamera用法基本上就结束了,可以看到Qt5虽然也有不足,但比起cv2.Videocapture还是做的好不少,Cpu占用率也下来了。

你可能感兴趣的:(记录PyQt5 开发(一)QCamera)