0

I am reasonably inexperienced Python user (v2.7.8) and I am trying to write a GUI that displays an image from a USB camera at a low 640x480 resolution but at the click of a button records a still at the highest resolution of 2592x1944. The GUI is being written in Tkinter. My Tkinter program uses Multiprocessing and Queue to take a frame from the camera, store it in queue and display the frame in the object window. I have had the program working on a Raspberry Pi with PiCamera as a proof of principle but now I need to move the system onto a PC with this USB device (https://www.leopardimaging.com/uploads/LI-OV5640-USB-72_datasheet.pdf). I have tried to port the code using OpenCV2 to control the camera, but as soon as I try to alter the resolution of the camera the program hangs with no error message appearing.

I can write similar code in the Python shell and get it working, although my method for displaying a smaller live feed is clunky:

import numpy as np
from multiprocessing import Process, Queue
from Queue import Empty
import cv2
from PIL import Image, ImageTk
import time
feed_queue = Queue(maxsize=2**4)
live_feed = cv2.VideoCapture(1)
live_feed.set(3,2592)
live_feed.set(4,1944)
live_feed.set(5,15)
while True:
    ret, img = live_feed.read()
    preview_size = (640,480)
    preview_frame = cv2.resize(img, preview_size, interpolation=cv2.INTER_AREA)
    cv2.imshow("input", preview_frame)
    key = cv2.waitKey(10)
    if key == 27:
        cv2.imwrite("output.jpg",img)
        break

However, as soon as I write something similar for working in Tkinter, it all falls down:

def image_capture(feed_queue):
    live_feed = cv2.VideoCapture(1)
    live_feed.set(3,2592)
    live_feed.set(4,1944)
    live_feed.set(5,15)

    while True:
        try:
            flag, frame = live_feed.read()
            if flag == 0:
                break
            feed_queue.put(frame)
            cv2.waitKey(10)
        except:
            live_feed.release()
            continue

def update_image(image_label, feed_queue):
    frame = feed_queue.get()
    preview_size = (640,480)
    preview_frame = cv2.resize(frame, preview_size, interpolation = cv2.INTER_AREA)  
    # Convert the colour space information from CV2's BGR to the more standard RGB for use with the Tkinter widgets using Python Image Library built in functions
    im = cv2.cvtColor(preview_frame, cv2.COLOR_BGR2RGB)
    # Create a reference copy of the original image so that it isn't designated as garbage by Python's memory allocator
    a = Image.fromarray(im)
    # Now convert this duplicate image to the format required by Tkinter and assign it to the Tkinter label widget, named image_label
    b = ImageTk.PhotoImage(image=a)
    image_label.configure(image=b)
    image_label._image_cache = b
    # Update the main window with this new image
    root.update()

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


if __name__ == '__main__':
    feed_queue = Queue(maxsize=2**4)

    p = Process(target=image_capture, args=(feed_queue,))
    p.start()

    # setup the update callback
    root.after(0, func=lambda: update_all(root, image_label, feed_queue))
    print 'root.after was called...'
    root.mainloop()
    print 'mainloop exit'
    p.join()

This may not be the most efficient way of doing it, so I would be grateful for any suggestions on better methods or ways I can get this program working.

Thanks everyone!

NOTE: I may have isolated the issue to putting the image into the queue. I wrote a few commands in the shell code and it crashed at that point

import numpy as np
from multiprocessing import Process, Queue
from Queue import Empty
import cv2
global live_feed
live_feed = cv2.VideoCapture(1)
live_feed.set(3,2592
live_feed.set(4,1944)
live_feed.set(5,15)

def takeapicture():
    global live_feed
    flag, frame = live_feed.read()
    return flag, frame

def makeaq(feed_q):
    global live_feed
    flag, frame = live_feed.read()
    feed_q.put(frame)

feed_q = Queue(maxsize = 2**4)
issue, img = takeapicture()
issue, img.shape
>(True, (1944L, 2592L, 3L))
pin = feed_q.get()

And crash!

Chris
  • 31
  • 8
  • Why are you using opencv to control the camera? – Nallath Aug 27 '15 at 14:46
  • Mainly because it is what I am familiar with. I am more than happy to try something else if it allows me to meet my main criteria - display live image at one size, record still image when prompted at another. – Chris Aug 27 '15 at 15:17
  • Please see my new request here: http://stackoverflow.com/questions/32271964/python-2-7-cv2-tkinter-with-webcam – Chris Aug 28 '15 at 13:17

1 Answers1

0

Although not technically an answer to this question, I have come up with a solution that lets me do what I need to do. Python 2.7 CV2 & Tkinter with webcam

Community
  • 1
  • 1
Chris
  • 31
  • 8