【opencv-python-headless pillow】

import cv2
import numpy as np
from tkinter import Tk, Button, Canvas, ALL
from threading import Thread
from PIL import Image, ImageTk

# 初始化摄像头
capture = cv2.VideoCapture(0)

# 定义全局变量
canvas_width, canvas_height = 800, 600
capture_area = None
similarity_threshold = 0.7

# 创建主窗口
root = Tk()
root.title("Image Capture and Comparison")

# 创建两个画布
canvas = Canvas(root, width=canvas_width // 2, height=canvas_height)
canvas.pack(side="left")

static_canvas = Canvas(root, width=canvas_width // 2, height=canvas_height)
static_canvas.pack(side="right")

# 捕捉按钮
capture_button = Button(root, text="Capture", command=lambda: Thread(target=on_click, args=(None,)).start())
capture_button.pack(side="bottom")

def update_ui():
    """线程1:更新UI"""
    while True:
        ret, frame = capture.read()
        if not ret:
            break
        
        # 调整帧大小以适应画布
        frame = cv2.resize(frame, (canvas_width // 2, canvas_height))
        
        # 将OpenCV图像转换为PIL图像,并创建一个PhotoImage对象
        img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        photo = ImageTk.PhotoImage(image=Image.fromarray(img))
        
        # 清除旧图像并绘制新图像
        canvas.delete(ALL)
        canvas.create_image(0, 0, image=photo, anchor='nw')
        root.update()

def process_image():
    """线程2:处理图像"""
    global capture_area
    
    while True:
        ret, frame = capture.read()
        if not ret or capture_area is None:
            continue
        
        # 对输入帧进行模板匹配
        result = cv2.matchTemplate(frame, capture_area, cv2.TM_CCOEFF_NORMED)
        _, max_val, _, max_loc = cv2.minMaxLoc(result)
        
        if max_val > similarity_threshold:
            # 计算中心点位置
            center = (max_loc[0] + capture_area.shape[1] // 2,
                      max_loc[1] + capture_area.shape[0] // 2)
            
            # 在图像上绘制中心点和矩形区域
            cv2.circle(frame, center, 5, (0, 0, 255), -1)
            cv2.rectangle(frame, max_loc, (max_loc[0] + capture_area.shape[1], max_loc[1] + capture_area.shape[0]), (0, 0, 255), 2)
            
            # 将处理后的图像显示在左侧画布
            img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            img = cv2.resize(img, (canvas_width // 2, canvas_height))
            photo = ImageTk.PhotoImage(image=Image.fromarray(img))
            canvas.delete(ALL)
            canvas.create_image(0, 0, image=photo, anchor='nw')
            root.update()

def on_click(event):
    """处理鼠标点击事件,选择静态区域"""
    global capture_area
    
    def update_selection(event, x, y):
        global x1, y1
        x1, y1 = event.x, event.y
        static_canvas.delete(ALL)
        static_canvas.create_rectangle(x, y, x1, y1, outline="red")

    def finalize_selection(event, x1, y1):
        global capture_area
        img = cv2.cvtColor(np.array(ImageGrab.grab((canvas_width // 2, 0, canvas_width, canvas_height))), cv2.COLOR_BGR2RGB)
        capture_area = img[min(y, y1):max(y, y1), min(x, x1):max(x, x1)]
        static_canvas.delete(ALL)
        static_canvas.create_image(0, 0, image=ImageTk.PhotoImage(Image.fromarray(capture_area)), anchor='nw')
        static_canvas.unbind("<B1-Motion>")
        static_canvas.unbind("<ButtonRelease-1>")
    
    x, y = event.x, event.y
    static_canvas.bind("<B1-Motion>", lambda e: update_selection(e, x, y))
    static_canvas.bind("<ButtonRelease-1>", lambda e: finalize_selection(e, x, y))

if __name__ == "__main__":
    # 启动两个线程
    Thread(target=update_ui).start()
    Thread(target=process_image).start()
    
    # 进入主循环
    root.mainloop()

    # 释放资源
    capture.release()

'''
使用多线程分别处理UI更新和图像处理。
左侧动态区显示实时图像。
右侧静态区显示捕获的图像,并可以通过鼠标框选特征区域。
模板匹配找出与右侧特征区域相似的区域,并在左侧图像上绘制出来。
用户可以设置相似度阈值(在本例中固定为0.7)
'''

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值