可是t = threading.Thread(target=self.windows_display)使用摄像头会闪烁
时间: 2024-03-27 10:35:01 浏览: 145
python中的线程threading.Thread()使用详解
闪烁可能是由于您的UI线程和摄像头线程之间的竞争条件造成的。为了解决这个问题,您可以尝试使用`Queue`来传递图像,而不是直接在UI线程和摄像头线程之间共享数据。具体而言,您可以在摄像头线程中将每个图像放入队列中,然后在UI线程中从队列中读取图像并更新画布。
下面是修改后的代码示例:
```
import threading
import cv2
import tkinter as tk
from tkinter import *
from PIL import Image, ImageTk
from queue import Queue
from Background.Thread_Demo import Thread_data
from Data_demo import data_demo
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):
while self.bool:
ref, frame = self.cap.read()
cv2.waitKey(1)
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.queue.put(photo) # 将图像放入队列中
def update_canvas(self):
if not self.queue.empty():
photo = self.queue.get() # 从队列中获取图像
self.canvas2.create_image(0, 0, image=photo, anchor=tk.NW)
self.canvas2.after(15, self.update_canvas) # 定时更新画布
root = Tk()
camera = Camera(root)
button_id = Button(root, text='打开摄像头', command=lambda: camera.Firing_run(button_id))
button_id.place(relx=0.01, rely=0.01, anchor='nw')
camera.update_canvas() # 启动定时更新画布的函数
root.mainloop()
```
在这个修改后的版本中,我们创建了一个队列,将每个帧的图像放入队列中。然后,在UI线程中,我们使用`update_canvas`函数从队列中获取图像并更新画布。我们使用`after`方法启动定时器,以便每隔一定时间更新画布。这样可以避免UI线程和摄像头线程之间的竞争条件,从而消除闪烁问题。
阅读全文