import cv2
from PIL import Image, ImageTk
import tkinter as tk
from tkinter import simpledialog
# 初始化摄像头
cap = cv2.VideoCapture(0)
# 设置窗口大小
window_width, window_height = 800, 600
# 创建主窗口
root = tk.Tk()
root.title("Degain By %%")
# 创建两个画布
left_canvas = tk.Canvas(root, width=window_width // 2, height=window_height)
left_canvas.grid(row=0, column=0)
right_canvas = tk.Canvas(root, width=window_width // 2, height=window_height)
right_canvas.grid(row=0, column=1)
# 用于保存选择框的位置
select_start_x, select_start_y, select_end_x, select_end_y = None, None, None, None
selected_image = None
# 选择框的ID
select_box_id = None
# 截图按钮
def take_snapshot():
global selected_image, select_box_id
"""当点击按钮时,从左画布复制图像到右画布"""
if hasattr(left_canvas, 'image') and left_canvas.image is not None:
# 将图像数据转换为Tkinter可识别的格式并显示在右画布
right_canvas.image = left_canvas.image
right_canvas.create_image(0, 0, image=right_canvas.image, anchor=tk.NW)
select_start_x, select_start_y = 0, 0
select_end_x, select_end_y = 80, 80
draw_selection_box()
right_canvas.bind("<ButtonPress-1>", on_select_start)
right_canvas.bind("<B1-Motion>", on_select_drag)
right_canvas.bind("<ButtonRelease-1>", on_select_end)
def draw_selection_box():
global select_box_id
if select_box_id is not None:
right_canvas.delete(select_box_id)
if select_start_x is not None and select_end_x is not None:
select_box_id = right_canvas.create_rectangle(
select_start_x, select_start_y, select_end_x, select_end_y,
outline='blue', width=2
)
def on_select_start(event):
global select_start_x, select_start_y
select_start_x, select_start_y = event.x, event.y
def on_select_drag(event):
global select_end_x, select_end_y
select_end_x, select_end_y = event.x, event.y
draw_selection_box()
def on_select_end(event):
global select_end_x, select_end_y, selected_image
select_end_x, select_end_y = event.x, event.y
draw_selection_box()
if all([select_start_x, select_start_y, select_end_x, select_end_y]):
# 获取选择区域
cropped_img = crop_and_resize(right_canvas.image, (select_start_x, select_start_y, select_end_x, select_end_y), (30, 30))
# 显示缩略图
right_canvas.create_image(10, 10, image=cropped_img, anchor=tk.NW)
selected_image = cropped_img
# 裁剪并调整大小
def crop_and_resize(img, bbox, size):
box = (bbox[0], bbox[1], bbox[2], bbox[3])
cropped_img = img.crop(box)
resized_img = cropped_img.resize(size, Image.ANTIALIAS)
return ImageTk.PhotoImage(resized_img)
# 更新UI,显示实时图像
def update_frame():
global selected_image
ret, frame = cap.read()
if ret:
frame = cv2.resize(frame, (window_width // 2, window_height))
img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
img_tk = ImageTk.PhotoImage(image=img)
# 在左画布上显示图像
left_canvas.create_image(0, 0, image=img_tk, anchor=tk.NW, tag="image")
left_canvas.image = img_tk
# 如果有选中的图像,则查找相似区域
if selected_image is not None:
find_similar_regions(frame, selected_image)
# 定时器,每隔15毫秒刷新一次图像
left_canvas.after(15, update_frame)
# 查找相似区域
def find_similar_regions(frame, template):
threshold = 0.8 # 相似度阈值
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray_template = cv2.cvtColor(np.array(template), cv2.COLOR_BGR2GRAY)
res = cv2.matchTemplate(gray_frame, gray_template, cv2.TM_CCOEFF_NORMED)
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
cv2.rectangle(frame, pt, (pt[0] + 30, pt[1] + 30), (0, 255, 0), 2)
# 开始更新图像
update_frame()
# 截图按钮
snapshot_button = tk.Button(root, text="图像截取", command=take_snapshot)
snapshot_button.grid(row=1, columnspan=2)
# 进入主循环
root.mainloop()
# 释放摄像头资源
cap.release()