在 Tkinter Python 中使用网络摄像头单击图像并打开 CV

Clicking an image using webcam in Tkinter Python and Open CV

我正在尝试开发一个代码,通过它我可以访问网络摄像头并在 Tkinter 中显示视频 Window。我已经能够使用参考代码 Tkinter nested mainloop

访问网络摄像头、加载视频,甚至停止视频

另外我想要的是有一个 "CLICK" 按钮,它可以捕捉那一瞬间的视频帧并显示捕捉到的帧。此外,应保持代码按下加载按钮和重新加载视频帧的能力。

目前我正在使用这个代码-

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

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

要保存来自相机的当前帧并保持流式传输,您应该将您的点击按钮操作与一个独立的函数相关联,让我们按如下方式调用 saveImage(queue):

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' 是您在主函数中启动的队列。