【问题标题】:How to take picture without freezing with tkinter and opencv?如何使用 tkinter 和 opencv 在不冻结的情况下拍照?
【发布时间】:2021-10-29 09:04:16
【问题描述】:

我对编码和 Tkinter 还很陌生,对 opencv 也很陌生。我正在尝试编写简单的网络摄像头应用程序,每次按下按钮时都可以拍摄快照。我有这个代码:

from tkinter import *
from PIL import Image, ImageTk
import cv2

root = Tk()
root.geometry("1200x700")

label =Label(root)
label.grid(row=0, column=0)
cap= cv2.VideoCapture(0, cv2.CAP_DSHOW)

def show_frames():
   cv2image= cv2.cvtColor(cap.read()[1],cv2.COLOR_BGR2RGB)
   img = Image.fromarray(cv2image)
   imgtk = ImageTk.PhotoImage(image = img)
   label.imgtk = imgtk
   label.configure(image=imgtk)
   label.after(20, show_frames)

def key_pressed(event):
   take_pic()

def take_pic():
   cam = cv2.VideoCapture(0, cv2.CAP_DSHOW)
   ###Rest of the photo saving script

show_frames()
root.bind("<Key>", key_pressed)
root.mainloop()

在进一步的版本中,我可以拍摄尽可能多的照片并根据需要多次保存它们,但是在我拍摄第一张照片后,有图片的部分 GUI 似乎冻结了。除此之外,该程序似乎正在运行。其他副作用是第一张之后的每张照片都很暗。看来相机需要一两秒来调整亮度。

我已经确定是 cam = cv2.VideoCapture(0, cv2.CAP_DSHOW) 部分搞砸了,但我不确定如何解决这个问题。

【问题讨论】:

  • 您无需在take_pic() 内再次调用cv2.VideoCapture(...)。在show_frames() 的开头添加global img,然后您可以简单地调用,例如,在take_pic() 中调用img.save('screenshot.png') 以保存捕获图像。其实你可以在key_pressed()里面调用img.save(...),然后take_pic()就可以去掉了。
  • 这是优雅且有效的解决方案。谢谢。

标签: python opencv tkinter webcam


【解决方案1】:

问题在于,在 take_pic 函数中,您正在将 id 为“0”的 cam 重新分配给另一个变量,因此分配给 tkinter 的变量被阻止访问相机。

附加以下修改以存储图像。我将显示的每一帧都存储在一个全局变量中,然后只要按下键,它就会存储这个全局变量的图像。

from tkinter import *
from PIL import Image, ImageTk
import cv2

root = Tk()
root.geometry("1200x700")

label =Label(root)
label.grid(row=0, column=0)
cap= cv2.VideoCapture(0, cv2.CAP_DSHOW)
cv2image = None

def show_frames():
    global cv2image
    cv2image= cv2.cvtColor(cap.read()[1],cv2.COLOR_BGR2RGB)
    img = Image.fromarray(cv2image)
    imgtk = ImageTk.PhotoImage(image = img)
    label.imgtk = imgtk
    label.configure(image=imgtk)
    label.after(20, show_frames)

def key_pressed(event):
    take_pic()

i = 0
def take_pic():
    global i
    cv2.imwrite(f"pics/{i}.jpg", cv2image)
    i += 1
    ###Rest of the photo saving script

show_frames()
root.bind("<Key>", key_pressed)
root.mainloop()

【讨论】:

    【解决方案2】:

    试试这个:

    from tkinter import *
    from PIL import Image, ImageTk
    import cv2
    
    root = Tk()
    root.geometry("1200x700")
    
    label = Label(root)
    label.frame_num = 0
    label.grid(row=0, column=0)
    cap= cv2.VideoCapture(0)
    
    if not cap.isOpened():
        print("Cannot open camera")
        exit()
    
    def show_frames():
       cv2image= cv2.cvtColor(cap.read()[1],cv2.COLOR_BGR2RGB)
       img = Image.fromarray(cv2image)
       imgtk = ImageTk.PhotoImage(image = img)
       label.imgtk = imgtk
       label.frame_num += 1.
       label.configure(image=imgtk)
       label.after(20, show_frames)
    
    def key_pressed(event):
       take_pic()
    
    def take_pic():
        file_name = f"{label.frame_num}.png"
        imagetk = label.imgtk
        imgpil = ImageTk.getimage( imagetk )
        imgpil.save(file_name, "PNG")
        imgpil.close()
    
    
    show_frames()
    root.bind("p", key_pressed)
    root.mainloop()
    

    【讨论】:

    • 我不知道为什么,但这根本不会启动 GUI。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-30
    • 2015-04-02
    • 2014-04-17
    相关资源
    最近更新 更多