Ошибка при воспроизведении видео с помощью tkinter (canvas) и потоков - PullRequest
0 голосов
/ 02 ноября 2018

Я пытаюсь создать графический интерфейс, который позволяет мне воспроизводить видео и останавливать его в какой-то момент, чтобы пометить несколько точек и воспроизвести его снова.

Я хочу реализовать это с Tkinter и потоком, который читает кадры (я помещаю их в буфер), и другим, который обновляет их на холсте, мой код:

import tkinter
import threading
import queue
import cv2
import PIL.Image, PIL.ImageTk

class GuiPart:
    def __init__(self, window, queue, w,h):
        self.queue = queue
        self.stopped=False

        self.canvas = tkinter.Canvas(window, width = w, height = h)
        self.canvas.pack()

        self.backgroudThread=threading.Thread(target=self.processIncomingFrames)
        self.backgroudThread.start()

    def processIncomingFrames(self):
        while True:
            try:
                frame = self.queue.get()
                frameImage = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame))
                self.canvas.create_image(0, 0, image = frameImage, anchor = tkinter.NW)
            except queue.Empty:
                pass

class AppManager:

    def __init__(self, window, video=0):
        self.window = window
        self.video = video

        self.capFile = cv2.VideoCapture(self.video)
        self.fps = self.capFile.get(cv2.CAP_PROP_FPS)
        self.widthVideo = self.capFile.get(cv2.CAP_PROP_FRAME_WIDTH)
        self.heightVideo = self.capFile.get(cv2.CAP_PROP_FRAME_HEIGHT)

        self.queue = queue.Queue(20)
        self.gui = GuiPart(window, self.queue, self.widthVideo, self.heightVideo)

        self.running=True

        self.readFileThread = threading.Thread(target=self.readFileThread)
        self.readFileThread.start()

    def readFileThread(self):
        while self.running:
                ret, frame = self.capFile.read()
                if not ret:
                    self.running = False
                while self.running:
                    try:
                        self.queue.put(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB), timeout=1)
                        break
                    except queue.Full:
                        pass

    def endApplication(self):
        self.running = False

window = tkinter.Tk()

manager = AppManager(window,"videoplayback.mp4")
window.mainloop()

Проблема в том, что он хорошо воспроизводит видео (сейчас мне не интересен FPS, я знаю, как его исправить), но при каждом определенном количестве кадров появляется начальный кадр, как если бы он был загружен в память и появился. При необходимости я могу записать видео с экрана, но по этой ссылке я оставляю GIF-файл, чтобы понять, что я имею в виду.

Знаете ли вы, что может быть причиной этого?

ОБНОВЛЕНО

Для решения проблемы я написал следующий код в функции processIncomingFrames ():

def processIncomingFrames(self):
        while True:
            try:
                frame = self.queue.get()
                frameImage = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame))
                if self.idFrame is None:
                    self.idFrame = self.canvas.create_image(0, 0, image = frameImage, anchor = tkinter.NW)
                else:
                    self.canvas.itemconfig(self.idFrame, image = frameImage)
                    self.canvas.image=frameImage
            except queue.Empty:
                pass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...