jack há 2 meses atrás
commit
a3bd220369
3 ficheiros alterados com 238 adições e 0 exclusões
  1. 217 0
      main.py
  2. 21 0
      requirements.txt
  3. BIN
      target_img.png

+ 217 - 0
main.py

@@ -0,0 +1,217 @@
+import pyautogui
+import cv2
+import numpy as np
+import time
+import threading
+from pynput import keyboard
+from pynput.mouse import Button
+import os
+import subprocess
+
+class MacImageClicker:
+    def __init__(self):
+        self.is_monitoring = False
+        self.target_image = None
+        self.confidence_threshold = 0.95
+        self.hotkey = keyboard.Key.f8
+        self.check_interval = 0.5
+        
+        # macOS 特定设置
+        pyautogui.FAILSAFE = True
+        pyautogui.PAUSE = 0.1
+        
+        # 查找目标图片
+        self.target_image_path = self.find_target_image()
+        
+    def find_target_image(self):
+        """在项目根目录查找目标图片"""
+        current_dir = os.getcwd()
+        image_files = []
+        
+        # 查找所有可能的图片文件
+        for file in os.listdir(current_dir):
+            if file.lower().endswith(('.png', '.jpg', '.jpeg')):
+                image_files.append(file)
+        
+        if not image_files:
+            print("在项目根目录未找到任何图片文件 (png, jpg, jpeg)")
+            return None
+            
+        # 优先选择包含 target 关键字的图片
+        target_files = [f for f in image_files if 'target' in f.lower()]
+        if target_files:
+            selected = target_files[0]
+        else:
+            selected = image_files[0]
+            
+        full_path = os.path.join(current_dir, selected)
+        print(f"找到目标图片: {selected}")
+        return full_path
+
+    def load_target_image(self):
+        """加载目标图片"""
+        if not self.target_image_path:
+            print("未找到目标图片文件")
+            return False
+            
+        try:
+            self.target_image = cv2.imread(self.target_image_path)
+            if self.target_image is not None:
+                print(f"成功加载目标图片: {os.path.basename(self.target_image_path)}")
+                print(f"图片尺寸: {self.target_image.shape[1]}x{self.target_image.shape[0]}")
+                return True
+            else:
+                print("图片加载失败,可能是格式不支持")
+                return False
+        except Exception as e:
+            print(f"加载图片时出错: {e}")
+            return False
+
+    def get_screenshot(self):
+        """获取屏幕截图 - macOS 版本"""
+        try:
+            # 使用 pyautogui 截图,在 macOS 上兼容性更好
+            screenshot = pyautogui.screenshot()
+            screenshot_cv = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
+            return screenshot_cv
+        except Exception as e:
+            print(f"截图失败: {e}")
+            return None
+
+    def find_and_click(self):
+        """在屏幕上查找目标图片并点击"""
+        if self.target_image is None:
+            return False
+            
+        try:
+            # 获取屏幕截图
+            screenshot = self.get_screenshot()
+            if screenshot is None:
+                return False
+            
+            # 模板匹配
+            result = cv2.matchTemplate(screenshot, self.target_image, cv2.TM_CCOEFF_NORMED)
+            min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
+            
+            # 调试信息(可选,可以注释掉以减少输出)
+            # print(f"当前匹配度: {max_val:.3f}")
+            
+            if max_val >= self.confidence_threshold:
+                # 计算目标中心位置
+                h, w = self.target_image.shape[:2]
+                center_x = max_loc[0] + w // 2
+                center_y = max_loc[1] + h // 2
+                
+                # 在 macOS 上使用 pyautogui 点击
+                current_pos = pyautogui.position()
+                pyautogui.moveTo(center_x, center_y, duration=0.1)
+                pyautogui.click()
+                
+                # 可选:移回原位置
+                # pyautogui.moveTo(current_pos.x, current_pos.y, duration=0.1)
+                
+                print(f"✅ 点击位置: ({center_x}, {center_y}), 相似度: {max_val:.3f}")
+                return True
+                
+        except Exception as e:
+            print(f"查找或点击时出错: {e}")
+            
+        return False
+
+    def monitoring_loop(self):
+        """监控循环"""
+        print("监控线程启动")
+        while True:
+            if self.is_monitoring:
+                self.find_and_click()
+            time.sleep(self.check_interval)
+
+    def toggle_monitoring(self):
+        """切换监控状态"""
+        self.is_monitoring = not self.is_monitoring
+        
+        if self.is_monitoring:
+            # 开启监控时确保图片已加载
+            if self.target_image is None:
+                if not self.load_target_image():
+                    self.is_monitoring = False
+                    print("❌ 无法加载目标图片,监控未开启")
+                    return
+        
+        status = "🟢 开启" if self.is_monitoring else "🔴 关闭"
+        print(f"监控状态: {status}")
+        
+        if self.is_monitoring:
+            print("开始监控屏幕,寻找目标图片...")
+
+    def on_press(self, key):
+        """键盘按下事件"""
+        if key == self.hotkey:
+            self.toggle_monitoring()
+        elif key == keyboard.Key.esc:
+            # ESC 键退出程序
+            print("退出程序")
+            os._exit(0)
+
+    def check_mac_permissions(self):
+        """检查 macOS 权限"""
+        try:
+            # 尝试截图来测试权限
+            test_screenshot = pyautogui.screenshot()
+            print("✅ 屏幕录制权限: 已授权")
+            return True
+        except Exception:
+            print("❌ 屏幕录制权限: 未授权")
+            print("请前往: 系统设置 > 隐私与安全性 > 屏幕录制")
+            print("为终端或您使用的 IDE 开启屏幕录制权限")
+            return False
+
+    def start(self):
+        """启动程序"""
+        print("🖥️  macOS 图像点击工具")
+        print("=" * 40)
+        
+        # 检查权限
+        if not self.check_mac_permissions():
+            return
+        
+        # 查找并加载目标图片
+        if not self.load_target_image():
+            print("请确保项目根目录有图片文件 (png, jpg, jpeg)")
+            return
+        
+        print(f"🎯 目标图片: {os.path.basename(self.target_image_path)}")
+        print(f"📏 相似度阈值: {self.confidence_threshold}")
+        print(f"🎹 控制快捷键:")
+        print(f"   - F8: 开启/关闭监控")
+        print(f"   - ESC: 退出程序")
+        print("=" * 40)
+        print("等待指令...")
+        
+        # 启动监控线程
+        monitor_thread = threading.Thread(target=self.monitoring_loop, daemon=True)
+        monitor_thread.start()
+        
+        # 启动键盘监听
+        try:
+            with keyboard.Listener(on_press=self.on_press) as listener:
+                listener.join()
+        except KeyboardInterrupt:
+            print("\n程序被用户中断")
+        except Exception as e:
+            print(f"程序出错: {e}")
+
+if __name__ == "__main__":
+    # 确保程序在 macOS 上运行
+    import platform
+    if platform.system() != 'Darwin':
+        print("警告: 这个工具是针对 macOS 优化的")
+        print("但检测到您正在运行:", platform.system())
+        print("继续运行可能遇到兼容性问题")
+        
+        response = input("是否继续? (y/n): ")
+        if response.lower() != 'y':
+            exit()
+    
+    clicker = MacImageClicker()
+    clicker.start()

+ 21 - 0
requirements.txt

@@ -0,0 +1,21 @@
+MouseInfo==0.1.3
+numpy==2.2.6
+opencv-python==4.12.0.88
+pillow==11.3.0
+PyAutoGUI==0.9.54
+PyGetWindow==0.0.9
+PyMsgBox==2.0.1
+pynput==1.8.1
+pyobjc-core==11.1
+pyobjc-framework-ApplicationServices==11.1
+pyobjc-framework-Cocoa==11.1
+pyobjc-framework-CoreText==11.1
+pyobjc-framework-Quartz==11.1
+pyperclip==1.11.0
+PyRect==0.2.0
+PyScreeze==1.0.1
+pytweening==1.2.0
+rubicon-objc==0.5.2
+setuptools==78.1.1
+six==1.17.0
+wheel==0.45.1

BIN
target_img.png