用Python实现序列帧播放器

6 篇文章 0 订阅
1 篇文章 0 订阅

用Python实现序列帧播放器

注意

以下所有代码不可直接使用,若要使用请到百度网盘上下载源码!
链接:https://pan.baidu.com/s/1P0x8ddbnn5veFnFQJLQ0tw
提取码:6666

程序思路

  1. 用PyQt5创建一个窗口
  2. 使用tkinter.messagebox和filedialog进行用户交互
  3. 使用Pygame播放序列帧动画
  4. 使用Opencv2无损合成序列帧

窗口设计

用Qt designer设计窗口,并用PyUIC转换,有需要的小伙伴请点击这里(提取码6666)

主界面

设计完成后主窗口大概是这个样子

主窗口
这里是代码

import sys
from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 194)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(80, 30, 281, 31))
        font = QtGui.QFont()
        font.setFamily("Adobe Caslon Pro Bold")
        font.setPointSize(13)
        font.setBold(True)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.horizontalLayoutWidget = QtWidgets.QWidget(Form)
        self.horizontalLayoutWidget.setGeometry(QtCore.QRect(50, 70, 311, 41))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label_2 = QtWidgets.QLabel(self.horizontalLayoutWidget)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.lineEdit = QtWidgets.QLineEdit(self.horizontalLayoutWidget)
        self.lineEdit.setReadOnly(True)
        self.lineEdit.setObjectName("lineEdit")
        self.horizontalLayout.addWidget(self.lineEdit)
        self.pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        self.pushButton_2 = QtWidgets.QPushButton(Form)
        self.pushButton_2.setGeometry(QtCore.QRect(50, 130, 151, 41))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_3 = QtWidgets.QPushButton(Form)
        self.pushButton_3.setGeometry(QtCore.QRect(214, 130, 151, 41))
        self.pushButton_3.setObjectName("pushButton_3")
        Form.setFixedSize(Form.width(), Form.height())
        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "序列帧播放器 v3.2.4"))
        self.label.setText(_translate("Form", "欢迎使用序列帧播放器 v3.2.4"))
        self.label_2.setText(_translate("Form", "文件路径:"))
        self.pushButton.setText(_translate("Form", "浏览..."))
        self.pushButton_2.setText(_translate("Form", "预览动画"))
        self.pushButton_3.setText(_translate("Form", "合成动画"))
        self.pushButton_2.setDisabled(True)
        self.pushButton_3.setDisabled(True)
     
 def show_mainwindow():
    app=QtWidgets.QApplication(sys.argv)
    mainwindow_ui = Ui_Form()
    qMainWindow = QtWidgets.QMainWindow()
    mainwindow_ui.setupUi(qMainWindow)
    qMainWindow.show()
    sys.exit(app.exec_())

show_mainwindow()

其他界面不作详细解释,需要源码请点击这里(提取码6666)

窗口交互

使用PyQt5的槽,绑定按钮事件

self.控件名.事件.connect(执行函数)

代码如下

def choose_file(self):
	self.pushButton.setDisabled(True)
        path=askdirectory()
        self.pushButton.setDisabled(False)
        if path!="":
            self.pushButton_2.setDisabled(False)
            self.pushButton_3.setDisabled(False)
            self.lineEdit.setText(path)
        else:
            self.pushButton_2.setDisabled(True)
            self.pushButton_3.setDisabled(True)
 def b2(self):
        f = open("setting.ini" , "w")
        f.write("path=" + self.lineEdit.text())
        f.close()
        import compose
        class Login(QtWidgets.QWidget , compose.Ui_Form):
            def __init__(self):
                super(Login , self).__init__()
                self.setupUi(self)
                self.Form.setWindowModality(QtCore.Qt.ApplicationModal)
        lg = Login()
        lg.show()
