1、需求
原需求:使用PyQt5将视频切割成图片
现增加:进度条以及选择文件功能,在ui上打印出日志
2、UI设计
原ui:
使用PyQt重新设计ui:
3、cmd命令转化为python文件
C:\Users\DIY-PC\AppData\Local\Programs\Python\Python38\python.exe -m PyQt5.uic.pyuic D:\python\pyqt\ui\screenshot.ui -o D:\python\pyqt\ui\ssplus.py
4、总结新加入知识点
1、往QTextEdit组件后追加文本:
self.output = QtWidgets.QTextEdit(Dialog)
self.output.append("")
2、选择文件,选择文件夹
self.inputBut = QtWidgets.QPushButton(Dialog)
self.inputBut.setGeometry(QtCore.QRect(300, 20, 75, 23))
self.inputBut.setObjectName("inputBut") # 选择文件
self.inputBut.clicked.connect(self.select_file) # 为button绑定消息对话框
self.outputBut = QtWidgets.QPushButton(Dialog)
self.outputBut.setGeometry(QtCore.QRect(300, 50, 75, 23))
self.outputBut.setObjectName("outputBut") # 选择文件夹
self.outputBut.clicked.connect(self.select_dir) # 为button绑定消息对话框
self.inputBut.setText(_translate("Dialog", "选择文件"))
self.outputBut.setText(_translate("Dialog", "选择文件夹"))
def select_file(self):
"""选择文件对话框"""
# QFileDialog组件定义
fileDialog = QFileDialog(self)
# QFileDialog组件设置
fileDialog.setWindowTitle("选择视频") # 设置对话框标题
fileDialog.setFileMode(QFileDialog.AnyFile) # 设置能打开文件的格式
fileDialog.setDirectory(r'D:') # 设置默认打开路径
# fileDialog.setNameFilter("Images (*.png *.xpm *.jpg)") # 按文件名过滤
file_path = fileDialog.exec() # 窗口显示,返回文件路径
if file_path and fileDialog.selectedFiles():
#self.output.append("选择文件成功:{}".format(fileDialog.selectedFiles()[0]))
self.inputdir.setText(fileDialog.selectedFiles()[0])
# 方式二
# file_path, file_type = QFileDialog.getOpenFileName(self, '标题', os.getcwd(), 'Images (*.png *.xpm *.jpg)')
# if file_path and file_type:
# print("选择文件成功:{}".format(file_path))
def select_dir(self):
"""选择文件夹对话框架"""
dir_path = QFileDialog.getExistingDirectory(self, '选择存储路径', os.getcwd())
if dir_path:
#self.output.append("选择文件夹成功:{}".format(dir_path))
self.outputdir.setText(dir_path)
3、进度条根据程序设置进度:
思路:视频按帧截图和按秒截图,知道视频总帧数和总秒数之后,在程序进行时,计算当前正在处理第几秒第几帧的数据,这样能得知当前进度
self.progressBar = QtWidgets.QProgressBar(Dialog)
self.progressBar.setGeometry(QtCore.QRect(90, 120, 281, 16))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.ui.progressBar.setValue(XXX)#XXX指的当前进度
5、运行效果
6、详细代码
项目结构:
main.py:
import sys
import os
import cv2
import ssplus
from PyQt5.QtWidgets import QApplication, QDialog
#注意就是下面的 if 语句
if hasattr(sys, 'frozen'):
os.environ['PATH'] = sys._MEIPASS + ";" + os.environ['PATH']
# import others
class MainDialog(QDialog):
def __init__(self, parent=None):
super(QDialog, self).__init__(parent)
self.ui = ssplus.Ui_Dialog()
self.ui.setupUi(self)
def accept(self):
# 设置进度条
video=self.ui.inputdir.text()
f_save_path=self.ui.outputdir.text()+'/'
maskText = self.ui.pattern.currentText()
mask = self.getCode(maskText)
frame_interval = 2 # 设置帧率间隔
time_interval = 1 # 设置时间间隔(单位:s)
if (mask == 1):
self.ui.output.append("当前模式:按照帧率截取视频\n帧率间隔:"+str(frame_interval))
elif (mask == 2):
self.ui.output.append("当前模式:按照时间截取视频\n时间间隔:"+str(time_interval)+"s")
file_name=os.path.basename(video).split('.')[0] # 拆分视频文件名称 ,剔除后缀
folder_name = f_save_path + file_name # 保存图片的上级目录+对应每条视频名称 构成新的目录存放每个视频
os.makedirs(folder_name, exist_ok=True) # 创建存放视频的对应目录
vc = cv2.VideoCapture(video) # 读入视频文件
fps = vc.get(cv2.CAP_PROP_FPS) # 获取当前视频帧率
frame_num=vc.get(cv2.CAP_PROP_FRAME_COUNT)
rval = vc.isOpened() # 判断视频是否打开
c = 1
while rval: # 循环读取视频帧
rval, frame = vc.read() # videoCapture.read() 函数,第一个返回值为是否成功获取视频帧,第二个返回值为返回的视频帧;
pic_path = folder_name + '/'
if rval:
if(mask == 1):
if (c % round(frame_interval) == 0): # 每隔frame_interval帧存储一次
cv2.imencode('.jpg', frame)[1].tofile(
pic_path + file_name + '_' + str(round(c / frame_interval)) + '.jpg') # 中文路径也可以保存
self.ui.output.append(file_name + '_' + str(round(c / frame_interval)) + '.jpg')
self.ui.progressBar.setValue(round(c / frame_interval) / round(frame_num/frame_interval) * 100)
cv2.waitKey(1)
c = c + 1
elif(mask == 2):
total_seconds=frame_num/fps
if (c % (round(fps)*time_interval) == 0): # 每隔time_interval秒存储一次
cv2.imencode('.jpg', frame)[1].tofile(
pic_path + file_name + '_' + str(round(c / fps)) + '.jpg')
self.ui.output.append(file_name + '_' + str(round(c / fps)) + '.jpg')
self.ui.progressBar.setValue(round(c / fps) / round(total_seconds) * 100)
print(round(c / fps) / round(total_seconds) * 100)
cv2.waitKey(1)
c = c + 1
else:
break
vc.release()
outputText=('save_success:' + folder_name)
self.ui.output.append(outputText)
self.ui.progressBar.setValue(100)
def getCode(self, cityName):
cityDict = {"按帧": 1,
"按秒": 2}
return cityDict[cityName]
def clearText(self):
self.ui.inputdir.clear()
self.ui.outputdir.clear()
self.ui.output.clear()
self.ui.progressBar.setValue(0) # 任务完成后将进度条归零
if __name__ == '__main__':
myapp = QApplication(sys.argv)
myDlg = MainDialog()
myDlg.show()
sys.exit(myapp.exec_())
ssplus.py:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'D:\python\pyqt\ui\screenshot.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# 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.
import os
import time
from PyQt5 import QtCore, QtWidgets
from PyQt5.QtWidgets import QFileDialog, QWidget
class Ui_Dialog(QWidget):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(400, 300)
self.confirm = QtWidgets.QDialogButtonBox(Dialog)
self.confirm.setGeometry(QtCore.QRect(30, 260, 341, 32))
self.confirm.setOrientation(QtCore.Qt.Horizontal)
self.confirm.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
self.confirm.setObjectName("confirm")
self.label = QtWidgets.QLabel(Dialog)
self.label.setGeometry(QtCore.QRect(30, 20, 54, 12))
self.label.setObjectName("label")
self.label_2 = QtWidgets.QLabel(Dialog)
self.label_2.setGeometry(QtCore.QRect(30, 50, 54, 12))
self.label_2.setObjectName("label_2")
self.label_3 = QtWidgets.QLabel(Dialog)
self.label_3.setGeometry(QtCore.QRect(30, 80, 54, 20))
self.label_3.setObjectName("label_3")
self.pattern = QtWidgets.QComboBox(Dialog)
self.pattern.setGeometry(QtCore.QRect(90, 80, 69, 22))
self.pattern.setObjectName("pattern")
self.pattern.addItem("")
self.pattern.addItem("")
self.inputdir = QtWidgets.QLineEdit(Dialog)
self.inputdir.setGeometry(QtCore.QRect(90, 20, 201, 20))
self.inputdir.setObjectName("inputdir")
self.outputdir = QtWidgets.QLineEdit(Dialog)
self.outputdir.setGeometry(QtCore.QRect(90, 50, 201, 20))
self.outputdir.setObjectName("outputdir")
self.output = QtWidgets.QTextEdit(Dialog)
self.output.setGeometry(QtCore.QRect(30, 150, 341, 101))
self.output.setObjectName("output")
self.progressBar = QtWidgets.QProgressBar(Dialog)
self.progressBar.setGeometry(QtCore.QRect(90, 120, 281, 16))
self.progressBar.setProperty("value", 0)
self.progressBar.setObjectName("progressBar")
self.label_4 = QtWidgets.QLabel(Dialog)
self.label_4.setGeometry(QtCore.QRect(30, 120, 54, 12))
self.label_4.setObjectName("label_4")
self.inputBut = QtWidgets.QPushButton(Dialog)
self.inputBut.setGeometry(QtCore.QRect(300, 20, 75, 23))
self.inputBut.setObjectName("inputBut") # 选择文件
self.inputBut.clicked.connect(self.select_file) # 为button绑定消息对话框
self.outputBut = QtWidgets.QPushButton(Dialog)
self.outputBut.setGeometry(QtCore.QRect(300, 50, 75, 23))
self.outputBut.setObjectName("outputBut") # 选择文件夹
self.outputBut.clicked.connect(self.select_dir) # 为button绑定消息对话框
self.retranslateUi(Dialog)
# Start program execution when the start button is clicked
self.confirm.accepted.connect(Dialog.accept)
#self.confirm.accepted.connect(Dialog.onStart) # type: ignore
self.confirm.rejected.connect(Dialog.clearText) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "视频截图"))
self.label.setText(_translate("Dialog", "视频:"))
self.label_2.setText(_translate("Dialog", "存储路径:"))
self.label_3.setText(_translate("Dialog", "截取模式:"))
self.pattern.setCurrentText(_translate("Dialog", "按帧"))
self.pattern.setItemText(0, _translate("Dialog", "按帧"))
self.pattern.setItemText(1, _translate("Dialog", "按秒"))
self.label_4.setText(_translate("Dialog", "进度条:"))
self.inputBut.setText(_translate("Dialog", "选择文件"))
self.outputBut.setText(_translate("Dialog", "选择文件夹"))
def select_file(self):
"""选择文件对话框"""
# QFileDialog组件定义
fileDialog = QFileDialog(self)
# QFileDialog组件设置
fileDialog.setWindowTitle("选择视频") # 设置对话框标题
fileDialog.setFileMode(QFileDialog.AnyFile) # 设置能打开文件的格式
fileDialog.setDirectory(r'D:') # 设置默认打开路径
# fileDialog.setNameFilter("Images (*.png *.xpm *.jpg)") # 按文件名过滤
file_path = fileDialog.exec() # 窗口显示,返回文件路径
if file_path and fileDialog.selectedFiles():
#self.output.append("选择文件成功:{}".format(fileDialog.selectedFiles()[0]))
self.inputdir.setText(fileDialog.selectedFiles()[0])
# 方式二
# file_path, file_type = QFileDialog.getOpenFileName(self, '标题', os.getcwd(), 'Images (*.png *.xpm *.jpg)')
# if file_path and file_type:
# print("选择文件成功:{}".format(file_path))
def select_dir(self):
"""选择文件夹对话框架"""
dir_path = QFileDialog.getExistingDirectory(self, '选择存储路径', os.getcwd())
if dir_path:
#self.output.append("选择文件夹成功:{}".format(dir_path))
self.outputdir.setText(dir_path)