2

以下のスクリプトは、ビデオ ファイルを開き、tkinter ラベルに表示します。フレームの取得は別のプロセスで行われます。

私の問題はquit_()、ビデオがロードされた後に関数を呼び出すと、完全なスクリプトを閉じることに成功しますが (Python インタープリターはアイドル状態になります)、ビデオをロードする前に終了しようとすると、ルート ウィンドウが破棄され、プログラムが実行されたままになります ( Python インタープリターは保留中なので、手動で強制終了する必要があります)。このloadswitch変数は、ビデオの読み込みを検出するtkinter BooleanVarであり、メイン ループに入る前にスクリプトが値の変更を待機するようにします。

問題は、引数としてファイルパスを持たないという事実が何らかの例外をimage_capture()引き起こし、終了の問題が発生することであるように私には思えます。ただし、スクリプトの実行時に例外は発生しません。

ビデオをロードする前に完全なスクリプトを終了させる方法についてのアイデアは大quit_()歓迎です!

私のスクリプト:

#!/usr/bin/python

import numpy as np
from multiprocessing import Process, Queue, Pipe
from Queue import Empty
import cv2
import cv2.cv as cv
from PIL import Image, ImageTk
import time
import Tkinter as tk
import tkMessageBox
import tkFileDialog

#tkinter GUI functions----------------------------------------------------------
def quit_(root, process):
   if tkMessageBox.askokcancel(message='Are you sure you want to quit?', icon='question', title='Quit'):
      process.terminate()
      root.destroy()

def load_win(root, loadswitch, con):
   #create child window when 'load video' button is clicked
   win = tk.Toplevel()
   win.resizable(False, False)
   #displays message, radiobuttons to choose data type, and gets the absolute file path if file
   tk.Label(win, text='Please choose video data type:').grid(column=0, row=0)
   videotype = tk.StringVar()
   videostream = tk.Radiobutton(win, text='Video live stream', variable=videotype, value='videostream').grid(column=0, row=1)
   videofile = tk.Radiobutton(win, text='Video file', variable=videotype, value='videofile').grid(column=0, row=2)
   def load_video(root, win, videotype):
      if videotype.get()=='videostream':
         win.destroy()
         #loadswitch.set(True)   #line to activate when stream capture code implemented
      elif videotype.get()=='videofile':
         filepath = tkFileDialog.askopenfilename()
         win.destroy()
         if filepath:
            loadswitch.set(True)
            con.send(filepath)
         else:
            pass
   tk.Button(win, text='OK', command=lambda: load_video(root, win, videotype)).grid(column=0, row=3)
   root.wait_window(win)

def update_image(image_label, queue, waitframe,root,process):
   if queue.get()==None:
      quit_(root,process)
   else:
      frame = queue.get()
      im = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
      a = Image.fromarray(im)
      b = ImageTk.PhotoImage(image=a)
      image_label.configure(image=b)
      image_label._image_cache = b  # avoid garbage collection
      root.update()
      time.sleep(waitframe)

def update_all(root, image_label, queue,waitframe,process):
   update_image(image_label, queue, waitframe,root,process)
   root.after(0, func=lambda: update_all(root, image_label, queue,waitframe,process))

#multiprocessing image processing functions-------------------------------------
def image_capture(queue,con):
   videopath = con.recv()
   vidFile = cv2.VideoCapture(videopath)#pour mettre la web cam, changer pour 0 et commenter les ligne passant fps et waitframe
   fps = vidFile.get(cv2.cv.CV_CAP_PROP_FPS)
   waitframe = 1/fps
   con.send(waitframe)#sending waitkey duration through pipe to update_image()
   while True:
      try:
         flag, frame=vidFile.read()
         if flag==0:
            queue.put(None)
            break
         else:
            #image processing code goes here
            queue.put(frame)
            cv2.waitKey(10)
      except:
         continue

if __name__ == '__main__':
#initialize multiprocessing
queue = Queue()
pcon, ccon = Pipe()
#start video procesing
p = Process(target=image_capture, args=(queue,ccon))
p.start()
#GUI of root window (les menus arretent la video, car ils occupent le processus...)
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", root.iconify)
root.title('FlowMap 0.1')
root.resizable(False, False)
image_label = tk.Label(master=root)# label for the video frame
image_label.grid(column=0, row=0, columnspan=2, rowspan=1)
#fill label with image until video is loaded
bg_im = ImageTk.PhotoImage(file='logo.png')
image_label['image'] = bg_im
# quit button
quit_button = tk.Button(master=root, text='Quit',command=lambda: quit_(root,p))
quit_button.grid(column=1, row=1)
#load video button and a switch to wait for the videopath to be chosen
loadswitch = tk.BooleanVar(master=root, value=False, name='loadswitch')
load_button = tk.Button(master=root, text='Load video',command=lambda: load_win(root, loadswitch, pcon))
load_button.grid(column=0, row=1)
#print an 'about' window
tkMessageBox.showinfo(message="FlowMap 0.1, (c) Raoul SCHORER 2013")
#wait for input to begin processing
root.wait_variable(loadswitch)
waitframe = pcon.recv()
print 'waitframe is: '+ str(waitframe)
# setup the update callback
root.after(0, func=lambda: update_all(root, image_label, queue, waitframe,p))
#exit program
root.mainloop()
print 'mainloop exit'
p.terminate()
print 'image capture process exit'
4

0 に答える 0