Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python OpenCV视频播放:重新打开视频时不显示图像_Python_Python 3.x_Opencv_Tkinter - Fatal编程技术网

Python OpenCV视频播放:重新打开视频时不显示图像

Python OpenCV视频播放:重新打开视频时不显示图像,python,python-3.x,opencv,tkinter,Python,Python 3.x,Opencv,Tkinter,我在使用Python(3.8.6)Tkinter和OpenCV时遇到了一个奇怪的问题。我正在尝试循环播放一个视频,直到选择了另一个视频 当我第一次打开视频时,它开始正常播放。当我打开另一个视频(同一个视频或其他视频)时,第一个视频停止,但第二个视频的图像不显示(它似乎在后台播放)。奇怪的是,当tkinter文件对话框显示打开另一个视频时,它确实会显示视频。但当对话框取消时,显示再次停止 如果我手动关闭播放(“p”)并重新打开视频(“o”),它将正常工作。 如果在打开新视频之前视频已完成(无循环)

我在使用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中修复了它,但从我的角度来看,这似乎只是一个解决办法。