PIL.ImageTk.PhotoImage 有什么更快的替代方法?
What's a faster alternative to PIL.ImageTk.PhotoImage?
我正在尝试显示视频,使用 examples/solutions 解决如何在 Tkinter 上播放视频的问题似乎无法实现流畅快速的渲染。
例如:
frame = self.vid_cap.read()
frame = cv2.resize(frame, (696, 486))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.latest_img_ = Image.fromarray(frame)
self.latest_img_ = ImageTk.PhotoImage(image=self.latest_img_)
self.canvas.create_image(0, 0, anchor="nw", image=self.latest_img_)
以上代码有效,但视频速度太慢,即使使用 self.canvas.after(1, self.video_loop_)
之类的东西也是如此。经过一些基准测试,结果是以下行:
self.latest_img_ = ImageTk.PhotoImage(image=self.latest_img_)
无论何时 运行 我的四核 mac 或 12 核钻机上的代码,都需要 9ms ~ 100ms,而它上面的整个代码(从捕获到转换 numpy数组到图像)只需要 0 毫秒到 1 毫秒。
什么可以比 ImageTk.PhotoImage
更快?
您应该保留 canvas
对象的引用并对其进行修改,而不是每次都创建新对象。为此,您可以首先通过传递 image=None
创建一个占位符。以下是最小样本:
import tkinter as tk
import cv2
from PIL import Image, ImageTk
class GUI(tk.Tk):
def __init__(self):
super().__init__()
self.canvas = tk.Canvas(self)
self.canvas.pack(fill="both", expand=1)
self.streaming_image = self.canvas.create_image(0, 0, anchor="nw", image=None)
def show_frame(self):
_, frame = self.vid_cap.read()
frame = cv2.resize(frame, (696, 486))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = Image.fromarray(frame)
self.latest_img = ImageTk.PhotoImage(image=img)
self.canvas.itemconfig(self.streaming_image, image=self.latest_img)
self.after(10, self.show_frame)
def start_video(self, path=None):
self.vid_cap = cv2.VideoCapture(path)
self.show_frame()
root = GUI()
root.start_video("your_path_here")
root.mainloop()
我正在尝试显示视频,使用 examples/solutions 解决如何在 Tkinter 上播放视频的问题似乎无法实现流畅快速的渲染。
例如:
frame = self.vid_cap.read()
frame = cv2.resize(frame, (696, 486))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.latest_img_ = Image.fromarray(frame)
self.latest_img_ = ImageTk.PhotoImage(image=self.latest_img_)
self.canvas.create_image(0, 0, anchor="nw", image=self.latest_img_)
以上代码有效,但视频速度太慢,即使使用 self.canvas.after(1, self.video_loop_)
之类的东西也是如此。经过一些基准测试,结果是以下行:
self.latest_img_ = ImageTk.PhotoImage(image=self.latest_img_)
无论何时 运行 我的四核 mac 或 12 核钻机上的代码,都需要 9ms ~ 100ms,而它上面的整个代码(从捕获到转换 numpy数组到图像)只需要 0 毫秒到 1 毫秒。
什么可以比 ImageTk.PhotoImage
更快?
您应该保留 canvas
对象的引用并对其进行修改,而不是每次都创建新对象。为此,您可以首先通过传递 image=None
创建一个占位符。以下是最小样本:
import tkinter as tk
import cv2
from PIL import Image, ImageTk
class GUI(tk.Tk):
def __init__(self):
super().__init__()
self.canvas = tk.Canvas(self)
self.canvas.pack(fill="both", expand=1)
self.streaming_image = self.canvas.create_image(0, 0, anchor="nw", image=None)
def show_frame(self):
_, frame = self.vid_cap.read()
frame = cv2.resize(frame, (696, 486))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = Image.fromarray(frame)
self.latest_img = ImageTk.PhotoImage(image=img)
self.canvas.itemconfig(self.streaming_image, image=self.latest_img)
self.after(10, self.show_frame)
def start_video(self, path=None):
self.vid_cap = cv2.VideoCapture(path)
self.show_frame()
root = GUI()
root.start_video("your_path_here")
root.mainloop()