带Tkinter的OpenCV:滞后和窗口问题

2024-03-28 16:44:45 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近开始在tkinter中使用opencv,我开始遇到一些我自己无法解决的问题。。。 下面的代码将播放一个视频文件,同时能够选择要在其中对文件进行排序的子目录。我开始遇到的问题是,每秒的帧数似乎有些奇怪,因为我播放的某些剪辑似乎“滞后”,或者没有正确的fps。 其次,代码看起来真的很混乱,因此按钮在点击一个按钮后会“消失”。 最后,我试着做一些事情,使按钮尽可能大地填充窗口底部的X轴,而主框架,与视频播放,保持相同的大小(因此,视频应该停留在中间,适应他的高度和宽度的帧大小,而不改变比率)。但这似乎不太管用

任何帮助都将不胜感激

PS:我正在使用Python 3.8和openCV 4.1.2

代码如下:

from tkinter import Tk, Button, Label, Frame
import os
import shutil
import cv2
from PIL import Image, ImageTk

x = 0

path = "path/to/folder"

def nbr():
    global x
    x += 1
    text.config(text=files[x])

class ButtonX (Button):

    def __init__ (self, *args, folder="", **kwargs):
        super().__init__(*args, **kwargs)
        self.folder = folder
        self.config(command=self.moveTo)

    def moveTo(self):
        global x
        global cap
        global width
        if cap.isOpened():
            cap.release()
        shutil.move(path + files[x], path + self.folder + "/" +files[x])
        print(files[x] + " moved to " + self.folder)
        nbr()
        cap = cv2.VideoCapture(path+files[x])
        ret, frame = cap.read()
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)*(height/cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))

folders = [dI for dI in os.listdir(path) if os.path.isdir(os.path.join(path,dI))]

allfiles = os.listdir(path)

files = [ fname for fname in allfiles if fname.endswith('.webm')]
files.sort(key=len)

print(folders)

window = Tk()
window.resizable(0, 0)
window.geometry("1600x908")
back = Frame(window)
back.grid(row=1, column=1)
window.grid_rowconfigure(0, weight=1)
window.grid_rowconfigure(2, weight=1)
window.grid_columnconfigure(0, weight=1)
window.grid_columnconfigure(2, weight=1)
player = Frame(back)
player.grid(row = 0, column=0)
buttouns = Frame(back)
buttouns.grid(row = 1, column=0)

text = Label(player)
text.grid(row=0, columnspan=4, sticky='w,e,n,s', padx=5, pady=50)

cap = cv2.VideoCapture(path+files[x])
fps = cap.get(cv2.CAP_PROP_FPS)
cap.set(cv2.CAP_PROP_FPS, fps)
print(fps)
height = 600
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)*(height/cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))

def show_frame():
    global cap
    global width
    cap.set(cv2.CAP_PROP_FPS, fps)
    ret, frame = cap.read()

    if frame is None:

        cap = cv2.VideoCapture(path+files[x])
        ret, frame = cap.read()

    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)

    img = Image.fromarray(cv2image).resize((width, height))
    imgtk = ImageTk.PhotoImage(image = img)
    text.imgtk = imgtk
    text.configure(image=imgtk)
    text.after(3, show_frame)

buttons = []

z = 1
y = 0

for i in range(len(folders)):
    new_button = ButtonX(buttouns,text=folders[i], width=20, height=2, folder=folders[i])
    buttons.append(new_button)
    buttons[i].grid(row=z, column=y, sticky='w,e,n,s', padx=5, pady=5)

    y += 1
    if y == 4:
        y = 0
        z += 1

def deleted():
    global cap
    global width
    print("deleted " + files[x])
    if cap.isOpened():
        cap.release()
    shutil.move(path + files[x], "path/to/deleted" + files[x])
    nbr()
    cap = cv2.VideoCapture(path+files[x])
    ret, frame = cap.read()
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)*(height/cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))

def skipped():
    global cap
    global width
    print(files[x] + " skipped")
    if cap.isOpened():
        cap.release()
    nbr()
    cap = cv2.VideoCapture(path+files[x])
    ret, frame = cap.read()
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)*(height/cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))

delete= Button(buttouns,text="Delete", width=20, height=2, command=deleted, foreground="red")
delete.grid(row=z+1,column=2, columnspan=2, sticky='w,e,n,s', padx=5, pady=5)
skip= Button(buttouns,text="Skip", width=20, height=2, command=skipped)
skip.grid(row=z+1, columnspan=2, sticky='w,e,n,s', padx=5, pady=5)

show_frame()
window.mainloop()

Tags: pathtextgetfileswindowwidthcv2global