Python开发多路显示USB摄像头

利用Python开发多路显示USB摄像头

1、项目介绍

  • 这是一个用来测试多个USB摄像头同时打开、拍照保存图像的小工具

1.1 开发环境:

python3.6.5
pycharm2018专业版
PyQt5 5.6
opencv-python
QT Designer

1.2 硬件准备:

  • 3~4个USB摄像头

1.3 新建项目文件夹:

确认pycharm已经配置好tools环境,方便打开QT设计师工具

目录结构:

在这里插入图片描述

2、设计界面布局和按钮功能

  • 利用pycharm打开QT Designer设计工具的界面布局,设计结果如下图。

在这里插入图片描述

回到pycharm中,利用pyuic将刚刚设计好的界面UI文件,生成对应的UI文件代码。

  • 下面是生成好的UI文件代码,保存的时候修改模块名称:如multiplexer_camera.py,运行如上图所示。
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(700, 500)
        Form.setMinimumSize(QtCore.QSize(700, 500))
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout.setContentsMargins(5, 5, 5, 5)
        self.verticalLayout.setObjectName("verticalLayout")
        self.widget_3 = QtWidgets.QWidget(Form)
        self.widget_3.setMaximumSize(QtCore.QSize(16777215, 46))
        self.widget_3.setObjectName("widget_3")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget_3)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.pushButton = QtWidgets.QPushButton(self.widget_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton.sizePolicy().hasHeightForWidth())
        self.pushButton.setSizePolicy(sizePolicy)
        self.pushButton.setMinimumSize(QtCore.QSize(130, 0))
        self.pushButton.setMaximumSize(QtCore.QSize(150, 16777215))
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.pushButton_2 = QtWidgets.QPushButton(self.widget_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton_2.sizePolicy().hasHeightForWidth())
        self.pushButton_2.setSizePolicy(sizePolicy)
        self.pushButton_2.setMinimumSize(QtCore.QSize(130, 0))
        self.pushButton_2.setMaximumSize(QtCore.QSize(150, 16777215))
        self.pushButton_2.setObjectName("pushButton_2")
        self.horizontalLayout.addWidget(self.pushButton_2)
        self.pushButton_4 = QtWidgets.QPushButton(self.widget_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton_4.sizePolicy().hasHeightForWidth())
        self.pushButton_4.setSizePolicy(sizePolicy)
        self.pushButton_4.setMinimumSize(QtCore.QSize(130, 0))
        self.pushButton_4.setObjectName("pushButton_4")
        self.horizontalLayout.addWidget(self.pushButton_4)
        self.pushButton_3 = QtWidgets.QPushButton(self.widget_3)
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.pushButton_3.sizePolicy().hasHeightForWidth())
        self.pushButton_3.setSizePolicy(sizePolicy)
        self.pushButton_3.setMinimumSize(QtCore.QSize(130, 0))
        self.pushButton_3.setMaximumSize(QtCore.QSize(150, 16777215))
        self.pushButton_3.setObjectName("pushButton_3")
        self.horizontalLayout.addWidget(self.pushButton_3)
        self.verticalLayout.addWidget(self.widget_3)
        self.widget = QtWidgets.QWidget(Form)
        self.widget.setStyleSheet("background-color: rgb(194, 255, 250);")
        self.widget.setObjectName("widget")
        self.gridLayout = QtWidgets.QGridLayout(self.widget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setSpacing(5)
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout_3 = QtWidgets.QGridLayout()
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.label_2 = QtWidgets.QLabel(self.widget)
        self.label_2.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_2.setStyleSheet("background-color: rgb(255, 255, 127);")
        self.label_2.setAlignment(QtCore.Qt.AlignCenter)
        self.label_2.setObjectName("label_2")
        self.gridLayout_3.addWidget(self.label_2, 0, 0, 1, 1)
        self.show_video2 = QtWidgets.QLabel(self.widget)
        self.show_video2.setStyleSheet("background-color: rgb(170, 170, 255);")
        self.show_video2.setAlignment(QtCore.Qt.AlignCenter)
        self.show_video2.setObjectName("show_video2")
        self.gridLayout_3.addWidget(self.show_video2, 1, 0, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_3, 0, 1, 1, 1)
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.show_video1 = QtWidgets.QLabel(self.widget)
        self.show_video1.setStyleSheet("background-color: rgb(170, 170, 255);")
        self.show_video1.setAlignment(QtCore.Qt.AlignCenter)
        self.show_video1.setObjectName("show_video1")
        self.gridLayout_2.addWidget(self.show_video1, 2, 0, 1, 1)
        self.label = QtWidgets.QLabel(self.widget)
        self.label.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label.setStyleSheet("background-color: rgb(255, 255, 127);")
        self.label.setAlignment(QtCore.Qt.AlignCenter)
        self.label.setObjectName("label")
        self.gridLayout_2.addWidget(self.label, 0, 0, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_2, 0, 0, 1, 1)
        self.gridLayout_6 = QtWidgets.QGridLayout()
        self.gridLayout_6.setObjectName("gridLayout_6")
        self.label_8 = QtWidgets.QLabel(self.widget)
        self.label_8.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_8.setStyleSheet("background-color: rgb(255, 255, 127);")
        self.label_8.setAlignment(QtCore.Qt.AlignCenter)
        self.label_8.setObjectName("label_8")
        self.gridLayout_6.addWidget(self.label_8, 0, 0, 1, 1)
        self.show_video3 = QtWidgets.QLabel(self.widget)
        self.show_video3.setStyleSheet("background-color: rgb(170, 170, 255);")
        self.show_video3.setAlignment(QtCore.Qt.AlignCenter)
        self.show_video3.setObjectName("show_video3")
        self.gridLayout_6.addWidget(self.show_video3, 1, 0, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_6, 1, 0, 1, 1)
        self.gridLayout_7 = QtWidgets.QGridLayout()
        self.gridLayout_7.setObjectName("gridLayout_7")
        self.label_9 = QtWidgets.QLabel(self.widget)
        self.label_9.setMaximumSize(QtCore.QSize(16777215, 20))
        self.label_9.setStyleSheet("background-color: rgb(255, 255, 127);")
        self.label_9.setAlignment(QtCore.Qt.AlignCenter)
        self.label_9.setObjectName("label_9")
        self.gridLayout_7.addWidget(self.label_9, 0, 0, 1, 1)
        self.show_video4 = QtWidgets.QLabel(self.widget)
        self.show_video4.setStyleSheet("background-color: rgb(170, 170, 255);")
        self.show_video4.setAlignment(QtCore.Qt.AlignCenter)
        self.show_video4.setObjectName("show_video4")
        self.gridLayout_7.addWidget(self.show_video4, 1, 0, 1, 1)
        self.gridLayout.addLayout(self.gridLayout_7, 1, 1, 1, 1)
        self.verticalLayout.addWidget(self.widget)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "显示多路USB摄像头"))
        self.pushButton.setText(_translate("Form", "显示摄像头图像"))
        self.pushButton_2.setText(_translate("Form", "保存图片"))
        self.pushButton_4.setText(_translate("Form", "暂停播放"))
        self.pushButton_3.setText(_translate("Form", "退出程序"))
        self.label_2.setText(_translate("Form", "摄像头②"))
        self.show_video2.setText(_translate("Form", "显示图像②"))
        self.show_video1.setText(_translate("Form", "显示图像①"))
        self.label.setText(_translate("Form", "摄像头①"))
        self.label_8.setText(_translate("Form", "摄像头③"))
        self.show_video3.setText(_translate("Form", "显示图像③"))
        self.label_9.setText(_translate("Form", "摄像头④"))
        self.show_video4.setText(_translate("Form", "显示图像④"))


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Form = QtWidgets.QWidget()
    ui = Ui_Form()
    ui.setupUi(Form)
    Form.show()
    sys.exit(app.exec_())
  • 界面设计完毕后,新建一个py文件multiplexer_main.py,导入UI模块的界面类并继承,开始编写按钮触发

