Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Display an OpenCV video in tkinter using multiprocessing

I am currently trying to develop a GUI for a multiprocessed OpenCV video stream. The code below does succeed in doing that, since it displays the video feed and a 'quit' button, but runs in a strange manner:

  • the program raises a Runtime error in pythonw.exe (I am using windows) on quit (either by the quit button or by closing the window by clicking on 'X') saying the program "requested the Runtime to terminate in an unusual manner"

Any idea as to how to solve that issue would be greatly appreciated!

My code:

#!/usr/bin/python

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

#tkinter GUI functions----------------------------------------------------------
def quit_(root, process):
   process.join()
   root.destroy()

def update_image(image_label, queue):
   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()

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

#multiprocessing image processing functions-------------------------------------
def image_capture(queue):
   vidFile = cv2.VideoCapture(0)
   while True:
      try:
         flag, frame=vidFile.read()
         if flag==0:
            break
         queue.put(frame)
         cv2.waitKey(20)
      except:
         continue

if __name__ == '__main__':
   queue = Queue()
   print 'queue initialized...'
   root = tk.Tk()
   print 'GUI initialized...'
   image_label = tk.Label(master=root)# label for the video frame
   image_label.pack()
   print 'GUI image label initialized...'
   p = Process(target=image_capture, args=(queue,))
   p.start()
   print 'image capture process has started...'
   # quit button
   quit_button = tk.Button(master=root, text='Quit',command=lambda: quit_(root,p))
   quit_button.pack()
   print 'quit button initialized...'
   # setup the update callback
   root.after(0, func=lambda: update_all(root, image_label, queue))
   print 'root.after was called...'
   root.mainloop()
   print 'mainloop exit'
   p.join()
   print 'image capture process exit'
  • Config: Windows 7 Home, Python 2.7.5, OpenCV 2.4
  • Disclaimer: the code above was inspired by this one.
like image 398
Raoul Avatar asked Jun 12 '13 18:06

Raoul


1 Answers

I solved it by using process.terminate() instead of process.join() in the quit_(root, process) function.

like image 137
Raoul Avatar answered Sep 23 '22 15:09

Raoul