基于Python的双USB摄像头实时预览保存软件

基于PyQt5,opencv,实现双usb外接摄像头拍摄存储
双摄像头支持单独开启关闭,实时预览视频,单独/同时保存预览视频图片
多线程模式,支持掉线重连(有点bug,因无法绑定设备id,画面会出现错乱,当两个摄像头全部重连成功后画面顺序恢复正常)

# !/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@author  : [email protected]
@des     :主要逻辑,默认拍摄照片存储路径为./img_save

"""
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtCore import QTimer
from PyQt5.QtGui import QPixmap, QImage
import os
from PyQt5.QtWidgets import QMessageBox
from gui.ui import untitled
import cv2 as cv
from threading import Thread


class Close():
    def __init__(self):
        pass
    # 窗口关闭按钮事件

    def closeEvent(self, event):
        """Shuts down application on close."""
        reply = QMessageBox.question(self, '警告', '窗口关闭后,将终止本次运行',
                                     QMessageBox.Yes | QMessageBox.No, QMessageBox.No)

        if reply == QMessageBox.Yes:
            event.accept()
            os._exit(0)
        else:
            event.ignore()


class Untitled(QtWidgets.QWidget, Close):
    single_show_video_label1 = QtCore.pyqtSignal()
    single_show_video_label_2 = QtCore.pyqtSignal()
    single_show_warning = QtCore.pyqtSignal(str)
    single_show_warning_close = QtCore.pyqtSignal(str)

    def __init__(self):
        # 还有这里
        QtWidgets.QStackedWidget.__init__(self)
        self.ui = untitled.Ui_Form()
        self.ui.setupUi(self)

        self.status_pushbutton_all = False
        self.status_pushbutton1 = False
        self.status_pushbutton_2 = False

        self.single_show_video1 = False
        self.single_show_video_2 = False

        self.t1 = ""
        self.t2 = ""

        self.video_img1 = ""
        self.video_img2 = ""

        self.video_save1 = ""
        self.video_save2 = ""

        self.img_save_num = 0
        self.save_path = R"./img_save"
        os.makedirs(self.save_path, exist_ok=True)

        self._init_view()
        self._init_slot()
        self._init_timer()

    def _init_timer(self):
        self.timer_camera1 = QTimer()
        self.timer_camera2 = QTimer()

    def _init_view(self):
        self.ui.label1.setFixedSize(500, 500)
        self.ui.label_2.setFixedSize(500, 500)
        self.ui.label1.clear()
        self.ui.label_2.clear()
        self.ui.lineEdit1.setText("摄像头一")
        self.ui.lineEdit_2.setText("摄像头二")
        self.ui.pushButton1.setText("开启摄像头一")
        self.ui.pushButton_2.setText("开启摄像头二")
        self.ui.pushButton_all.setDisabled(True)
        self.ui.pushButton_all.setText("存储图像")

    def view_pushbutton_all(self):
        if self.status_pushbutton_all:
            self.ui.pushButton_all.setDisabled(False)
        else:
            self.ui.pushButton_all.setDisabled(True)
        # self.ui.pushButton_all.setText("存储图像")

    def save_image(self):
        """

        :return:
        """
        if self.video_img1 != "":
            save_img_file = os.path.join(
                self.save_path, "front_{}.png".format(
                    self.img_save_num))
            cv.imwrite(save_img_file, self.video_save1)
            print("{}保存成功".format(save_img_file))
        if self.video_img2 != "":
            save_img_file = os.path.join(
                self.save_path, "back_{}.png".format(
                    self.img_save_num))
            cv.imwrite(save_img_file, self.video_save2)
            print("{}保存成功".format(save_img_file))
        else:
            pass

    def view_pushbutton_2(self):
        if self.status_pushbutton_2:
            self.ui.pushButton_2.setText("结束摄像头二")
            self.ui.pushButton_2.clicked.disconnect(self.slot_pushbutton_2)
            self.ui.pushButton_2.clicked.connect(self.slot_finish_pushButton_2)
            if self.t2 == "":
                self.t2 = Thread(target=self.show_camera2)
                self.t2.start()

            else:
                pass
            self.single_show_video_2 = True
        else:
            self.ui.pushButton_2.setText("开启摄像头二")
            self.ui.pushButton_2.clicked.disconnect(
                self.slot_finish_pushButton_2)
            self.ui.pushButton_2.clicked.connect(self.slot_pushbutton_2)
            # self.t2.join()
            self.single_show_video_2 = False

    def view_pushbutton1(self):
        if self.status_pushbutton1:
            self.ui.pushButton1.setText("结束摄像头一")
            self.ui.pushButton1.clicked.disconnect(self.slot_pushbutton1)
            self.ui.pushButton1.clicked.connect(self.slot_finish_pushButton1)
            if self.t1 == "":
                try:
                    self.t1 = Thread(target=self.show_camera1)
                    self.t1.start()
                except Exception as e:
                    print(e)
                    self.show_warning(msg="摄像头1启动失败/断开连接")
            else:
                pass
            self.single_show_video1 = True
        else:
            self.ui.pushButton1.setText("开启摄像头一")
            self.ui.pushButton1.clicked.disconnect(
                self.slot_finish_pushButton1)
            self.ui.pushButton1.clicked.connect(self.slot_pushbutton1)
            # self.t1.join()
            self.single_show_video1 = False

    def show_camera1(self):
        """

        :return:
        """
        camear_start_single1 = False
        def start_camera1():
            cap = cv.VideoCapture(2)
            while cap.isOpened():
                ret, frame = cap.read()
                image = cv.cvtColor(frame, cv.COLOR_RGB2BGR)
                video_img = QImage(
                    image.data,
                    image.shape[1],
                    image.shape[0],
                    QImage.Format_RGB888)
                self.video_save1 = frame
                self.video_img1 = video_img
                if self.single_show_video1:
                    self.single_show_video_label1.emit()
                else:
                    self.video_img1 = ""
                    self.video_save1 = ""
                # if self.status_pushbutton1 == False:
                #     break
            cap.release()
            raise Exception("摄像头未成功连接")

        retry_times = 3
        while not camear_start_single1 and retry_times > 0:
            try:
                start_camera1()
                camear_start_single = True
            except Exception as e:
                print(e)
                # self.single_show_warning.emit("摄像头1启动失败/断开连接,点击确定开始尝试重新连接")
                self.video_img1 = ""
                self.video_save1 = ""
                retry_times -= 1
        # self.single_show_warning.emit("多次重连失败,点击确定关闭程序,重启解决此问题")
        self.single_show_warning_close.emit("多次重连摄像头1失败,点击确定关闭程序,重启解决此问题")


    def show_camera2(self):
        camear_start_single2 = False

        def start_camera2():
            cap = cv.VideoCapture(1)
            while cap.isOpened():
                ret, frame = cap.read()
                image = cv.cvtColor(frame, cv.COLOR_RGB2BGR)
                video_img = QImage(
                    image.data,
                    image.shape[1],
                    image.shape[0],
                    QImage.Format_RGB888)
                self.video_save2 = frame
                self.video_img2 = video_img

                if self.single_show_video_2:
                    self.single_show_video_label_2.emit()
                else:
                    self.video_img2 = ""
                    self.video_save2 = ""
                # if self.status_pushbutton_2 == False:
                #     break
            cap.release()

        retry_times = 3
        while not camear_start_single2 and retry_times>0:
            try:
                start_camera2()
                camear_start_single2 = True
            except Exception as e:
                print("e",e)
                # self.single_show_warning.emit("摄像头2启动失败/断开连接,点击确定开始尝试重新连接")
                # start_camera2()
                self.video_img2 = ""
                self.video_save2 = ""
                retry_times -= 1
        self.single_show_warning_close.emit("多次重连摄像头2失败,点击确定关闭程序,重启解决此问题")



    def show_video_label1(self):
        """

        :return:
        """
        self.ui.label1.setPixmap(QPixmap(self.video_img1))

    def show_video_label_2(self):
        """

        :return:
        """
        self.ui.label_2.setPixmap(QPixmap(self.video_img2))

    def slot_finish_pushButton1(self):
        """

        :return:
        """
        self.status_pushbutton1 = False
        self.view_pushbutton1()
        self.check_status_pushbutton_all()

    def check_status_pushbutton_all(self):
        if self.status_pushbutton1 or self.status_pushbutton_2:
            self.status_pushbutton_all = True
        else:
            self.status_pushbutton_all = False
        self.view_pushbutton_all()

    def slot_finish_pushButton_2(self):
        """

        :return:
        """
        self.status_pushbutton_2 = False
        self.view_pushbutton_2()
        self.check_status_pushbutton_all()

    def _init_slot(self):
        self.ui.pushButton1.clicked.connect(self.slot_pushbutton1)
        self.ui.pushButton_2.clicked.connect(self.slot_pushbutton_2)
        self.ui.pushButton_all.clicked.connect(self.slot_pushbutton_all)

        self.single_show_video_label1.connect(self.show_video_label1)
        self.single_show_video_label_2.connect(self.show_video_label_2)
        self.single_show_warning.connect(self.show_warning)
        self.single_show_warning_close.connect(self.show_warning_close)

    def slot_pushbutton1(self):
        """

        :return:
        """
        self.status_pushbutton1 = True
        self.view_pushbutton1()
        self.check_status_pushbutton_all()

    def slot_pushbutton_2(self):
        """

        :return:
        """
        self.status_pushbutton_2 = True
        self.view_pushbutton_2()
        self.check_status_pushbutton_all()

    def slot_pushbutton_all(self):
        """

        :return:
        """
        self.status_pushbutton_all = True
        try:
            self.img_save_num += 1
            t_save = Thread(target=self.save_image)
            t_save.start()
            t_save.join()
        except Exception as e:
            print(e)
            self.single_show_warning.emit("图片保存失败")
        self.view_pushbutton_all()

    def show_warning(self,msg):
        QMessageBox.question(self, '警告', '{}'.format(msg),QMessageBox.Yes)

    def show_warning_close(self,msg):
        reply = QMessageBox.question(self, '警告', '{}'.format(msg), QMessageBox.Yes)
        if reply == QMessageBox.Yes:
            os._exit(0)

UI文件

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(1109, 600)
        self.horizontalLayout_5 = QtWidgets.QHBoxLayout(Form)
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        spacerItem = QtWidgets.QSpacerItem(
            20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        spacerItem1 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem1)
        self.label1 = QtWidgets.QLabel(Form)
        self.label1.setObjectName("label1")
        self.horizontalLayout.addWidget(self.label1)
        spacerItem2 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem2)
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        spacerItem3 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem3)
        self.horizontalLayout.setStretch(0, 1)
        self.horizontalLayout.setStretch(1, 10)
        self.horizontalLayout.setStretch(2, 1)
        self.horizontalLayout.setStretch(3, 10)
        self.horizontalLayout.setStretch(4, 1)
        self.verticalLayout.addLayout(self.horizontalLayout)
        spacerItem4 = QtWidgets.QSpacerItem(
            20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem4)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        spacerItem5 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem5)
        self.lineEdit1 = QtWidgets.QLineEdit(Form)
        self.lineEdit1.setStyleSheet("border:none;")
        self.lineEdit1.setObjectName("lineEdit1")
        self.horizontalLayout_2.addWidget(self.lineEdit1)
        spacerItem6 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem6)
        self.lineEdit_2 = QtWidgets.QLineEdit(Form)
        self.lineEdit_2.setStyleSheet("border:none;")
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.horizontalLayout_2.addWidget(self.lineEdit_2)
        spacerItem7 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_2.addItem(spacerItem7)
        self.horizontalLayout_2.setStretch(0, 1)
        self.horizontalLayout_2.setStretch(1, 10)
        self.horizontalLayout_2.setStretch(2, 1)
        self.horizontalLayout_2.setStretch(3, 10)
        self.horizontalLayout_2.setStretch(4, 1)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        spacerItem8 = QtWidgets.QSpacerItem(
            20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem8)
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        spacerItem9 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem9)
        self.pushButton1 = QtWidgets.QPushButton(Form)
        self.pushButton1.setObjectName("pushButton1")
        self.horizontalLayout_3.addWidget(self.pushButton1)
        spacerItem10 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem10)
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setObjectName("pushButton_2")
        self.horizontalLayout_3.addWidget(self.pushButton_2)
        spacerItem11 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem11)
        self.horizontalLayout_3.setStretch(0, 5)
        self.horizontalLayout_3.setStretch(1, 2)
        self.horizontalLayout_3.setStretch(2, 10)
        self.horizontalLayout_3.setStretch(3, 2)
        self.horizontalLayout_3.setStretch(4, 5)
        self.verticalLayout.addLayout(self.horizontalLayout_3)
        spacerItem12 = QtWidgets.QSpacerItem(
            20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem12)
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        spacerItem13 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_4.addItem(spacerItem13)
        self.pushButton_all = QtWidgets.QPushButton(Form)
        self.pushButton_all.setObjectName("pushButton_all")
        self.horizontalLayout_4.addWidget(self.pushButton_all)
        spacerItem14 = QtWidgets.QSpacerItem(
            40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.horizontalLayout_4.addItem(spacerItem14)
        self.horizontalLayout_4.setStretch(0, 10)
        self.horizontalLayout_4.setStretch(1, 3)
        self.horizontalLayout_4.setStretch(2, 10)
        self.verticalLayout.addLayout(self.horizontalLayout_4)
        spacerItem15 = QtWidgets.QSpacerItem(
            20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.verticalLayout.addItem(spacerItem15)
        self.verticalLayout.setStretch(0, 1)
        self.verticalLayout.setStretch(1, 100)
        self.verticalLayout.setStretch(2, 1)
        self.verticalLayout.setStretch(3, 2)
        self.verticalLayout.setStretch(4, 1)
        self.verticalLayout.setStretch(5, 2)
        self.verticalLayout.setStretch(6, 1)
        self.verticalLayout.setStretch(7, 2)
        self.verticalLayout.setStretch(8, 1)
        self.horizontalLayout_5.addLayout(self.verticalLayout)

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

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.label1.setText(
            _translate(
                "Form",
                "

TextLabel

"
)) self.label_2.setText( _translate( "Form", "

TextLabel

"
)) self.pushButton1.setText(_translate("Form", "PushButton")) self.pushButton_2.setText(_translate("Form", "PushButton")) self.pushButton_all.setText(_translate("Form", "PushButton")) 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_())
# !/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@author  : [email protected]
@des     :启动脚本

"""
import sys
from PyQt5 import QtWidgets
from gui.ctrl import ctrl_untitled


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    Form = ctrl_untitled.Untitled()
    Form.show()
    sys.exit(app.exec_())

程序运行截图
基于Python的双USB摄像头实时预览保存软件_第1张图片
项目目录结构
基于Python的双USB摄像头实时预览保存软件_第2张图片

你可能感兴趣的:(python,ui,开发语言,opencv,qt5)