def brot(self):
        self.pushButton_2.setDisabled(True)
        self.pushButton_3.setDisabled(True)
        f = open("setting.ini", "w")
        f.write("path=" + self.lineEdit.text())
        f.close()
        import browse
        class Browse(QtWidgets.QWidget, browse.Ui_Form):
            def __init__(self):
                super(Browse, self).__init__()
                self.setupUi(self)
                self.Form.setWindowModality(QtCore.Qt.ApplicationModal)
        rg = Browse()
        rg.show()
        self.pushButton_2.setDisabled(False)
        self.pushButton_3.setDisabled(False)
def bro(self):
        #here
        f = open("setting.ini", "w")
        f.write("path=" + self.lineEdit.text())
        f.close()
        import browse
        class Browse(QtWidgets.QWidget, browse.Ui_Form):
            def __init__(self):
                super(Browse, self).__init__()
                self.setupUi(self)
                self.Form.setWindowModality(QtCore.Qt.ApplicationModal)
        rg = Browse()
        rg.show()
        self.pushButton_2.setDisabled(False)
        self.pushButton_3.setDisabled(False)

绑定槽函数

self.pushButton.clicked.connect(self.choose_file)
self.pushButton_2.clicked.connect(self.brot)
self.pushButton_3.clicked.connect(self.b2)

预览模块

预览使用Pygame进行图片加载并循环播放。
代码如下

import glob
import os
import tkinter
from tkinter import messagebox
from PyQt5.QtWidgets import QMessageBox
root=tkinter.Tk()
root.withdraw()
from PyQt5 import QtCore, QtGui, QtWidgets
import time
import sys
import pygame
import threading
import random
from PIL import Image
from pygame.locals import *
pic=[]
def main():
    global pic
    pygame.init()
    f = open("setting.ini", "r").read()
    f = f.split("\n")[0]
    f = f.split("=")[1]
    fn = os.listdir(f)
    imgf = fn[0].split(".")[1]
    g = glob.glob(f + "/*." + imgf)
    img = Image.open(g[0])
    imgSize = img.size  # 大小/尺寸
    w = img.width  # 图片的宽
    o = img.height  # 图片的高
    h=open("setting.ini","r").read()
    if bool(h.split("\n")[1].split("=")[1] == "True"):
        try:
            screen = pygame.display.set_mode((w, o), flags=FULLSCREEN | HWSURFACE)
        except:
            screen = pygame.display.set_mode((w, o))
    else:
        screen = pygame.display.set_mode((w, o))
    text = pygame.font.SysFont("SimHei", 30)
    pygame.display.set_caption("动图预览")
    index = 0
    fcclock = pygame.time.Clock()  # 创建一个时间对象
    fcclock.tick(int(h.split("\n")[2].split("=")[1]))  # 调用Clock()类创建的对象中的tick()函数
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            if event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    pygame.quit()
                    sys.exit()
        screen.fill((100, 100, 100))
        screen.blit(pic[index], (0, 0))
        text = pygame.font.SysFont("SimHei", 10)
        screen.blit(text.render("Animation file displayed " + f, True, (255, 255, 255)), (0, o - 10))
        screen.blit(text.render("Software maker Xiao Shen", True, (255, 255, 255)), (w - 120, o - 10))
        screen.blit(text.render("Current frame: " + str(index) + "/" + str(len(pic)), True, (255, 255, 255)), (0, 0))
        screen.blit(text.render("Press ESC to exit", True, (255, 255, 255)), (w - 85, 0))
        # Press ESC to exit
        index += 1
        if index >= len(pic):
            index = 0
        pygame.display.update()
        fcclock.tick(int(h.split("\n")[2].split("=")[1]))
