下面的代码摘自Kieleth的现有文章,我将其用作较大代码库的子集。我正在尝试利用它捕获每千多个实时帧拍摄一次的帧列表,然后以延时的方式播放。我已经捕获了帧,但是在调用一个简单函数时似乎看不到它们。我在其他文章中看到过,不建议将for循环用于此类事件,但尚未弄清楚如何正确显示。关于这个的任何建议将不胜感激?
from tkinter import ttk
import time
import cv2
from PIL import Image,ImageTk
#import threading
root = Tk()
def video_button1():# this flips between start and stop when video button pressed.
if root.video_btn1.cget('text') == "Stop Video":
root.video_btn1.configure(text = "Start Video")
root.cap.release()
elif root.video_btn1.cget('text') == "Start Video":
root.video_btn1.configure(text = "Stop Video")
root.cap = cv2.VideoCapture(0)
show_frame()
def show_frame():
# if video_btn1.cget('text') == "Stop Video":
global time_lapse_counter
ret, frame = root.cap.read()
if ret:
frame = cv2.flip(frame, 1) #flip image
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img) #converts img into tkinter readable format
root.video_label.imgtk = imgtk
if time_lapse_counter >= 20: # for Every 20 frames, capture one into time_lapse_list
time_lapse_list.append(imgtk)
time_lapse_counter = 0
root.video_label.configure(image=imgtk)
if len(time_lapse_list) == 5: # keep only 4 frames in the list *** debug purposes.
time_lapse_list.pop(0)
time_lapse_counter += 1
video_loop = root.after(40, show_frame)
else:
root.video_btn1.configure(text = "Start Video")
def time_lapse_play():
root.cap.release() #stop capturing video.
for image in time_lapse_list:
print (image, " ", len(time_lapse_list)," ",time_lapse_list) #
#*** I see the print of the pyimagexxx but nothing appears on the video***#
imgtk = image
root.video_label.imgtk = imgtk
root.video_label.configure(image=imgtk)
cv2.waitKey(500)
# video_loop = root.after(500, time_lapse_play)
def setup_widgets(): #simple label and 2 button widget setup
#Setup Top Right Window with pictures
f_width, f_height = 810, 475
root.rightframe= Frame(root, border=0, width=f_width, height = f_height)
root.rightframe.grid(row=0, column=0, padx=10, pady=0)
# Show video in Right Frame
root.cap = cv2.VideoCapture(0)
root.cap.set(cv2.CAP_PROP_FRAME_WIDTH, f_width)
root.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, f_height)
root.video_label = Label(root.rightframe)
root.video_label.grid(row=0, column = 0)
root.video_btn1 = Button(root.rightframe, fg='maroon', bg="yellow", text = "Stop Video", font=("Arial",10),height=0, width = 10, command=video_button1)
root.video_btn1.grid(row=0, column = 1)
root.video_btn2 = Button(root.rightframe, fg='maroon', bg="yellow", text="Time Lapse", font=("Arial",10),height=0, width = 10, command=time_lapse_play)
root.video_btn2.grid(row=1, column = 1)
# Main Code
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
screen_resolution = str(screen_width)+'x'+str(screen_height)
root.geometry(screen_resolution)
time_lapse_counter = 0
time_lapse_list=[]
setup_widgets()
show_frame()
root.mainloop()```
我终于弄明白了这一点。似乎在使用回调时for循环实际上无法正常工作。我已经修改了代码以删除for循环。我敢肯定它可以使用一些改进,但是可以。我不确定如何随着弹出/追加随着时间的推移增加列表图像数而重置列表中的图像计数,我想知道是否有溢出错误。也就是说,几分钟后,列表将包含[pyimage100-pyimage200],几小时后,列表将包含[pyimage1000000-pyimage1000100]。
from tkinter import *
import cv2
from PIL import Image,ImageTk
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg)
import matplotlib.pyplot as plt
root = Tk()
def video_button1():# this flips between start and stop when video button pressed.
if root.video_btn1.cget('text') == "Stop Video":
root.video_btn1.configure(text = "Start Video")
root.cap.release()
elif root.video_btn1.cget('text') == "Start Video":
root.video_btn1.configure(text = "Stop Video")
root.cap = cv2.VideoCapture(0)
root.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 400)
root.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 400)
show_frame()
def show_frame():
# if video_btn1.cget('text') == "Stop Video":
global time_lapse_counter
ret, frame = root.cap.read()
if ret:
frame = cv2.flip(frame, 1) #flip image
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
imgtk = ImageTk.PhotoImage(image=img) #converts img into tkinter readable format
root.video_label.imgtk = imgtk
root.video_label.configure(image=imgtk)
if time_lapse_counter >= 20: # for Every 20 frames, capture one into time_lapse_list
time_lapse_list.append(imgtk)
time_lapse_counter = 0
if len(time_lapse_list) == 100: # keep 99 frames in the list
time_lapse_list.pop(0)
time_lapse_counter += 1
video_loop = root.after(40, show_frame)
else:
root.video_btn1.configure(text = "Start Video")
def time_lapse_play():
root.cap.release() #stop capturing video.
global frame_counter
if frame_counter <= len(time_lapse_list)-1:
imgtk = time_lapse_list[frame_counter] # get image from list
root.video_label.configure(image=imgtk) # update label with image from list
frame_counter += 1
video_loop = root.after(250, time_lapse_play) #wait 250ms until next frame
else:
frame_counter = 0 #reset frame_counter
def setup_widgets(): #simple label and 2 button widget setup
#Setup Top Right Window with pictures
f_width, f_height = 1200, 500
root.rightframe= Frame(root, border=0, width=f_width, height = f_height)
root.rightframe.grid(row=0, column=0, padx=10, pady=0)
# Show video in Right Frame
root.cap = cv2.VideoCapture(0)
root.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 400)
root.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 400)
root.video_label = Label(root.rightframe)
root.video_label.grid(row=0, column = 0)
root.video_btn1 = Button(root.rightframe, fg='maroon', bg="yellow", text =
"Stop Video", font=("Arial",10),height=0, width = 10, command=video_button1)
root.video_btn1.grid(row=0, column = 1)
root.video_btn2 = Button(root.rightframe, fg='maroon', bg="yellow", text="Time Lapse", font=("Arial",10),height=0, width = 10, command=time_lapse_play)
root.video_btn2.grid(row=1, column = 1)
fig = plt.figure(1)
canvas = FigureCanvasTkAgg(fig, root.rightframe)
canvas.get_tk_widget().place(x=700,y=0)
canvas.get_tk_widget().config(border=2, bg="yellow", width=400, height=400)
# Main Code
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
screen_resolution = str(screen_width)+'x'+str(screen_height)
root.geometry(screen_resolution)
time_lapse_counter = 0
frame_counter = 0
time_lapse_list=[]
setup_widgets()
show_frame()
root.mainloop()
`