python - 使用 tkinter(画布)和线程播放视频时出错
问题描述
我正在尝试制作一个 GUI,允许我播放视频并在某个点停止它以标记某些点并再次播放。
我想用 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
解决方案
推荐阅读
- javascript - Webpack:Configuration.resolve 具有未知属性“扩展”
- javascript - 如何使用带有身份验证的 JavaScript(前端应用程序)向 MongoDB 发送请求?
- javascript - ChartJS - 在不同的调用中从服务器返回标签和数据
- d3.js - d3 元素是否需要用重复的代码重新定义?
- jquery-ui-sortable - 想通过 Tabulator js 插件禁用列(行号:)的排序使用
- sumologic - Sumologic 仪表板中的环境切换
- javascript - Javascript - 无法实例化 firebase-firestore
- python - 使用 BeautifulSoup4 和 Python 抓取有序列表
- jquery - 在 angularjs 中动态加载 Jquery 选项卡
- node.js - GET 的表达参数长度限制