基于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 Threadclass 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 = Falseself.status_pushbutton1 = Falseself.status_pushbutton_2 = Falseself.single_show_video1 = Falseself.single_show_video_2 = Falseself.t1 = ""self.t2 = ""self.video_img1 = ""self.video_img2 = ""self.video_save1 = ""self.video_save2 = ""self.img_save_num = 0self.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:passdef 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:passself.single_show_video_2 = Trueelse: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 = Falsedef 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:passself.single_show_video1 = Trueelse: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 = Falsedef show_camera1(self):""":return:"""camear_start_single1 = Falsedef 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 = frameself.video_img1 = video_imgif self.single_show_video1:self.single_show_video_label1.emit()else:self.video_img1 = ""self.video_save1 = ""# if self.status_pushbutton1 == False:#     breakcap.release()raise Exception("摄像头未成功连接")retry_times = 3while not camear_start_single1 and retry_times > 0:try:start_camera1()camear_start_single = Trueexcept 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 = Falsedef 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 = frameself.video_img2 = video_imgif 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:#     breakcap.release()retry_times = 3while not camear_start_single2 and retry_times>0:try:start_camera2()camear_start_single2 = Trueexcept Exception as e:print("e",e)# self.single_show_warning.emit("摄像头2启动失败/断开连接,点击确定开始尝试重新连接")# start_camera2()self.video_img2 = ""self.video_save2 = ""retry_times -= 1self.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 = Falseself.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 = Trueelse:self.status_pushbutton_all = Falseself.view_pushbutton_all()def slot_finish_pushButton_2(self):""":return:"""self.status_pushbutton_2 = Falseself.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 = Trueself.view_pushbutton1()self.check_status_pushbutton_all()def slot_pushbutton_2(self):""":return:"""self.status_pushbutton_2 = Trueself.view_pushbutton_2()self.check_status_pushbutton_all()def slot_pushbutton_all(self):""":return:"""self.status_pushbutton_all = Truetry:self.img_save_num += 1t_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, QtWidgetsclass 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.translateForm.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 sysapp = 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_untitledif __name__ == '__main__':app = QtWidgets.QApplication(sys.argv)Form = ctrl_untitled.Untitled()Form.show()sys.exit(app.exec_())

程序运行截图

项目目录结构

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

  1. 浏览器显示海康摄像头实时预览画面纯前端解决方案

    浏览器显示海康摄像头实时预览画面纯前端解决方案 将海康设备的 rtsp 协议视频流通过 ffmpeg 转码为 flv 实时视频流,并将实时视频流通过 express 服务生成 http 长链接或 ws ...

  2. Java海康威视摄像头实时预览视频流保存到指定文件中

    海康威视摄像头实时预览视频流保存到文件中 目前在开发海康威视sdk ,IPC设备,视频回调用的是官方提供的Demo中的(fRealDataCallBack ) 在最下面代码可以设置Thread.sle ...

  3. 前端如何显示服务器摄像头,浏览器显示海康摄像头实时预览画面纯前端解决方案...

    php 实时输出内容到浏览器 php 实时输出内容到浏览器 当你在处理一个过程需要耗时很长,但你又需要适时的知道程序当前的处理状况的时候,该怎么办呢?下面就分享一下如何使用php及时的输出当前结果到浏 ...

  4. 网络监控摄像头流媒体视频管理平台实时预览零延迟支持海康威视浙江大华宇视等解决方案分析

    方案简介 网络摄像头监控视频低延迟一直是一个比较难以解决的问题,很多非音视频开发专业的技术人员,花费了大量精力开发出来的各种集成网络监控摄像头在浏览器Web网页实时播放的程序,要么延迟非常高,要么及其 ...

  5. antd picker 使用 如何_如何基于jsoneditor二次封装一个可实时预览的json编辑器组件?(react版)...

    前言 做为一名前端开发人员,掌握vue/react/angular等框架已经是必不可少的技能了,我们都知道,vue或react等MVVM框架提倡组件化开发,这样一方面可以提高组件复用性和可扩展性,另一 ...

  6. echarts折线图怎么从y轴开始_基于echarts的双y轴实时更新折线图

    一款基于echarts的双y轴实时更新折线图效果,页面加载后开始自动更新数据并绘制对应的折线图,可以点击右上角的按钮:显示数据视图.刷新数据和将数据存储为png的图片. 查看演示 下载资源: 46 次 ...

  7. Python OpenCV 读取USB摄像头报错问题解决

    报错信息: Traceback (most recent call last):   File "G:\Python图像识别相关学习视频\人体姿势检测.py", line 32, ...

  8. jetson nano yolov5部署及USB摄像头实时检测 初次尝试

    (1条消息) Jetson nano部署Yolov5 --从烧录到运行 1:1复刻全过程_IamYZD的博客-CSDN博客_jetson nano部署yolov5 1.yolov5部署 学校发的板子不 ...

  9. Android 双usb 摄像头支持

    公司有一款产品需要支持双USB摄像头,标准的Android设备只支持同时打开一个camera,若要支持两个显示需要修改rk3288 源码, hardware/rockchip/camera/Camer ...

最新文章

  1. Storage API简介和存储限制与逐出策略
  2. 【渗透过程】嘉缘网站 --测试
  3. 【QGIS入门实战精品教程】2.2:QGIS软件的下载与安装(Windows)
  4. aaynctask控制多个下载进度_使用 Python 下载的 11 种姿势,一种比一种高级
  5. Angular - ng-repeat高级用法
  6. demo10 关于JS Tree Shaking
  7. js隐藏和显示div
  8. SLAM_四元数取逆-Quaternion Inverse - 已验证
  9. java常用类实验报告总结_【Java基础】java常用类实验总结
  10. Android 签名类型
  11. gliffy-confluence-plugin-9.1.2安装
  12. 07-PKI证书体系
  13. VLAN tag格式
  14. 用Excel绘制曲线图
  15. HTML5系列代码:注册商标reg_和版权商标copy
  16. 用 Python 制作“会跳舞”的动态图表
  17. 【哲理】你的上限是什么?如何打破上限?-莫安迪
  18. 4g手机关闭4g信号显示无服务器,手机4G信号栏为什么突然出现“HD”?原来开通了这个业务,望周知...
  19. AI:2020年6月23日北京智源大会演讲分享之AI创业专题论坛——10:30-11:20陆奇教授《AI创业发展趋势:机会与挑战》
  20. 机器学习-预剪枝和后剪枝

热门文章

  1. 数字化汗字中仲字如化数字化_如何将旧的电影照片数字化
  2. Linux下关于snmp的snmpwalk命令
  3. iPhone 导入照片显示时间不是拍摄时间
  4. 单片机作业1_为OLED制作汉字字库_第3部分
  5. 学计算机编程我有什么好处,学编程到底有什么好处?我发现了这三个秘密!
  6. 矩阵分析 (二) 内积空间
  7. 阿里技术类面试真题,你能做对几个?(含答案)
  8. WiFi广告路由器的利与弊
  9. 感想篇:7)知其然与知其所以然,KnowHow与KnowWhy
  10. 联发科MT6737和MT6735芯片组有什么差异?MT6737和MT6735芯片组资料分享