Python 2.7 CV2及更高版本Tkinter与网络摄像头 [英] Python 2.7 CV2 & Tkinter with webcam

查看:108
本文介绍了Python 2.7 CV2及更高版本Tkinter与网络摄像头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Tkinter制作gui来显示USB摄像机的输出.这是用于显微镜实验的,其想法是gui显示低分辨率的实时流,但是单击按钮则获取高分辨率的图像.我已经能够使用笔记本电脑的内置摄像头(VideoCapture(0))使用该代码,但是当我尝试将代码与预期的摄像头一起使用时(

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

要写入的文件大小为零字节.尽管摄像机仍在打开并且可以通过外壳控制,但原本应该用于输送显示器的框架却变空了.我对为什么内置摄像头可以工作但USB无法使用相同的代码感到困惑.

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.

请帮助...

推荐答案

好的,我想我已经解决了这个问题. 基本上,程序在更改分辨率后一直试图让相机在准备好之前显示下一帧.因此,它返回了None并且程序崩溃了.我已经解决了此问题,方法是使虚拟框架的尺寸与预览图像的尺寸相同,然后用相机中的最后一个有效框架填充该虚拟框架.程序录制高分辨率的静止图像时,将显示最后一帧.另外,为了给程序足够的时间来记录图像,我建立了一个while循环,为相机提供了一段设置的时间来进行自我配置并记录图像.如果出现故障并且超时,我可以创建一种安全关闭程序的方法.下面是新代码,除了处理异常外-可以安全关闭应用程序的样板文件可以放入其中.

OK, I think I've solved the issue. Basically the program was continually trying to ask the camera for the next frame to display before it was ready after changing the resolution. It therefore returned a None and the program crashed. I have solved it by making a dummy frame the same size as the preview image and I fill it with the last valid frame from the camera. While the program is recording the high resolution still image, this last frame is displayed. Also, to give the program enough time to record the image I have set up a while loop to give the camera a set period of time to get itself configured and record the image. If there is a fault and it times out I can create a way to close the program safely. The new code is below, except for handling the exceptions - boilerplate stuff that will close the application safely can go in there.

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

global save_dir
save_dir = "C:/Users/.../"
global runner
runner = 00
global run_num
run_num = "00"

##########################################################################
##########################################################################
global hi_w, hi_h
global lo_w, lo_h
hi_w, hi_h = 2592,1944
lo_w, lo_h = 640,480
#Set up dummy frame
global last_frame
last_frame = np.zeros((lo_h, lo_w, 3), dtype=np.uint8)
global cap
cap = cv2.VideoCapture(1)
cap.set(3, lo_w)
cap.set(4, lo_h)

##########################################################################
##########################################################################
# Define the Tkinter functions

#-- QUIT_ --#
#-----------#
def quit_(root):
    root.destroy()

#---------------------


#-- FUNCTION1 --#
#---------------#
def function1(root):
    global save_dir, run_num
    filename = save_dir + "z01_" + run_num + ".jpeg"
    capture(filename)

#---------------------


#-- FUNCTION2 --#
#---------------#
def function2(root):
    global save_dir, run_num
    filename = save_dir + "z02_" + run_num + ".jpeg"
    capture(filename)

#---------------------


#-- FUNCTION3 --#
#---------------#
def function3(root):
    global save_dir, runner, run_num
    filename = save_dir + "z03_" + run_num + ".jpeg"
    capture(filename)
    runner = runner + 1
    run_num = '{0:02d}'.format(runner)

#---------------------

def capture(filename):
    print 'capturing'
    cap.set(3, hi_w)
    cap.set(4, hi_h)
    print time.time()

    timeout = time.time() + 30
    while time.time() < timeout:
        flag2, frame2 = cap.read()
        if flag2:
            frame2 = cv2.flip(frame2,1)
            cv2.imwrite(filename, frame2)
            cap.set(3, lo_w)
            cap.set(4, lo_h)
            time.sleep(1)
            global counter
            counter = 0
            break
        else:
            time.sleep(1)
    else:
        <code to handle timeout appropriately>

#---------------------       

def show_frame():
    global counter, save_dir, runner, run_num
    flag, frame = cap.read()
    frame = cv2.flip(frame, 1)
    if flag is None:
        print "Major error!"
        <code to handle exception>
    elif flag:
        global last_frame
        last_frame = frame.copy()
    else:
        print "Cant process the image"
        <code to handle exception>

    cv2image = cv2.cvtColor(last_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()

感谢所有提供帮助的人.

Thanks to everyone who helped.

这篇关于Python 2.7 CV2及更高版本Tkinter与网络摄像头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