尝试编译使用Tkinter和cv2构建的简单视频播放器GUI。编译后,GUI可以正确打开,但是在加载视频文件并尝试播放后,GUI冻结。
只需运行以下命令即可完成编译- 终端中的pyinstaller。
在编译之前,该应用程序可以在我的python环境中运行。 为了清楚起见,下面将发布整个代码: 该应用程序使用cv2模块和PIL通过以下方式逐帧显示视频:
cv2.VideoCapture(video_source)
方法read()加载框架cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
python PIL.ImageTk.PhotoImage(image=PIL.Image.fromarray(frame))
python Fcanvas.create_image(0, 0, image=self.photo, anchor=NW)
下面插入了相关的代码段:
from tkinter import *
from tkinter import filedialog, Label
import PIL.Image, PIL.ImageTk
import cv2
import numpy as np
class Root:
def __init__(self):
self.app = Tk()
self.Fcanvas = Canvas(bg='white', height=1200, width=1200)
# creating a menu bar
self.app.mainloop()
def load_video(self):
file_name = filedialog.askopenfilename(initialdir='/', title='Select video')
self.video_cap = MyVideoCapture(file_name)
self.Fcanvas = Canvas(bg='white', height=self.video_cap.height, width=self.video_cap.width)
self.Fcanvas.pack()
# initiating pause flag
self.pause_flag = True
#self.time_bar.config()
self.time_bar.config(from_=0, to=self.video_cap.vid.get(cv2.CAP_PROP_FRAME_COUNT)/self.video_cap.frame_rate)
self.time_bar.pack_configure()
def update(self):
# check if video object exists
if self.pause_flag is False:
try:
ret, frame = self.video_cap.get_frame()
if ret:
# Get a frame from the video source
self.photo = PIL.ImageTk.PhotoImage(image=PIL.Image.fromarray(frame))
self.Fcanvas.delete(ALL)
self.Fcanvas.create_image(0, 0, image=self.photo, anchor=NW)
self.after_id = self.app.after(int((1 / self.video_cap.frame_rate) * 1000), self.update)
# updating timer
self.time_print()
# updating slider
self.time_bar.set(self.video_cap.get_time()/1000)
except (ValueError, ImportError, AttributeError):
print('No video was loaded')
return
class MyVideoCapture:
def __init__(self, video_source):
# open the video source
self.vid = cv2.VideoCapture(video_source)
if not self.vid.isOpened():
raise ValueError("Unable to open video source", video_source)
# get video source width and height
self.height = self.vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
self.width = self.vid.get(cv2.CAP_PROP_FRAME_WIDTH)
self.frame_rate = self.vid.get(cv2.CAP_PROP_FPS)
def get_frame(self):
if self.vid.isOpened():
ret, frame = self.vid.read()
self.cur_frame_cnt = self.vid.get(cv2.CAP_PROP_POS_FRAMES)
if ret:
# Return a boolean success flag and the current frame converted to BGR
return ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
else:
return ret, None
else:
return False, None
Root()