基于PyQt5,opencv,实现双usb外接摄像头拍摄存储
双摄像头支持单独开启关闭,实时预览视频,单独/同时保存预览视频图片
多线程模式,支持掉线重连(有点bug,因无法绑定设备id,画面会出现错乱,当两个摄像头全部重连成功后画面顺序恢复正常)
# !/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@author : v_jiaohaicheng@baidu.com
@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, '警告', '<font color=red><b>窗口关闭后,将终止本次运行</b></font>',
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, '警告', '<font color=red><b>{}</b></font>'.format(msg),QMessageBox.Yes)
def show_warning_close(self,msg):
reply = QMessageBox.question(self, '警告', '<font color=red><b>{}</b></font>'.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",
"<html><head/><body><p align=\"center\">TextLabel</p></body></html>"))
self.label_2.setText(
_translate(
"Form",
"<html><head/><body><p align=\"center\">TextLabel</p></body></html>"))
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 : v_jiaohaicheng@baidu.com
@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_())
程序运行截图
项目目录结构