事件函数代码,完整代码如下。

#!/usr/bin/python
# -*- coding:utf-8 -*-
# Author:凌云剑圣
# datetime:20210919
from PyQt5.Qt import *
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QApplication
import sys
from multiplexer_camera import Ui_Form
import cv2 as cv


class ShowImage:

    def __init__(self, camera_object, show_label_object):
        self.camera_object = camera_object
        self.show_label_object = show_label_object
        self.frame = []  # 存图片
        self.detectFlag = False  # 检测flag
        self.cap = []
        self.timer_camera = QTimer()  # 定义定时器

    def open_file(self):
        """代开文件"""
        # print('打开文件')
        self.cap = cv.VideoCapture(self.camera_object, cv.CAP_DSHOW)
        self.timer_camera.start(100)
        self.timer_camera.timeout.connect(self.open_frame)

    def open_frame(self):
        if (self.cap.isOpened()):
            self.detectFlag = True
            ret, self.frame = self.cap.read()
            self.read_video(ret, self.frame)

    def read_video(self, ret, frame):
        if ret:
            src = cv.flip(frame, 1)  # 摄像头镜像翻转
            frame = cv.cvtColor(src, cv.COLOR_BGR2RGB)
            height, width, bytesPerComponent = frame.shape
            bytesPerLine = bytesPerComponent * width
            q_image = QImage(frame.data, width, height, bytesPerLine,
                             QImage.Format_RGB888).scaled(self.show_label_object.width(),
                                                          self.show_label_object.height())
            self.show_label_object.setPixmap(QPixmap.fromImage(q_image))

        else:
            self.cap.release()
            self.timer_camera.stop()  # 停止计时器

    def stop_video(self):
        """停止视频"""
        # print('play_video')
        if self.cap != []:
            self.cap.release()
            self.timer_camera.stop()  # 停止计时器
            self.detectFlag = False
            self.show_label_object.setText("该通道已停播~\\(^o^)/~")
            self.show_label_object.setStyleSheet("QLabel{background:pink;}"
                                                 "QLabel{color:rgb(100,100,100);"
                                                 "font-size:15px;font-weight:bold;"
                                                 "font-family:宋体;}")
        else:
            # QMessageBox.warning(self, "Warming", "Push the left upper corner button to Quit.",
            #                               QMessageBox.Yes)
            pass

    def save_image(self):
        # src = cv.flip(self.frame, 1)  # 摄像头镜像翻转
        cv.imwrite("./camera_%s.png" % str(int(self.camera_object) + 1), self.frame)  # 保存图像


