Python OpenCV视频播放:重新打开视频时不显示图像
我在使用Python(3.8.6)Tkinter和OpenCV时遇到了一个奇怪的问题。我正在尝试循环播放一个视频,直到选择了另一个视频 当我第一次打开视频时,它开始正常播放。当我打开另一个视频(同一个视频或其他视频)时,第一个视频停止,但第二个视频的图像不显示(它似乎在后台播放)。奇怪的是,当tkinter文件对话框显示打开另一个视频时,它确实会显示视频。但当对话框取消时,显示再次停止 如果我手动关闭播放(“p”)并重新打开视频(“o”),它将正常工作。 如果在打开新视频之前视频已完成(无循环),它也会正常工作Python OpenCV视频播放:重新打开视频时不显示图像,python,python-3.x,opencv,tkinter,Python,Python 3.x,Opencv,Tkinter,我在使用Python(3.8.6)Tkinter和OpenCV时遇到了一个奇怪的问题。我正在尝试循环播放一个视频,直到选择了另一个视频 当我第一次打开视频时,它开始正常播放。当我打开另一个视频(同一个视频或其他视频)时,第一个视频停止,但第二个视频的图像不显示(它似乎在后台播放)。奇怪的是,当tkinter文件对话框显示打开另一个视频时,它确实会显示视频。但当对话框取消时,显示再次停止 如果我手动关闭播放(“p”)并重新打开视频(“o”),它将正常工作。 如果在打开新视频之前视频已完成(无循环)
import os
import tkinter as tk
from tkinter import filedialog
from PIL import Image, ImageTk
import cv2
VIDEO_RATE = int(1000.0/30.0)
class VideoPlayback:
def __init__(self):
self.cv2Video = None
def __del__(self):
if self.cv2Video and self.cv2Video.isOpened():
self.cv2Video.release()
def openVideo(self, src, width=405, height=720):
self.cv2Video = cv2.VideoCapture(src)
if not self.cv2Video.isOpened():
raise ValueError("Unable to open video source", src)
self.resizeDim = (width,height)
def closeVideo(self):
if self.cv2Video:
self.cv2Video.release()
def readVideoFrame(self, retry=5):
if self.cv2Video and self.cv2Video.isOpened():
ret, frame = self.cv2Video.read()
if ret:
return (ret, cv2.cvtColor(cv2.resize(frame, self.resizeDim), cv2.COLOR_BGR2RGB))
else:
if retry:
self.cv2Video.set(cv2.CAP_PROP_POS_FRAMES, 0)
return self.readVideoFrame(retry=retry-1)
else:
return (False, None)
else:
return (False, None)
class MainWindow(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self,"Minimal working example")
self.geometry("1280x740+2+2")
self.attributes("-fullscreen",True)
frTop = tk.Frame(master=self, width=1280, height=720)
frTop.pack(side='top', fill='both', expand=1)
# Playback canvas
self.cnvVideo = tk.Canvas(master=frTop, width=405, height=720)
self.cnvVideoImg = self.cnvVideo.create_image(0,0, anchor='nw')
self.cnvVideo.pack(side='right', fill='both', expand=1)
# Buttons
self.bind("o",self.openVideoPlayback)
self.bind("p",self.closeVideoPlayback)
# reference video playback
self.video = VideoPlayback()
self.afterVideo = None
def openVideoPlayback(self, *args):
# show file dialog
videoSrc = filedialog.askopenfilename(title = 'Open video', filetypes=(("Video files (*.mp4)","*.mp4"),("All files (*.*)","*.*")))
if videoSrc:
# open selected video for playback
self.video.openVideo(videoSrc, width=405, height=720)
# start update loop
self.afterVideo = self.after(VIDEO_RATE, self.updateVideoPlayback)
def updateVideoPlayback(self):
(ret, frame) = self.video.readVideoFrame()
if ret:
image = Image.fromarray(frame)
image = ImageTk.PhotoImage(image, master=self)
self.cnvVideo.itemconfig(self.cnvVideoImg, image=image)
self.cnvVideo.image = image
self.cnvVideo.after(VIDEO_RATE, self.updateVideoPlayback)
else:
print("Stop rescheduling")
def closeVideoPlayback(self, *args):
# stop video playback
if self.video:
self.video.closeVideo()
app = MainWindow()
app.mainloop()
在打开新视频之前,我尝试添加了self.video.closeVideo()
。
在打开新视频之前,我尝试在取消(self.afterVideo)后添加self.after
代码是更大的Tkinter接口的一部分,但仅限于最小的(非)工作示例。您的代码在Python 3.7和OpenCV 4.4.0.42上运行良好。@HenryYik您在Windows上吗?我的确切配置是:win32和OpenCV 4.4.0上的Python 3.8.6(tags/v3.8.6:db45529,Sep 23 2020,15:52:53)[MSC v.1927 64位(AMD64)]。我将尝试降级Python。问题仍然存在于Python 3.7中(也存在于Python 2.7中),所以它似乎与Python版本无关。我通过将
self.cnvVideo.update\u idletasks()
添加到updateVideoPlayback中修复了它,但从我的角度来看,这似乎只是一个解决办法。