python打开相机_创建一个可以使用python3和tkin打开/关闭相机图像的GUI

你在这里所做的有一些基本问题。基本前提是不正确的,因为您不应该继续销毁和重新创建标签小部件来显示图像。相反,只需通过使用新图像调用其configure()方法来更新附加到现有小部件的图像。这是一个性能修复,而不管这里有什么线程问题。一般来说,创建一次小部件并更新它们。这避免了在从UI树中移除和添加小部件时发生的一连串几何更改事件。在

这里的螺纹设计不正确。您不应该从工作线程进行Tk调用。Tk绑定到一个线程,只有事件在线程之间传递。为了说明如何更好地构造它,我修改了代码,使用queue.Queue()将图像帧从opencv读取器线程传递到Tk线程。我们可以发布一个自定义事件来通知UI有一个新的框架准备就绪(<>)。在

最后一个问题是,您应该保留对添加到Tk标签的图像的引用,否则当您不期望它时,它可能会被垃圾回收。因此,我们用每个新图像更新self.photo成员。在import sys

import cv2

import threading

import tkinter as tk

import tkinter.ttk as ttk

from queue import Queue

from PIL import Image

from PIL import ImageTk

class App(tk.Frame):

def __init__(self, parent, title):

tk.Frame.__init__(self, parent)

self.is_running = False

self.thread = None

self.queue = Queue()

self.photo = ImageTk.PhotoImage(Image.new("RGB", (800, 600), "white"))

parent.wm_withdraw()

parent.wm_title(title)

self.create_ui()

self.grid(sticky=tk.NSEW)

self.bind('<>', self.on_next_frame)

parent.wm_protocol("WM_DELETE_WINDOW", self.on_destroy)

parent.grid_rowconfigure(0, weight = 1)

parent.grid_columnconfigure(0, weight = 1)

parent.wm_deiconify()

def create_ui(self):

self.button_frame = ttk.Frame(self)

self.stop_button = ttk.Button(self.button_frame, text="Stop", command=self.stop)

self.stop_button.pack(side=tk.RIGHT)

self.start_button = ttk.Button(self.button_frame, text="Start", command=self.start)

self.start_button.pack(side=tk.RIGHT)

self.view = ttk.Label(self, image=self.photo)

self.view.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

self.button_frame.pack(side=tk.BOTTOM, fill=tk.X, expand=True)

def on_destroy(self):

self.stop()

self.after(20)

if self.thread is not None:

self.thread.join(0.2)

self.winfo_toplevel().destroy()

def start(self):

self.is_running = True

self.thread = threading.Thread(target=self.videoLoop, args=())

self.thread.daemon = True

self.thread.start()

def stop(self):

self.is_running = False

def videoLoop(self, mirror=False):

No=0

cap = cv2.VideoCapture(No)

cap.set(cv2.CAP_PROP_FRAME_WIDTH, 800)

cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 600)

while self.is_running:

ret, to_draw = cap.read()

if mirror is True:

to_draw = to_draw[:,::-1]

image = cv2.cvtColor(to_draw, cv2.COLOR_BGR2RGB)

self.queue.put(image)

self.event_generate('<>')

def on_next_frame(self, eventargs):

if not self.queue.empty():

image = self.queue.get()

image = Image.fromarray(image)

self.photo = ImageTk.PhotoImage(image)

self.view.configure(image=self.photo)

def main(args):

root = tk.Tk()

app = App(root, "OpenCV Image Viewer")

root.mainloop()

if __name__ == '__main__':

sys.exit(main(sys.argv))

我应该补充一点,如果你想在按下停止按钮后显示一个空白图像,你可以将viewlabel小部件设置为一个新的空白图像,如构造函数中所示。在

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值