python-3.x - tkinter 视频的闪烁视频
问题描述
我正在尝试在 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 This post here Flickering video in opencv-tkinter integration对我没有帮助。
解决方案
您需要进行两项更改:拆分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')
推荐阅读
- c++ - 在 NVIDIA 和 Intel GPU 上启动内核时的 OpenCL CL_INVALID_COMMAND_QUEUE
- vbscript - 这些 VBScript 语句有什么作用?
- python - "IsADirectoryError: [Errno 21] 是一个目录:" 它是一个文件
- javascript - Onerror 和 onload 事件不会在反应的脚本元素中触发
- amazon-web-services - AWS EMR 与 Glue 目录,明确指定 catalogId
- google-bigquery - 我想在插入 Bigquery 表时生成唯一 ID。
- mysql - 获取 MySQL 中受影响的行数
- lda - 如何用槌预测一批文档的主题
- sql-server - 在数据库表中创建多个地址
- amazon-web-services - AWS Server Migration Service Hyper-V 连接器运行状况不佳