最近有一个需求,要求写一个客户端实时展示多个摄像头的视频流。
界面大致设计如下:
由于我是搞Java出生的,很想用java写客户端,但是java写的窗口程序,实在是太。。。
所以,最后还是选择python+qt来完成这个任务。
使用python 3.6
要调用摄像头,首先想到使用opencv的VideoCapture组件了(还有一种方式是使用vlc,暂时不研究了)
公司摄像头是rtsp协议的流,网络资源是rtmp协议的流(这里就用网络资源)
我的大致实现思路,比较简单:
1.窗口设计6个label
2.每个摄像头定义一个线程,需要启动6个子线程
3.每个线程里获取视频流每一帧,用label展示
第一步:
使用QtDesigner设计UI:
在PyCharm中使用qt的pyuic插件生成UI类:
第二步
编写主类:
# 作者:gc
# 日期:2020-04-09 14:06
# 描述:测试主类import cv2, sys, os, threading, time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QImage, QPixmap
from form.TestCamera import Ui_Formclass TestCamera(QtWidgets.QWidget, Ui_Form):def __init__(self):super(TestCamera, self).__init__()self.setupUi(self)self.init_camera()def init_camera(self):"""初始化摄像头监控"""print("进程pid:", os.getpid())threading.Thread(target=Camera('rtmp://58.200.131.2:1935/livetv/hunantv', self.Camera1).display).start()threading.Thread(target=Camera('rtmp://58.200.131.2:1935/livetv/gxtv', self.Camera2).display).start()threading.Thread(target=Camera('rtmp://58.200.131.2:1935/livetv/gdtv', self.Camera3).display).start()threading.Thread(target=Camera('rtmp://58.200.131.2:1935/livetv/dftv', self.Camera4).display).start()threading.Thread(target=Camera('rtmp://58.200.131.2:1935/livetv/gxtv', self.Camera5).display).start()threading.Thread(target=Camera('rtmp://58.200.131.2:1935/livetv/hunantv', self.Camera6).display).start()class Camera:"""摄像头对象"""def __init__(self, url, out_label):"""初始化方法"""self.url = urlself.outLabel = out_labeldef display(self):"""显示"""cap = cv2.VideoCapture(self.url)start_time = time.time()while cap.isOpened():success, frame = ad()if success:if (time.time() - start_time) > 0.1:frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)self.outLabel.setPixmap(QPixmap.fromImage(img))cv2.waitKey(1)start_time = time.time()if __name__ == '__main__':app = QtWidgets.QApplication(sys.argv)mainWindow = TestCamera()mainWindow.show()())
说明一下为什么在display里面加入(time.time() - start_time) > 0.1条件:
最开始我是没有加这些条件的,但是程序会在运行时突然挂掉,原因是因为
frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
self.outLabel.setPixmap(QPixmap.fromImage(img))
这部分代码很费cpu的资源,我电脑性能一般,4核16线程的,同时处理6个摄像头的视频流,有点吃不消(不知道是不是这个原因,但是我加了延迟,确实是减少了我cpu的开销),所以我加了一个延迟,0.1s。
说说我个人的理解吧,做这个客户端看使用场景,如果是单摄像头实时显示,那至少我这台电脑是能够保证流处理的速度,几乎不延迟和卡顿,如果是多摄像头显示,这个客户端是放在定制终端上使用,建议还是使用带GPU的终端好点,图片处理速度更快,毕竟是GPU,如果是要求随处安装的客户端,我不知道该怎么弄才能解决CPU开销大的问题。
第三步
看看实现效果吧:
我把UI类也贴出来吧:
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'TestCamera.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Form(object):def setupUi(self, Form):Form.setObjectName("Form")size(797, 336)self.layoutWidget = QtWidgets.QWidget(Form)self.layoutWidget.setGeometry(QtCore.QRect(30, 20, 741, 292))self.layoutWidget.setObjectName("layoutWidget")idLayout = QtWidgets.QGridLayout(self.idLayout.setContentsMargins(0, 0, 0, idLayout.setObjectName("gridLayout")self.Camera1 = QtWidgets.QLabel(self.layoutWidget)self.Camera1.setMinimumSize(QtCore.QSize(241, 141))self.Camera1.setMaximumSize(QtCore.QSize(241, 141))self.Camera1.setAutoFillBackground(True)self.Camera1.setText("")self.Camera1.setScaledContents(True)self.Camera1.setObjectName("Camera1")idLayout.addWidget(self.Camera1, 0, 0, 1, 1)self.Camera2 = QtWidgets.QLabel(self.layoutWidget)self.Camera2.setMinimumSize(QtCore.QSize(241, 141))self.Camera2.setMaximumSize(QtCore.QSize(241, 141))self.Camera2.setAutoFillBackground(True)self.Camera2.setText("")self.Camera2.setScaledContents(True)self.Camera2.setObjectName("Camera2")idLayout.addWidget(self.Camera2, 0, 1, 1, 1)self.Camera3 = QtWidgets.QLabel(self.layoutWidget)self.Camera3.setMinimumSize(QtCore.QSize(241, 141))self.Camera3.setMaximumSize(QtCore.QSize(241, 141))self.Camera3.setAutoFillBackground(True)self.Camera3.setText("")self.Camera3.setScaledContents(True)self.Camera3.setObjectName("Camera3")idLayout.addWidget(self.Camera3, 0, 2, 1, 1)self.Camera4 = QtWidgets.QLabel(self.layoutWidget)self.Camera4.setMinimumSize(QtCore.QSize(241, 141))self.Camera4.setMaximumSize(QtCore.QSize(241, 141))self.Camera4.setAutoFillBackground(True)self.Camera4.setText("")self.Camera4.setScaledContents(True)self.Camera4.setObjectName("Camera4")idLayout.addWidget(self.Camera4, 1, 0, 1, 1)self.Camera5 = QtWidgets.QLabel(self.layoutWidget)self.Camera5.setMinimumSize(QtCore.QSize(241, 141))self.Camera5.setMaximumSize(QtCore.QSize(241, 141))self.Camera5.setAutoFillBackground(True)self.Camera5.setText("")self.Camera5.setScaledContents(True)self.Camera5.setObjectName("Camera5")idLayout.addWidget(self.Camera5, 1, 1, 1, 1)self.Camera6 = QtWidgets.QLabel(self.layoutWidget)self.Camera6.setMinimumSize(QtCore.QSize(241, 141))self.Camera6.setMaximumSize(QtCore.QSize(241, 141))self.Camera6.setAutoFillBackground(True)self.Camera6.setText("")self.Camera6.setScaledContents(True)self.Camera6.setObjectName("Camera6")idLayout.addWidget(self.Camera6, 1, 2, 1, anslateUi(Form)tSlotsByName(Form)def retranslateUi(self, Form):_translate = anslateForm.setWindowTitle(_translate("Form", "Form"))
本文发布于:2024-02-01 08:26:38,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170674720035232.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |