def Firing_run(self, button_id): self.bool = True self.cap = cv2.VideoCapture(0) t = threading.Thread(target=self.windows_display) t.start() button_id.config(text='关闭摄像头', command=lambda: self.Cease_stop(button_id)) def Cease_stop(self, button_id): self.bool = False self.label.destroy() self.canvas2.delete("all") self.label = tk.Label(self.canvas2, text='摄像头显示区!', font=("黑体", 25), width=15, height=1) self.label.place(relx=0.32, rely=0.50, anchor='nw') button_id.config(text='打开摄像头', command=lambda: self.Firing_run(button_id)) def windows_display(self): if self.bool: ref, frame = self.cap.read() if ref: self.label.destroy() self.canvas2.delete("all") image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) image1 = Image.fromarray(image) image2 = image1.resize((self.w, self.h), Image.ANTIALIAS) self.photo = ImageTk.PhotoImage(image=image2) self.canvas2.create_image(0, 0, image=self.photo, anchor=tk.NW) else: self.cap = cv2.VideoCapture(0) self.label.destroy() self.label = tk.Label(self.canvas2, text='未找到摄像头!', font=("黑体", 25), width=15, height=1) self.label.place(relx=0.32, rely=0.50, anchor='nw') self.canvas2.update() self.canvas2.after(15, self.windows_display)怎么停止self.windows_display
时间: 2024-02-14 19:18:57 浏览: 23
可以通过调用Cease_stop方法来停止self.windows_display。在Cease_stop方法中,将self.bool设置为False,这会导致self.windows_display停止递归调用。同时,删除当前self.label并清空self.canvas2。最后,将button_id的文本和命令设置为打开摄像头,并将其命令设置为self.Firing_run(button_id)。
相关问题
class Camera(): def init(self, top): self.top = top self.h = int(data_demo.window_height // 1.5) self.w = int(data_demo.window_width // 1.74) self.canvas2 = Canvas(self.top, bg='LightSkyBlue', width=self.w, height=self.h, highlightthickness=2, highlightbackground='Black') self.canvas2.place(relx=0.0, rely=0.032) self.label = tk.Label(self.canvas2, text='摄像头显示区!', font=("黑体", 25), width=15, height=1) self.label.place(relx=0.32, rely=0.50, anchor='nw') self.queue = Queue() # 创建一个队列 def Firing_run(self, button_id): self.bool = True self.label.destroy() self.cap = cv2.VideoCapture(0) t = threading.Thread(target=self.windows_display) t.start() button_id.config(text='关闭摄像头', command=lambda: self.Cease_stop(button_id)) def Cease_stop(self, button_id): self.bool = False button_id.config(text='打开摄像头', command=lambda: self.Firing_run(button_id)) def windows_display(self): if self.bool: ref, frame = self.cap.read() if ref: image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) image1 = Image.fromarray(image) image2 = image1.resize((self.w, self.h), Image.ANTIALIAS) photo = ImageTk.PhotoImage(image=image2) self.canvas2.create_image(0, 0, image=photo, anchor=tk.NW) self.canvas2.update() self.canvas2.after(15, self.windows_display())用多线程怎么进行优化
可以考虑使用多线程来优化程序,将图像采集和画面显示的任务放到两个不同的线程中执行,避免两个任务之间的阻塞和竞争。具体实现可以按照以下步骤:
1. 创建两个线程,一个用于采集图像数据,一个用于显示图像数据。
2. 采集线程中,使用一个循环不断读取摄像头采集到的图像数据,并将其放入队列中。
3. 显示线程中,从队列中获取图像数据,进行处理和显示,并在一定时间后再次获取队列中的数据进行更新。
4. 在程序运行过程中,可以通过控制标志位的值来控制线程的开启和关闭。
下面是一个使用多线程进行优化的示例代码:
```
import threading
import cv2
import tkinter as tk
from queue import Queue
from PIL import Image, ImageTk
class Camera():
def __init__(self, top):
self.top = top
self.h = int(data_demo.window_height // 1.5)
self.w = int(data_demo.window_width // 1.74)
self.canvas2 = tk.Canvas(self.top, bg='LightSkyBlue', width=self.w, height=self.h, highlightthickness=2, highlightbackground='Black')
self.canvas2.place(relx=0.0, rely=0.032)
self.label = tk.Label(self.canvas2, text='摄像头显示区!', font=("黑体", 25), width=15, height=1)
self.label.place(relx=0.32, rely=0.50, anchor='nw')
self.queue = Queue() # 创建一个队列
self.bool = False # 控制线程开启和关闭的标志位
def Firing_run(self, button_id):
self.bool = True
self.label.destroy()
self.cap = cv2.VideoCapture(0)
t1 = threading.Thread(target=self.capture_image)
t2 = threading.Thread(target=self.show_image)
t1.start()
t2.start()
button_id.config(text='关闭摄像头', command=lambda: self.Cease_stop(button_id))
def Cease_stop(self, button_id):
self.bool = False
button_id.config(text='打开摄像头', command=lambda: self.Firing_run(button_id))
def capture_image(self):
while self.bool:
ref, frame = self.cap.read()
if ref:
self.queue.put(frame)
def show_image(self):
while self.bool:
if not self.queue.empty():
frame = self.queue.get()
image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
image1 = Image.fromarray(image)
image2 = image1.resize((self.w, self.h), Image.ANTIALIAS)
photo = ImageTk.PhotoImage(image=image2)
self.canvas2.create_image(0, 0, image=photo, anchor=tk.NW)
self.canvas2.update()
else:
continue
self.canvas2.after(15)
```
在上面的代码中,我们创建了两个线程,一个用于采集图像数据(capture_image函数),一个用于显示图像数据(show_image函数)。通过队列来进行线程间通信,采集线程从摄像头中读取图像数据,将其放入队列中;显示线程从队列中获取图像数据,并将其进行处理和显示。同时,我们使用了标志位来控制线程的开启和关闭。
class Camera(): def __init__(self, top): self.top = top self.h = int(data_demo.window_height // 1.5) self.w = int(data_demo.window_width // 1.74) self.canvas2 = Canvas(self.top, bg='LightSkyBlue', width=self.w, height=self.h, highlightthickness=2, highlightbackground='Black') self.canvas2.place(relx=0.0, rely=0.032) self.label = tk.Label(self.canvas2, text='摄像头显示区!', font=("黑体", 25), width=15, height=1) self.label.place(relx=0.32, rely=0.50, anchor='nw') def Firing_run(self, button_id): self.bool = True self.label.destroy() self.cap = cv2.VideoCapture(0) t = threading.Thread(target=self.windows_display) t.start() print("1") button_id.config(text='关闭摄像头', command=lambda: self.Cease_stop(button_id)) def Cease_stop(self, button_id): self.bool = False button_id.config(text='打开摄像头', command=lambda: self.Firing_run(button_id)) def windows_display(self): while self.bool: ref, frame = self.cap.read() if ref: image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) image1 = Image.fromarray(image) image2 = image1.resize((self.w, self.h), Image.ANTIALIAS) self.photo = ImageTk.PhotoImage(image=image2) self.canvas2.create_image(0, 0, image=self.photo, anchor=tk.NW) self.canvas2.update() self.canvas2.after(10)它这段代码在画布上显示了摄像头画面但是会一闪一闪的怎么修改
这个闪烁的问题可能是由于在`windows_display()`函数中更新画面时,画布的刷新频率和摄像头采集图像的帧率不一致导致的。你可以尝试将`self.canvas2.after(10)`的参数调大一些,比如改成`self.canvas2.after(30)`或者更大的值,这样可以让画布的刷新频率和摄像头采集图像的帧率更接近,减少闪烁的情况。
如果仍然存在闪烁的问题,可以尝试使用双缓冲机制,即在画布上绘制图像之前,先将图像绘制到一个临时的缓冲区,等到图像完全绘制完成后再将缓冲区中的图像显示在画布上。这可以通过在创建画布时添加`doublebuffer=1`参数来实现,即将`self.canvas2 = Canvas(self.top, bg='LightSkyBlue', width=self.w, height=self.h, highlightthickness=2, highlightbackground='Black')`改为`self.canvas2 = Canvas(self.top, bg='LightSkyBlue', width=self.w, height=self.h, highlightthickness=2, highlightbackground='Black', doublebuffer=1)`。这样做可以减少闪烁的情况。