class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(400, 97)
        font = QtGui.QFont()
        font.setPointSize(11)
        Form.setFont(font)
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(20, 20, 121, 16))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.progressBar = QtWidgets.QProgressBar(Form)
        self.progressBar.setGeometry(QtCore.QRect(20, 50, 401, 23))
        self.progressBar.setMaximum(0)
        self.progressBar.setProperty("value", 0)
        self.progressBar.setFormat("")
        self.progressBar.setObjectName("progressBar")
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(310, 20, 71, 20))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.label_2.setFont(font)
        self.Form=Form
        self.label_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.label_2.setObjectName("label_2")
        self.retranslateUi(Form)
        Form.setFixedSize(Form.width(), Form.height())
        t=threading.Thread(target=self.time_go)
        t.start()
        QtCore.QMetaObject.connectSlotsByName(Form)
    def time_go(self):
        for i in range(11):
            self.label_2.setText("("+str(i)+"/10)")
            if i==6:
                time.sleep(3)
                f = open("setting.ini", "r").read()
                f = f.split("\n")[0]
                f = f.split("=")[1]
                fn = os.listdir(f)
                try:
                    imgf = fn[0].split(".")[1]
                    g = glob.glob(f + "/*." + imgf)
                    if imgf == 'jpg':
                        pass
                    elif imgf == 'png':
                        pass
                    elif imgf == 'jpeg':
                        pass
                    elif imgf == 'bmp':
                        pass
                    else:
                        print(自动)
                    if len(g) == 0:
                        print(自动)
                    img = Image.open(g[0])
                except:
                    QtWidgets.QMessageBox.critical(QtWidgets.QWidget(),"错误", "选择的文件夹无法被识别。\n请检查以下原因:\n1.文件夹内没有图片\n2.文件夹内有非图片文件\n请重新选择文件!")
                    self.Form.close()
            time.sleep(random.uniform(0.0001000,0.2000000))
        self.Form.hide()
        time.sleep(0.3)
        self.Form.setWindowTitle("Loading resource")
        self.label.setText("正在加载资源...")
        f = open("setting.ini", "r").read()
        f = f.split("\n")[0]
        f = f.split("=")[1]
        fn = os.listdir(f)
        imgf = fn[0].split(".")[1]
        g = glob.glob(f + "/*." + imgf)
        self.label_2.setText("(0/"+str(len(g))+")")
        self.Form.show()
        count=0
        for i in g:
            global pic
            pic.append(pygame.image.load(i))
            count+=1
            self.label_2.setText("("+str(count)+"/" + str(len(g)) + ")")
        self.Form.close()
        main()
    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Loading component"))
        self.label.setText(_translate("Form", "正在加载组件..."))      
         # 这里是为了耗时间,不需要的朋友可以去掉
        self.label_2.setText(_translate("Form", "(0/10)"))
def show_mainwindow():
    app=QtWidgets.QApplication(sys.argv)
    mainwindow_ui = Ui_Form()
    qMainWindow = QtWidgets.QMainWindow()
    mainwindow_ui.setupUi(qMainWindow)
    qMainWindow.show()
    sys.exit(app.exec_())
show_mainwindow()

渲染模块

使用OpenCV库进行图片的合成,这里有一个小细节
——计时模块
大概就是一个进位原理
代码如下

def time_go(self):
        while True:
            self.label_15.setText("已用时间:" + self.nt)
            h=int(self.nt.split(":")[0])
            m = int(self.nt.split(":")[1])
            s = int(self.nt.split(":")[2])
            #self.progressBar.setValue(int(self.value))
            time.sleep(1)
            s+=1
            if s>=60:
                s=0
                m+=1
            if m>=60:
                s=0
                m=0
                h+=1
            ss="00"
            sm="00"
            sh="00"
            if s<10:
                ss="0"+str(s)
            else:
                ss=str(s)
            if m<10:
                sm="0"+str(m)
            else:
                sm=str(m)
            if h<10:
                sh="0"+str(h)
            else:
                sh=str(h)
            self.nt=sh+":"+sm+":"+ss
            self.label_15.setText("已用时间:"+self.nt)
            if self.mt==False:
                return

我们决定使用多线程进行一个加快的处理
用法:

thread=threading.Thread(target=函数名)
thread.start # 启动线程

图片的合成过程有些复杂,不多说,直接放代码

