在画布上显示一个启动按钮和一个停止按钮,点击启动按钮后出现摄像头图像,点击停止按钮后关闭摄像头图像
时间: 2023-09-06 14:12:23 浏览: 140
好的,你可以参考以下代码实现:
```python
import tkinter as tk
from tkinter import Canvas, Button
import cv2
from PIL import Image, ImageTk
import threading
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=20, height=1)
self.label.place(relx=0.18, rely=0.50, anchor='nw')
# 创建启动按钮
self.start_button = Button(self.top, text='启动摄像头', font=("黑体", 20), width=10, height=1, command=self.start_camera)
self.start_button.place(relx=0.4, rely=0.01)
# 创建停止按钮
self.stop_button = Button(self.top, text='停止摄像头', font=("黑体", 20), width=10, height=1, command=self.stop_camera)
self.stop_button.place(relx=0.6, rely=0.01)
def start_camera(self):
self.bool = True
self.label.destroy()
self.cap = cv2.VideoCapture(0)
# 创建线程
self.thread = threading.Thread(target=self.windows_display)
self.thread.start()
def stop_camera(self):
self.bool = False
self.label.destroy()
self.cap.release()
self.canvas2.delete('all')
# 显示提示信息
self.label = tk.Label(self.canvas2, text='点击启动按钮启动摄像头', font=("黑体", 25), width=20, height=1)
self.label.place(relx=0.18, rely=0.50, anchor='nw')
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(30)
```
在`__init__`方法中,我们创建了一个启动按钮和一个停止按钮,分别调用`start_camera`和`stop_camera`方法。在`start_camera`方法中,我们使用`threading`模块创建了一个线程,并在其中调用`windows_display`方法显示摄像头图像。在`stop_camera`方法中,我们关闭了摄像头并清空了画布,同时显示提示信息。`windows_display`方法中的代码与之前相同,不再赘述。
注意,在这个实现中我们使用了`self.thread`成员变量来存储线程对象,这是为了在停止摄像头时能够正常关闭线程。如果在启动摄像头之前点击停止按钮,线程对象还未创建,此时需要判断`self.thread`是否存在,若存在则调用`join`方法等待线程结束。
阅读全文