class Window(QWidget, Ui_Form):

    def __init__(self):
        super().__init__()
        icon = './15.png'
        self.setWindowIcon(QIcon(icon))
        self.setupUi(self)
        self.save_path = None
        self.video_obj = []

    def open_camera(self):
        for i in range(self.video_spinBox.value()):
            self.video_obj.append(ShowImage(i, getattr(self, "show_video%s" % int(i+1))))
        return self.video_obj

    def on_click(self):
        self.pushButton.clicked.connect(self.show_multiplexer_video)
        self.pushButton_2.clicked.connect(self.save_multiplexer_image)
        self.pushButton_3.clicked.connect(self.quit_obj)
        self.pushButton_4.clicked.connect(self.stop_video)

    def show_multiplexer_video(self):
        """
        显示多路USB摄像头图像
        :return:
        """
        try:
            for i in self.open_camera():
                i.open_file()
        except Exception as e:
            print(e)

    def save_multiplexer_image(self):
        """
        保存多路摄像头图像
        :return:
        """
        try:
            for i in self.video_obj:
                if i.detectFlag:
                    i.save_image()
        except Exception as e:
            print(e)

    def stop_video(self):
        """ stop"""
        try:
            for i in self.video_obj:
                if i.detectFlag:
                    i.stop_video()
        except Exception as e:
            print(e)

    def quit_obj(self):
        # print('88')
        quit()
        

# 在被其他文档调用时,下面的代码不会被执行
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    window.on_click()
    sys.exit(app.exec_())
完成以上步骤,运行multiplexer_main.py文件,运行后,结果如UI设计界面所示,可见即可得。

3、测试工具

  • 插上开始时准备好的USB摄像头,运行multiplexer_main.py文件,测试各功能。不出意外,完美运行。如图:

在这里插入图片描述

项目到处结束,要打包成exe文件的小伙伴自己动手哟。如果懒得动手,请点击以下链接:

exe文件下载路径

项目总结:

这个小工具做出来还是比较实用的,考验pyqt5和OpenCV的应用以及QT Designer布局管理的应用,希望能帮助到小伙伴们,感谢你的预览,祝你生活愉快,天天开心。

  • 5
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值