在Tkinter Python和Open CV中使用网络摄像头单击图像

时间:2015-02-24 07:17:17

标签: python opencv tkinter

我正在尝试开发一个代码,通过该代码我可以访问网络摄像头并在Tkinter窗口中显示视频。我已经能够访问网络摄像头,加载视频,甚至使用参考代码Tkinter nested mainloop停止视频

我想要的还有一个“点击”按钮,该按钮可以捕捉当时的视频帧并显示捕获的帧。此外,应保持代码按下加载按钮并重新加载视频帧的能力。

目前我正在使用此代码 -

from multiprocessing import Process, Queue
import cv2
import ImageTk
from PIL import *
import Image
import Tkinter as tk

def image_capture(queue):
    vidFile = cv2.VideoCapture(0)
    while True:
        flag, frame=vidFile.read()
        frame = cv2.cvtColor(frame,cv2.cv.CV_BGR2RGB)
        queue.put(frame)
        cv2.waitKey(10)

def update_all(root, imagelabel, queue, process, var):
    if var.get()==True:
        global im
        im = queue.get()
        a = Image.fromarray(im)
        b = ImageTk.PhotoImage(image=a)
        imagelabel.configure(image=b)
        imagelabel._image_cache = b
        root.update()
        root.after(0, func=lambda: update_all(root, imagelabel, queue, process, var))
    else:
        print var.get()
        root.quit()

def playvideo(root, imagelabel, queue, var):

    global im
    p = Process(target=image_capture, args=(task,))
    p.start()
    update_all(root, imagelabel, queue, p, var)
    root.mainloop()
    p.terminate()
    if var.get()==False:
        try:
            cv2.imwrite("capturedFrame.jpg",im[:, :, ::-1])
            a = Image.fromarray(im)
            imagelabel.configure(image=a)
            imagelabel._image_cache = im
        except Exception,e:
            print e
    var.set(True)
    print 'finishing'

if __name__ == '__main__':
    try:
        task = Queue()
        root = tk.Tk()
        image_label = tk.Label(master=root)
        image_label.grid(column=0, row=0, columnspan=2, rowspan=1)
        background = ImageTk.PhotoImage(file='img.jpg')
        image_label['image'] = background
        button_frame = tk.Frame(root)
        button_frame.grid(column=0, row=1, columnspan=1)

        load_button = tk.Button(master=button_frame, text='Load video',command=lambda: playvideo(root, image_label, task, switch))
        load_button.grid(column=0, row=0, sticky='ew')

        #Click button
        switch = tk.BooleanVar(master=root, value=True, name='switch')
        stop_button = tk.Button(master=button_frame, text='Click',command=lambda: switch.set(False))
        stop_button.grid(column=0, row=1, sticky='ew')

        #quit button
        quit_button = tk.Button(master=button_frame, text='Quit',command=root.destroy)
        quit_button.grid(column=0, row=2, sticky='ew')
        root.mainloop()

    except Exception,e:
        print e

此代码单击单击按钮上的图像,甚至保存图像,但抛出异常 -

image "<Image.Image image mode=RGB size=640x480 at 0x5494FA8>" doesn't exist

虽然代码有效,但有没有更好的方法从网络摄像头点击并保存这些点击的图像。任何形式的帮助将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:0)

要从相机保存当前帧并保持流式传输,您应该将单击按钮操作与独立功能关联,让我们按如下方式调用saveImage(队列):

def saveImage(queue):
    img = queue.get()
    cv2.imwrite("capturedFrame.jpg",img)

,单击按钮可以声明如下:

click_button = tk.Button(master=button_frame, text='Click',command=lambda: saveImage(task))

其中'task'是您在main函数中启动的队列。