Мерцающее видео для видео tkinter - PullRequest
1 голос
/ 13 января 2020

Я пытаюсь сделать простое приложение play / pause в tkinter. В основном я хочу показать видео с кнопкой воспроизведения / паузы внизу.

Итак, после некоторых исследований я нашел этот подходящий пост для показа видео с использованием tkinter и opencv: для показа потокового видео внутри кадра в tkinter

При использовании кода, приведенного в принятом ответе для показа видео, проблем нет, и я не вижу мерцания. Вот код:

# import the necessary packages
from __future__ import print_function
import tkinter as tk
from PIL import ImageTk, Image
import cv2


root = tk.Tk()
# Create a frame
app = tk.Frame(root, bg="white")
app.grid()
# Create a label in the frame
lmain = tk.Label(app)
lmain.grid()

# Capture from camera
cap = cv2.VideoCapture(r'PATH_TO_VIDEO_FILE')

# function for video streaming
frame_number = 0
def video_stream(): 
    global frame_number
    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_number)
    success, frame = cap.read()
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    img = Image.fromarray(cv2image)
    imgtk = ImageTk.PhotoImage(image=img)
    lmain.imgtk = imgtk
    lmain.configure(image=imgtk)
    lmain.after(1, video_stream) 

    frame_number += 1

video_stream()
root.mainloop()

Теперь я немного изменил код, чтобы иметь возможность использовать менеджер сетки и добавить кнопку воспроизведения:

# import the necessary packages

from __future__ import print_function
import tkinter as tk
from PIL import ImageTk, Image

import cv2


class PhotoBoothApp:
    def __init__(self, path_to_video):
        # initialize the root window
        self.window = tk.Tk()
        self.window.title("Video_Player")
        self.videocap = cv2.VideoCapture(path_to_video)
        self.frame_number = 0

        # Initalize
        self.videocap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_number)
        success, self.frame = self.videocap.read()
        cv2image = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGBA)
        self.img = Image.fromarray(cv2image)
        self.imgtk = ImageTk.PhotoImage(image=self.img)
        # Show frames
        self.picture_label = tk.Label(self.window, image=self.imgtk, relief=tk.RIDGE).grid(row=0, column=0)
        self.btn_next_image=tk.Button(self.window, text="Play", width=50, bg ="green",command=self.video_stream).grid(row=1,column=0)

        self.window.mainloop()





    def video_stream(self):

        self.videocap.set(cv2.CAP_PROP_POS_FRAMES, self.frame_number)
        sucess, frame = self.videocap.read()
        cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
        img = Image.fromarray(cv2image)
        self.imgtk = ImageTk.PhotoImage(image=img)
        self.picture_label = tk.Label(self.window, image=self.imgtk, relief=tk.RIDGE).grid(row=0, column=0)
        # Update Frame Number to display
        self.frame_number = self.frame_number + 1
        self.window.after(1, self.video_stream) 


ph = PhotoBoothApp(r'PATH_TO_FILE')

Проблема в том, что когда я При выполнении приведенного выше кода видео мерцает, как будто tkinter необходимо перезагрузить что-то между кадрами. Понятия не имею, почему это происходит.

PS Этот пост здесь Мерцающее видео в интеграции с opencv-tkinter мне не помогло.

1 Ответ

2 голосов
/ 13 января 2020

Вам необходимо внести два изменения: разделить строку self.picture_label, чтобы создать правильную ссылку на ваш Label объект, а затем использовать self.picure_label.config(...) для изменения изображения.

class PhotoBoothApp:
    def __init__(self, path_to_video):
        # initialize the root window
        ...
        self.picture_label = tk.Label(self.window, image=self.imgtk, relief=tk.RIDGE)
        self.picture_label.grid(row=0, column=0)
        ...

    def video_stream(self):
        ...
        img = Image.fromarray(cv2image)
        self.imgtk = ImageTk.PhotoImage(image=img)
        self.picture_label.config(image=self.imgtk)
        # Update Frame Number to display
        self.frame_number = self.frame_number + 1
        self.window.after(1, self.video_stream)

ph = PhotoBoothApp(r'PATH_TO_FILE')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...