--- tags: Python系統設計 --- # 图像识别 ```python= import subprocess import sys required_packages = ['opencv-python', 'numpy', 'pyautogui', 'keyboard'] for package in required_packages: try: __import__(package if package != 'opencv-python' else 'cv2') except ImportError: print(f"📦 缺少套件 {package},正在安装...") subprocess.check_call([sys.executable, "-m", "pip", "install", package]) import cv2 import numpy as np import pyautogui import time import tkinter as tk import threading import keyboard import traceback # ✅ 新增:显示错误细节 import ctypes import sys try: pyautogui.FAILSAFE = False # === 读取模板 === template = cv2.imread('Boss.bmp', cv2.IMREAD_COLOR) if template is None: raise FileNotFoundError("❌ 模板图像 'Boss.bmp' 无法读取,请检查路径或格式") template_gray = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY) template_h, template_w = template_gray.shape[:2] scales = np.linspace(0.5, 1.5, 20) # === Tkinter 浮动蓝框 === root = tk.Tk() root.attributes('-topmost', True) root.overrideredirect(True) root.attributes('-alpha', 0.4) if sys.platform == "win32": hwnd = ctypes.windll.user32.GetParent(root.winfo_id()) styles = ctypes.windll.user32.GetWindowLongW(hwnd, -20) styles |= 0x80000 | 0x20 # WS_EX_LAYERED | WS_EX_TRANSPARENT ctypes.windll.user32.SetWindowLongW(hwnd, -20, styles) canvas = tk.Canvas(root, bg='white', highlightthickness=0) canvas.pack(fill=tk.BOTH, expand=True) root.geometry("0x0+0+0") def move_window(x, y, w, h): root.geometry(f"{w}x{h}+{x}+{y}") canvas.delete("all") canvas.create_rectangle(0, 0, w, h, outline="blue", width=4) def hide_window(): root.geometry("0x0+0+0") canvas.delete("all") # === 检测函数 === def find_and_show(): while not keyboard.is_pressed('esc'): screenshot = pyautogui.screenshot() img_rgb = np.array(screenshot) img_bgr = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR) img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY) best_val = -1 best_loc = None best_scale = 1.0 for scale in scales: resized = cv2.resize(template_gray, (int(template_w * scale), int(template_h * scale))) if resized.shape[0] > img_gray.shape[0] or resized.shape[1] > img_gray.shape[1]: continue res = cv2.matchTemplate(img_gray, resized, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc = cv2.minMaxLoc(res) if max_val > best_val: best_val = max_val best_loc = max_loc best_scale = scale if best_val > 0.90: w, h = int(template_w * best_scale), int(template_h * best_scale) x, y = best_loc center_x = x + w // 2 center_y = y + h // 2 # 将框放大 3 倍 w_large, h_large = int(w * 2), int(h * 2) x_large = center_x - w_large // 2 y_large = center_y - h_large // 2 # 用 pyautogui 画一个框(可视化辅助) # pyautogui.moveTo(x, y) # pyautogui.dragRel(w, 0, duration=0.1) # pyautogui.dragRel(0, h, duration=0.1) # pyautogui.dragRel(-w, 0, duration=0.1) # pyautogui.dragRel(0, -h, duration=0.1) # hide_window() # 先隐藏蓝框(避免遮挡游戏) pyautogui.moveTo(center_x, center_y, duration=0.2) pyautogui.click() # move_window(x, y, w, h) # 点击后再显示蓝框 # move_window(x_large, y_large, w_large, h_large) # ✅ 改成放大版 print(f"✅ 找到目标于 ({center_x}, {center_y}) 相似度: {best_val:.2f}") else: # hide_window() print("🔍 没有找到目标...") time.sleep(1) print("🛑 检测到 Esc,结束程序") root.destroy() # === 启动检测线程 === threading.Thread(target=find_and_show, daemon=True).start() def on_esc_press(): print("🛑 检测到 Esc,准备退出程式") root.quit() root.destroy() keyboard.add_hotkey('esc', on_esc_press) root.mainloop() except Exception as e: print("❗ 程序发生异常:", str(e)) traceback.print_exc() input("\n⚠️ 按 Enter 退出(查看上方错误讯息)...") ```