def main_thread(self):
        self.label_13.setText("当前状态:正在准备")
        time.sleep(1.3)
        self.label_13.setText("当前状态:正在合成")
        img_array = []
        fn = os.listdir(open("setting.ini","r").read().split("\n")[0].split("=")[1])
        imgf = fn[0].split(".")[1]
        g = glob.glob(open("setting.ini","r").read().split("\n")[0].split("=")[1] + "/*." + imgf)
        add = 100 / len(g)
        for filename in g:
            self.label_14.setText("当前合成项:" + filename)
            if self.value <= 100:
                self.value += add
            img = cv2.imdecode(ny.fromfile(filename, dtype=ny.uint8), -1)
            img_array.append(img)
        fps=self.spinBox.value()
        _width=int(open("config.tmp","r").read().split(" ")[0])
        _height =int(open("config.tmp", "r").read().split(" ")[1])
        self.label_13.setText("当前状态:正在写入")
        out = cv2.VideoWriter(self.lineEdit.text(), cv2.VideoWriter_fourcc(*'DIVX'), fps, (_width, _height))
        for i in range(len(img_array)):
            out.write(img_array[i])
        out.release()
        self.mt=False
        self.label_13.setText("当前状态:合成完毕")
        self.progressBar.setMaximum(1)
        self.label_16.setText("100%")
        QtWidgets.QMessageBox.information(QtWidgets.QWidget(), "完成","合成已完成\n耗时 "+self.nt+" 秒!")
        self.pushButton.setDisabled(False)
        self.pushButton_2.setDisabled(False)
        self.lineEdit.setDisabled(False)
        self.spinBox.setDisabled(False)
        self.comboBox_3.setDisabled(False)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现在线音乐播放器需要前端和后端的技术。前端技术可以使用HTML、CSS和JavaScript,后端技术可以使用Python。 下面是一个基于Python Flask框架实现的在线音乐播放器的示例代码: ```python from flask import Flask, render_template, url_for, request import os app = Flask(__name__) @app.route("/") def index(): music_list = os.listdir("static/music") return render_template("index.html", music_list=music_list) @app.route("/play", methods=["POST"]) def play(): music_name = request.form["music_name"] return render_template("play.html", music_name=music_name) if __name__ == "__main__": app.run(debug=True) ``` 这是一个简单的后端代码,我们需要在`static/music`文件夹下放置音乐文件,然后通过前端页面来实现在线播放。下面是HTML代码: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>在线音乐播放器</title> </head> <body> <h1>在线音乐播放器</h1> <ul> {% for music in music_list %} <li> <form action="{{ url_for('play') }}" method="post"> <input type="hidden" name="music_name" value="{{ music }}" /> <button type="submit">{{ music }}</button> </form> </li> {% endfor %} </ul> </body> </html> ``` 这是主页的HTML代码,我们通过Python代码中的`music_list = os.listdir("static/music")`获取`static/music`文件夹下的所有音乐文件,然后通过循环展示在页面上。当用户点击某个音乐文件时,会提交一个POST请求到`/play`路由,Python代码中的`play()`函数会接收到这个请求,然后渲染一个新的页面。 下面是播放页面的HTML代码: ```html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>{{ music_name }}</title> </head> <body> <h1>{{ music_name }}</h1> <audio controls src="{{ url_for('static', filename='music/' + music_name) }}"></audio> </body> </html> ``` 这是播放页面的HTML代码,我们通过Python代码中的`music_name = request.form["music_name"]`获取用户选择的音乐文件名称,然后在页面上渲染出音乐名称和播放器。由于音乐文件在`static/music`文件夹下,因此我们使用`url_for('static', filename='music/' + music_name)`来获取音乐文件的URL。 这样,我们就完成了一个简单的在线音乐播放器实现。当用户访问`http://127.0.0.1:5000/`时,会展示出音乐列表,用户选择某个音乐文件后,会跳转到播放页面,自动播放该音乐文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值