I am using Tkinter to make a gui to display the output from a usb camera. It is for a microscopy experiment with the idea being that the gui shows a low resolution live stream, but at the click of a button a high resolution image is taken. I have been able to get the code working with the inbuilt webcam of my laptop, (VideoCapture(0)) but when I try and use the code with the intended webcam (https://www.leopardimaging.com/uploads/LI-OV5640-USB-72_datasheet.pdf - VideoCapture(1)) it crashes. The code is this:

import Tkinter as tk
import cv2
import cv2.cv as cv
import numpy as np
from PIL import Image, ImageTk

global counter
counter = 0
global save_dir
save_dir = "C:/Users/etc..."
global runner
runner = 50
global run_num
run_num = "50"
##########################################################################
global hi_w, hi_h
global lo_w, lo_h
hi_w, hi_h = 640,480 # Camera intended resolution 2592,1944
lo_w, lo_h = 320,240 # Camera intended resolution 640,480
cap = cv2.VideoCapture(1)
cap.set(3, lo_w)
cap.set(4, lo_h)
cap.set(5,15)
##########################################################################
# Define the Tkinter functions

#-- QUIT_ --#
#-----------#
def quit_(root):
    root.destroy()    
#---------------------
#-- FUNCTION1 --#
#---------------#
def function1(root):
    global counter
    counter = 1    
#---------------------
#-- FUNCTION2 --#
#---------------#
def function2(root):
    global counter
    counter = 2    
#---------------------
#-- FUNCTION3 --#
#---------------#
def function3(root):
    global counter
    counter = 3    
#---------------------
def capture(filename):
    print 'capturing'
    global hi_w, hi_h, lo_w, lo_h
    cap.set(3, hi_w)
    cap.set(4, hi_h)
    flag2, frame2 = cap.read()
    frame2 = cv2.flip(frame2, 1)
    print 'writing'
    cv2.imwrite(filename, frame2)
    print 'resetting'
    cap.set(3, lo_w)
    cap.set(4, lo_h)
    del flag2, frame2
    global counter
    counter = 0

def show_frame():
    #Set up dummy frame
    global counter, save_dir, runner, run_num
    if counter == 1:
        flag,frame = cap.read()
        filename = save_dir + "z01_" + run_num + ".jpeg"
        capture(filename)
    elif counter == 2:
        flag, frame = cap.read()
        filename = save_dir + "z02_" + run_num + ".jpeg"
        capture(filename)
    elif counter == 3:
        flag, frame = cap.read()
        filename = save_dir + "z03_" + run_num + ".jpeg"
        capture(filename)
        runner = runner + 1
        run_num = '{0:02d}'.format(runner)
        counter = 0
    else:
            flag, frame = cap.read()
            frame = cv2.flip(frame, 1)

    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    img = Image.fromarray(cv2image)
    imgtk = ImageTk.PhotoImage(image=img)
    lmain.imgtk = imgtk
    lmain.configure(image=imgtk)
    lmain.after(10, show_frame)


if __name__ == '__main__':
    root = tk.Tk()
    lmain = tk.Label(master=root)
    lmain.grid(column=0, rowspan=4, padx=5, pady=5)

    button1 = tk.Button(master=root, text='Function 1', command=lambda: function1(root))
    button1.grid(column=1, columnspan=2, row=0, padx=5, pady=5)
    button2 = tk.Button(master=root, text='Function 2', command=lambda: function2(root))
    button2.grid(column=1, columnspan=2, row=1, padx=5, pady=5)
    button3 = tk.Button(master=root, text='Function 3', command=lambda: function3(root))
    button3.grid(column=1, columnspan=2, row=2, padx=5, pady=5)
    quit_button = tk.Button(master=root, text='Quit',bg="red3", fg="white", command=lambda: quit_(root))
    quit_button.grid(column=1, row=3, padx=5, pady=5)

    show_frame()
    root.mainloop()
    cap.release()

The program crashes after the first button press with the following error:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1486, in __call__
    return self.func(*args)
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 533, in callit
    func(*args)
  File "C:/Users/.../LI_USB_GUI_RR_worksWithInBuiltCam2.py", line 109, in show_frame
    cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
error: ..\..\..\..\opencv\modules\imgproc\src\color.cpp:3648: error: (-215) scn == 3 || scn == 4 in function cv::cvtColor

The file that is meant to have been written is zero bytes in size. The frame that is supposed to be there to feed the display has become empty, although the camera is still on and controllable through shell. I am really perplexed as to why the inbuilt camera will work but a USB won't with the same code.

Please help...

First, pygame is probably a better option to display a stream. The end-of-file pointer is not updated until the file is closed so it shows zero length. I can't tell from the code if the file is closed or not after the capture and write. You want something similar to an SQL file that has a manager running independently to handle read and writes simultaneously. Otherwise, you will have to do something like read x bytes from the file, or close the file every second or so, opening a different one for the next write sequence, and then it can be read. Perhaps someone else will have more info. To test this I would suggest that you read from the camera, close the "read" program, then open the Tkinter program and see if it can then display the file from the camera capture.

Edited 1 Year Ago by woooee

This article has been dead for over six months. Start a new discussion instead.