吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1456|回复: 14
上一主题 下一主题
收起左侧

[Python 转载] 图像识别点击 [图像识别自动点击按键精灵] 修改版

  [复制链接]
跳转到指定楼层
楼主
gzsklsskszngc 发表于 2024-9-19 23:49 回帖奖励
本帖最后由 gzsklsskszngc 于 2024-9-19 23:54 编辑

首先感谢原贴作者提供的代码:https://www.52pojie.cn/forum.php?mod=viewthread&tid=1965479&highlight=%CD%BC%CF%F1
我在原代码的基础上做了以下小修改
1.将原按顺序点击模版图像修改为如果找到匹配区域,则模拟点击操作,并可以输入相应的键盘输入。如果没有找到匹配区域,则等待一段时间后重试,直到匹配到图像才继续下一步骤,避免程序无脑乱按。
2.增加热键设置功能,用户可自定义快捷键来启动/停止运行程序
3.增加步骤名称,方便用户识别脚步
4.去除延迟时间,改为默认100毫秒
5.增加保存和加载配置功能,用户点击“保存配置”按钮,将当前配置保存到文件。用户点击“加载配置”按钮,从文件中加载配置,并更新界面显示。
6.原程序启动后根本停不下来,所以我增加了循环次数,当脚本运行完成后,或用户点击“停止运行”按钮,停止脚本。
7.增加图像相似度调整,提高匹配几率
8.增加日志记录
9.本来想增加图像预览功能,没成功
10.后续考虑增加条件判断,检测截图模版是否匹配成功等

操作:
左键双击编辑步骤名称
右键双击编辑相似度
中键双击编辑键盘输入
欢迎提出建议
再次感谢原作者@chh322

上代码:
[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import filedialog, simpledialog, ttk, messagebox
from PIL import Image, ImageTk, ImageGrab, ImageEnhance
import cv2
import numpy as np
import pyautogui
import time
import random
import threading
import logging
import os
import json

class ImageRecognitionApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图像识别与点击")
        self.image_list = []  # 存储 (图像路径, 步骤名称, 相似度, 键盘输入)
        self.screenshot_area = None  # 用于存储截图区域
        self.rect = None  # 用于存储 Canvas 上的矩形
        self.start_x = None
        self.start_y = None
        self.canvas = None
        self.running = False  # 控制脚本是否在运行
        self.thread = None  # 用于保存线程
        self.hotkey = '<F1>'  # 默认热键
        self.similarity_threshold = 0.8  # 默认相似度阈值
        self.delay_time = 0.1  # 默认延迟时间
        self.loop_count = 1  # 默认循环次数
        self.init_ui()
        self.init_logging()
        self.load_config()

    def init_ui(self):
        # 主框架布局
        self.main_frame = tk.Frame(self.root)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 左侧布局:上传图片、截图、运行脚本按钮
        self.left_frame = tk.Frame(self.main_frame)
        self.left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)

        # 批量上传图片按钮
        self.batch_upload_button = tk.Button(self.left_frame, text="上传图像", command=self.batch_upload_images)
        self.batch_upload_button.pack(pady=5)

        # 框选截图按钮(微信风格截图)
        self.screenshot_button = tk.Button(self.left_frame, text="框选截图", command=self.prepare_capture_screenshot)
        self.screenshot_button.pack(pady=5)

        # 删除选中图片按钮
        self.delete_button = tk.Button(self.left_frame, text="删除图片", command=self.delete_selected_image)
        self.delete_button.pack(pady=5)

        # 运行/停止脚本按钮
        self.toggle_run_button = tk.Button(self.left_frame, text="开始运行", command=self.toggle_script)
        self.toggle_run_button.pack(pady=5)

        # 保存配置按钮
        self.save_config_button = tk.Button(self.left_frame, text="保存配置", command=self.save_config)
        self.save_config_button.pack(pady=5)

        # 设置热键按钮
        self.set_hotkey_button = tk.Button(self.left_frame, text="设置热键", command=self.set_hotkey)
        self.set_hotkey_button.pack(pady=5)

        # 手动加载配置按钮
        self.load_config_button = tk.Button(self.left_frame, text="加载配置", command=self.load_config_manually)
        self.load_config_button.pack(pady=5)

        # 循环次数输入框
        self.loop_count_label = tk.Label(self.left_frame, text="循环次数:")
        self.loop_count_label.pack(pady=5)
        self.loop_count_entry = tk.Entry(self.left_frame)
        self.loop_count_entry.insert(0, str(self.loop_count))
        self.loop_count_entry.pack(pady=5)

        # 右侧布局:图像列表显示
        self.right_frame = tk.Frame(self.main_frame)
        self.right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)

        # 使用 Treeview 来显示图片和等待时间
        self.tree = ttk.Treeview(self.right_frame, columns=("图片", "步骤名称", "相似度", "键盘输入"), show='headings')
        self.tree.heading("图片", text="图片")
        self.tree.heading("步骤名称", text="步骤名称")
        self.tree.heading("相似度", text="相似度")
        self.tree.heading("键盘输入", text="键盘输入")
        self.tree.column("图片", width=200)  # 调整图片列宽度
        self.tree.column("步骤名称", width=100)  # 调整步骤名称列宽度
        self.tree.column("相似度", width=100)  # 调整相似度列宽度
        self.tree.column("键盘输入", width=100)  # 调整键盘输入列宽度
        self.tree.pack(fill=tk.BOTH, expand=True, pady=5)
        self.tree.bind('<Double-1>', self.edit_image_name)  # 左键双击编辑步骤名称
        self.tree.bind('<Double-3>', self.edit_similarity_threshold)  # 右键双击编辑相似度
        self.tree.bind('<Double-2>', self.edit_keyboard_input)  # 中键双击编辑键盘输入
        self.tree.image_refs = []  # 保持对图像的引用,防止被垃圾回收

        # 绑定热键
        self.root.bind(self.hotkey, self.toggle_script)

    def init_logging(self):
        logging.basicConfig(filename='app.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

    def batch_upload_images(self):
        file_paths = filedialog.askopenfilenames(filetypes=[("Image files", "*.jpg *.png")])
        if file_paths:
            for file_path in file_paths:
                self.image_list.append((file_path, os.path.basename(file_path), 0.8, ""))
            self.update_image_listbox()

    def prepare_capture_screenshot(self):
        # 隐藏主窗口
        self.root.withdraw()
        time.sleep(0.5)

        # 创建一个全屏幕的透明窗口,用于捕获框选区域
        self.top = tk.Toplevel(self.root)
        self.top.attributes('-fullscreen', True)
        self.top.attributes('-alpha', 0.3)  # 透明度设置

        # 在窗口上创建 Canvas
        self.canvas = tk.Canvas(self.top, cursor="cross", bg='grey')
        self.canvas.pack(fill=tk.BOTH, expand=True)

        # 绑定鼠标事件
        self.canvas.bind("<ButtonPress-1>", self.on_button_press)
        self.canvas.bind("<B1-Motion>", self.on_mouse_drag)
        self.canvas.bind("<ButtonRelease-1>", self.on_button_release)

    def on_button_press(self, event):
        # 记录起始点坐标
        self.start_x = event.x
        self.start_y = event.y
        # 如果有之前的矩形,删除
        if self.rect:
            self.canvas.delete(self.rect)
        # 创建新的矩形框
        self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline='red', width=2)

    def on_mouse_drag(self, event):
        # 动态更新矩形框的大小
        cur_x, cur_y = (event.x, event.y)
        self.canvas.coords(self.rect, self.start_x, self.start_y, cur_x, cur_y)

    def on_button_release(self, event):
        # 记录终点坐标
        end_x = event.x
        end_y = event.y

        # 获取截图区域
        bbox = (min(self.start_x, end_x), min(self.start_y, end_y), max(self.start_x, end_x), max(self.start_y, end_y))

        # 使用规则 "JT******.png" 命名截图文件
        timestamp = f"JT{random.randint(100000, 999999)}.png"
        screenshot_path = timestamp

        # 截图指定区域
        screenshot = ImageGrab.grab(bbox)
        screenshot.save(screenshot_path)

        # 更新图像列表
        self.image_list.append((screenshot_path, timestamp, 0.8, ""))
        self.update_image_listbox()

        # 关闭全屏透明窗口
        self.top.destroy()
        self.root.deiconify()

    def update_image_listbox(self):
        # 清空旧的列表项
        for row in self.tree.get_children():
            self.tree.delete(row)

        # 插入新项,显示图片路径和等待时间
        for img_path, img_name, similarity_threshold, keyboard_input in self.image_list:
            # 加载图像并创建缩略图
            image = Image.open(img_path)
            image.thumbnail((50, 50))  # 调整缩略图大小
            photo = ImageTk.PhotoImage(image)

            # 插入图像和等待时间
            self.tree.insert("", tk.END, values=(img_path, img_name, similarity_threshold, keyboard_input), image=photo)
            self.tree.image_refs.append(photo)  # 保持对图像的引用,防止被垃圾回收

    def edit_image_name(self, event):
        # 左键双击列表项,编辑步骤名称
        selected_item = self.tree.selection()[0]
        selected_index = self.tree.index(selected_item)
        selected_image = self.image_list[selected_index]

        # 弹出对话框修改步骤名称
        new_image_name = simpledialog.askstring("修改步骤名称", "请输入新的步骤名称:", initialvalue=selected_image[1])
        if new_image_name is not None:
            self.image_list[selected_index] = (selected_image[0], new_image_name, selected_image[2], selected_image[3])
            self.update_image_listbox()

    def edit_similarity_threshold(self, event):
        # 右键双击列表项,编辑相似度
        selected_item = self.tree.selection()[0]
        selected_index = self.tree.index(selected_item)
        selected_image = self.image_list[selected_index]

        # 弹出对话框修改相似度
        new_similarity_threshold = simpledialog.askfloat("修改相似度", "请输入新的相似度(0.1 - 1.0):", initialvalue=selected_image[2], minvalue=0.1, maxvalue=1.0)
        if new_similarity_threshold is not None:
            self.image_list[selected_index] = (selected_image[0], selected_image[1], new_similarity_threshold, selected_image[3])
            self.update_image_listbox()

    def edit_keyboard_input(self, event):
        # 中键双击列表项,编辑键盘输入
        selected_item = self.tree.selection()[0]
        selected_index = self.tree.index(selected_item)
        selected_image = self.image_list[selected_index]

        # 弹出对话框修改键盘输入
        new_keyboard_input = simpledialog.askstring("修改键盘输入", "请输入新的键盘输入:", initialvalue=selected_image[3])
        if new_keyboard_input is not None:
            self.image_list[selected_index] = (selected_image[0], selected_image[1], selected_image[2], new_keyboard_input)
            self.update_image_listbox()

    def delete_selected_image(self):
        # 删除选中的图片
        selected_item = self.tree.selection()
        if selected_item:
            selected_index = self.tree.index(selected_item[0])
            del self.image_list[selected_index]
            self.update_image_listbox()

    def toggle_script(self, event=None):
        if not self.running:
            self.start_script_thread()
            self.toggle_run_button.config(text="停止运行")
        else:
            self.stop_script()
            self.toggle_run_button.config(text="开始运行")

    def start_script_thread(self):
        if not self.running:
            self.running = True
            self.thread = threading.Thread(target=self.run_script, daemon=True)
            self.thread.start()

    def run_script(self):
        # 获取循环次数
        self.loop_count = int(self.loop_count_entry.get())
        current_loop = 0

        # 按顺序执行所有图片的模板匹配并点击
        while self.running and current_loop < self.loop_count:
            for img_path, img_name, similarity_threshold, keyboard_input in self.image_list:
                if not self.running:
                    break
                while self.running:
                    if self.match_and_click(img_path, similarity_threshold):
                        if keyboard_input:
                            pyautogui.write(keyboard_input)
                        break
                    time.sleep(self.delay_time)  # 等待延迟时间后重试
            current_loop += 1

    def stop_script(self):
        self.running = False
        if self.thread is not None:
            self.thread.join()  # 等待线程结束
        print("脚本已停止")
        logging.info("脚本已停止")

    def match_and_click(self, template_path, similarity_threshold):
        # 截取当前屏幕
        screenshot = pyautogui.screenshot()
        screenshot = np.array(screenshot)
        screenshot = cv2.cvtColor(screenshot, cv2.COLOR_RGB2BGR)

        # 读取模板图像
        template = cv2.imread(template_path, 0)
        if template is None:
            print(f"无法读取图像: {template_path}")
            logging.error(f"无法读取图像: {template_path}")
            return False

        # 转换截图为灰度图像
        gray_screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)

        # 进行模板匹配
        result = cv2.matchTemplate(gray_screenshot, template, cv2.TM_CCOEFF_NORMED)
        loc = np.where(result >= similarity_threshold)

        # 如果找到了相似区域,模拟点击
        found = False
        for pt in zip(*loc[::-1]):
            # 计算点击点的位置
            click_x = pt[0] + template.shape[1] // 2
            click_y = pt[1] + template.shape[0] // 2
            # 模拟点击
            pyautogui.click(click_x, click_y)
            found = True
            break  # 点击一次后跳出

        if not found:
            print(f"未找到匹配区域: {template_path}")
            logging.warning(f"未找到匹配区域: {template_path}")
            return False

        return True

    def set_hotkey(self):
        # 设置热键
        new_hotkey = simpledialog.askstring("设置热键", "请输入新的热键(例如:<F1>):", initialvalue=self.hotkey)
        if new_hotkey is not None:
            self.hotkey = new_hotkey
            self.root.bind(self.hotkey, self.toggle_script)
            print(f"热键已设置为: {self.hotkey}")
            logging.info(f"热键已设置为: {self.hotkey}")

    def save_config(self):
        config = {
            "image_list": self.image_list,
            "hotkey": self.hotkey,
            "screenshot_area": self.screenshot_area,
            "similarity_threshold": self.similarity_threshold,
            "delay_time": self.delay_time,
            "loop_count": self.loop_count
        }
        with open('config.json', 'w') as f:
            json.dump(config, f)
        print("配置已保存")
        logging.info("配置已保存")

    def load_config(self):
        if os.path.exists('config.json'):
            with open('config.json', 'r') as f:
                config = json.load(f)
                self.image_list = config.get("image_list", [])
                self.hotkey = config.get("hotkey", '<F1>')
                self.screenshot_area = config.get("screenshot_area", None)
                self.similarity_threshold = config.get("similarity_threshold", 0.8)
                self.delay_time = config.get("delay_time", 0.1)
                self.loop_count = config.get("loop_count", 1)
                self.loop_count_entry.delete(0, tk.END)
                self.loop_count_entry.insert(0, str(self.loop_count))
                self.root.bind(self.hotkey, self.toggle_script)
                self.update_image_listbox()
            print("配置已加载")
            logging.info("配置已加载")

    def load_config_manually(self):
        file_path = filedialog.askopenfilename(filetypes=[("JSON files", "*.json")])
        if file_path:
            with open(file_path, 'r') as f:
                config = json.load(f)
                self.image_list = config.get("image_list", [])
                self.hotkey = config.get("hotkey", '<F1>')
                self.screenshot_area = config.get("screenshot_area", None)
                self.similarity_threshold = config.get("similarity_threshold", 0.8)
                self.delay_time = config.get("delay_time", 0.1)
                self.loop_count = config.get("loop_count", 1)
                self.loop_count_entry.delete(0, tk.END)
                self.loop_count_entry.insert(0, str(self.loop_count))
                self.root.bind(self.hotkey, self.toggle_script)
                self.update_image_listbox()
            print("配置已加载")
            logging.info("配置已加载")

if __name__ == "__main__":
    root = tk.Tk()
    app = ImageRecognitionApp(root)
    root.mainloop()





免费评分

参与人数 8吾爱币 +7 热心值 +5 收起 理由
小色虫 + 1 大佬,来做个quicker动作
MiluChild + 1 + 1 用心讨论,共获提升!
lkl2425572 + 1 期待成品,感谢楼主
yjn866y + 1 + 1 热心回复!
chesterche + 1 可以后台吗?
helh0275 + 1 + 1 谢谢@Thanks!
zhufengwan + 1 + 1 谢谢@Thanks!
lgc81034 + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

来自 5#
zkpy 发表于 2024-9-20 04:13
[Asm] 纯文本查看 复制代码
import tkinter as tk
from tkinter import filedialog, simpledialog, ttk, messagebox
from PIL import Image, ImageTk, ImageGrab, ImageEnhance
import cv2
import numpy as np
import pyautogui
import time
import random
import threading
import logging
import os
import json

class ImageRecognitionApp:
    def __init__(self, root):
        self.root = root
        self.root.title("图像识别与点击")
        self.image_list = []
        self.init_variables()
        self.init_ui()
        self.init_logging()
        self.load_config()

    def init_variables(self):
        self.screenshot_area = None
        self.rect = None
        self.start_x = self.start_y = None
        self.canvas = None
        self.running = False
        self.thread = None
        self.hotkey = '<F1>'
        self.similarity_threshold = 0.8
        self.delay_time = 0.1
        self.loop_count = 1
        self.selected_image = None
        self.preview_photo = None  # Added to store the reference to the preview image

    def init_ui(self):
        self.main_frame = tk.Frame(self.root)
        self.main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)

        self.create_left_frame()
        self.create_right_frame()

        self.root.bind(self.hotkey, self.toggle_script)

    def create_left_frame(self):
        self.left_frame = tk.Frame(self.main_frame)
        self.left_frame.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)

        buttons = [
            ("上传图像", self.batch_upload_images),
            ("框选截图", self.prepare_capture_screenshot),
            ("删除图片", self.delete_selected_image),
            ("开始运行", self.toggle_script),
            ("保存配置", self.save_config),
            ("设置热键", self.set_hotkey),
            ("加载配置", self.load_config_manually)
        ]

        for text, command in buttons:
            tk.Button(self.left_frame, text=text, command=command).pack(pady=5)

        self.create_loop_count_input()

    def create_loop_count_input(self):
        tk.Label(self.left_frame, text="循环次数:").pack(pady=5)
        self.loop_count_entry = tk.Entry(self.left_frame)
        self.loop_count_entry.insert(0, str(self.loop_count))
        self.loop_count_entry.pack(pady=5)

    def create_right_frame(self):
        self.right_frame = tk.Frame(self.main_frame)
        self.right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)

        self.create_tree_view()
        self.create_preview_area()

    def create_tree_view(self):
        self.tree_frame = tk.Frame(self.right_frame)
        self.tree_frame.pack(side=tk.TOP, fill=tk.BOTH, expand=True)

        columns = ("图片", "步骤名称", "相似度", "键盘输入")
        self.tree = ttk.Treeview(self.tree_frame, columns=columns, show='headings')
        
        for col in columns:
            self.tree.heading(col, text=col)
            self.tree.column(col, width=100)

        self.tree.column("图片", width=200)
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, pady=5)
        self.tree.bind('<<TreeviewSelect>>', self.on_treeview_select)
        self.tree.bind('<Double-1>', self.edit_image_name)
        self.tree.bind('<Double-3>', self.edit_similarity_threshold)
        self.tree.bind('<Double-2>', self.edit_keyboard_input)

        self.scrollbar = ttk.Scrollbar(self.tree_frame, orient="vertical", command=self.tree.yview)
        self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.configure(yscrollcommand=self.scrollbar.set)

    def create_preview_area(self):
        self.preview_frame = tk.Frame(self.right_frame)
        self.preview_frame.pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True, pady=10)

        tk.Label(self.preview_frame, text="图片预览").pack()
        self.preview_image = tk.Label(self.preview_frame)
        self.preview_image.pack()

    def init_logging(self):
        logging.basicConfig(filename='app.log', level=logging.INFO, 
                            format='%(asctime)s - %(levelname)s - %(message)s')

    def batch_upload_images(self):
        file_paths = filedialog.askopenfilenames(filetypes=[("Image files", "*.jpg *.png")])
        if file_paths:
            for file_path in file_paths:
                self.image_list.append((file_path, os.path.basename(file_path), 0.8, ""))
            self.update_image_listbox()

    def prepare_capture_screenshot(self):
        self.root.withdraw()
        time.sleep(0.5)
        self.create_screenshot_window()

    def create_screenshot_window(self):
        self.top = tk.Toplevel(self.root)
        self.top.attributes('-fullscreen', True, '-alpha', 0.3)
        self.canvas = tk.Canvas(self.top, cursor="cross", bg='grey')
        self.canvas.pack(fill=tk.BOTH, expand=True)
        self.canvas.bind("<ButtonPress-1>", self.on_button_press)
        self.canvas.bind("<B1-Motion>", self.on_mouse_drag)
        self.canvas.bind("<ButtonRelease-1>", self.on_button_release)

    def on_button_press(self, event):
        self.start_x = event.x
        self.start_y = event.y
        if self.rect:
            self.canvas.delete(self.rect)
        self.rect = self.canvas.create_rectangle(self.start_x, self.start_y, self.start_x, self.start_y, outline='red', width=2)

    def on_mouse_drag(self, event):
        cur_x, cur_y = (event.x, event.y)
        self.canvas.coords(self.rect, self.start_x, self.start_y, cur_x, cur_y)

    def on_button_release(self, event):
        end_x = event.x
        end_y = event.y

        bbox = (min(self.start_x, end_x), min(self.start_y, end_y), max(self.start_x, end_x), max(self.start_y, end_y))

        timestamp = f"JT{random.randint(100000, 999999)}.png"
        screenshot_path = timestamp

        screenshot = ImageGrab.grab(bbox)
        screenshot.save(screenshot_path)

        self.image_list.append((screenshot_path, timestamp, 0.8, ""))
        self.update_image_listbox()

        self.top.destroy()
        self.root.deiconify()

    def update_image_listbox(self):
        for row in self.tree.get_children():
            self.tree.delete(row)

        self.tree.image_refs = []  # Reset the image reference list

        for img_path, img_name, similarity_threshold, keyboard_input in self.image_list:
            image = Image.open(img_path)
            image.thumbnail((50, 50))
            photo = ImageTk.PhotoImage(image)
            self.tree.insert("", tk.END, values=(img_path, img_name, similarity_threshold, keyboard_input), image=photo)
            self.tree.image_refs.append(photo)  # Save the image reference

        if self.tree.selection():
            self.on_treeview_select(None)

    def on_treeview_select(self, event):
        selected_items = self.tree.selection()
        if selected_items:
            item = selected_items[0]
            img_path = self.tree.item(item, "values")[0]
            self.display_preview(img_path)

    def display_preview(self, img_path):
        try:
            image = Image.open(img_path)
            image.thumbnail((300, 300))
            self.preview_photo = ImageTk.PhotoImage(image)  # Use instance variable to store reference
            self.preview_image.config(image=self.preview_photo)
        except Exception as e:
            print(f"无法加载图片: {e}")
            self.preview_image.config(image=None)
            self.preview_photo = None

    def edit_image_name(self, event):
        selected_item = self.tree.selection()[0]
        selected_index = self.tree.index(selected_item)
        selected_image = self.image_list[selected_index]

        new_image_name = simpledialog.askstring("修改步骤名称", "请输入新的步骤名称:", initialvalue=selected_image[1])
        if new_image_name is not None:
            self.image_list[selected_index] = (selected_image[0], new_image_name, selected_image[2], selected_image[3])
            self.update_image_listbox()

    def edit_similarity_threshold(self, event):
        selected_item = self.tree.selection()[0]
        selected_index = self.tree.index(selected_item)
        selected_image = self.image_list[selected_index]

        new_similarity_threshold = simpledialog.askfloat("修改相似度", "请输入新的相似度(0.1 - 1.0):", initialvalue=selected_image[2], minvalue=0.1, maxvalue=1.0)
        if new_similarity_threshold is not None:
            self.image_list[selected_index] = (selected_image[0], selected_image[1], new_similarity_threshold, selected_image[3])
            self.update_image_listbox()

    def edit_keyboard_input(self, event):
        selected_item = self.tree.selection()[0]
        selected_index = self.tree.index(selected_item)
        selected_image = self.image_list[selected_index]

        new_keyboard_input = simpledialog.askstring("修改键盘输入", "请输入新的键盘输入:", initialvalue=selected_image[3])
        if new_keyboard_input is not None:
            self.image_list[selected_index] = (selected_image[0], selected_image[1], selected_image[2], new_keyboard_input)
            self.update_image_listbox()

    def delete_selected_image(self):
        selected_item = self.tree.selection()
        if selected_item:
            selected_index = self.tree.index(selected_item[0])
            del self.image_list[selected_index]
            self.update_image_listbox()

    def toggle_script(self, event=None):
        if not self.running:
            self.start_script_thread()
            self.toggle_run_button.config(text="停止运行")
        else:
            self.stop_script()
            self.toggle_run_button.config(text="开始运行")

    def start_script_thread(self):
        if not self.running:
            self.running = True
            self.thread = threading.Thread(target=self.run_script, daemon=True)
            self.thread.start()

    def run_script(self):
        self.loop_count = int(self.loop_count_entry.get())
        current_loop = 0

        while self.running and current_loop < self.loop_count:
            for img_path, img_name, similarity_threshold, keyboard_input in self.image_list:
                if not self.running:
                    break
                while self.running:
                    if self.match_and_click(img_path, similarity_threshold):
                        if keyboard_input:
                            pyautogui.write(keyboard_input)
                        break
                    time.sleep(self.delay_time)
            current_loop += 1

    def stop_script(self):
        self.running = False
        if self.thread is not None:
            self.thread.join()
        print("脚本已停止")
        logging.info("脚本已停止")

    def match_and_click(self, template_path, similarity_threshold):
        screenshot = pyautogui.screenshot()
        screenshot = np.array(screenshot)
        screenshot = cv2.cvtColor(screenshot, cv2.COLOR_RGB2BGR)

        template = cv2.imread(template_path, 0)
        if template is None:
            print(f"无法读取图像: {template_path}")
            logging.error(f"无法读取图像: {template_path}")
            return False

        gray_screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)

        result = cv2.matchTemplate(gray_screenshot, template, cv2.TM_CCOEFF_NORMED)
        loc = np.where(result >= similarity_threshold)

        found = False
        for pt in zip(*loc[::-1]):
            click_x = pt[0] + template.shape[1] // 2
            click_y = pt[1] + template.shape[0] // 2
            pyautogui.click(click_x, click_y)
            found = True
            break

        if not found:
            print(f"未找到匹配区域: {template_path}")
            logging.warning(f"未找到匹配区域: {template_path}")
            return False

        return True

    def set_hotkey(self):
        new_hotkey = simpledialog.askstring("设置热键", "请输入新的热键(例如:<F1>):", initialvalue=self.hotkey)
        if new_hotkey is not None:
            self.hotkey = new_hotkey
            self.root.bind(self.hotkey, self.toggle_script)
            print(f"热键已设置为: {self.hotkey}")
            logging.info(f"热键已设置为: {self.hotkey}")

    def save_config(self):
        config = {
            "image_list": self.image_list,
            "hotkey": self.hotkey,
            "screenshot_area": self.screenshot_area,
            "similarity_threshold": self.similarity_threshold,
            "delay_time": self.delay_time,
            "loop_count": self.loop_count
        }
        with open('config.json', 'w') as f:
            json.dump(config, f)
        print("配置已保存")
        logging.info("配置已保存")

    def load_config(self):
        if os.path.exists('config.json'):
            with open('config.json', 'r') as f:
                config = json.load(f)
                self.image_list = config.get("image_list", [])
                self.hotkey = config.get("hotkey", '<F1>')
                self.screenshot_area = config.get("screenshot_area", None)
                self.similarity_threshold = config.get("similarity_threshold", 0.8)
                self.delay_time = config.get("delay_time", 0.1)
                self.loop_count = config.get("loop_count", 1)
                self.loop_count_entry.delete(0, tk.END)
                self.loop_count_entry.insert(0, str(self.loop_count))
                self.root.bind(self.hotkey, self.toggle_script)
                self.update_image_listbox()
            print("配置已加载")
            logging.info("配置已加载")

    def load_config_manually(self):
        file_path = filedialog.askopenfilename(filetypes=[("JSON files", "*.json")])
        if file_path:
            with open(file_path, 'r') as f:
                config = json.load(f)
                self.image_list = config.get("image_list", [])
                self.hotkey = config.get("hotkey", '<F1>')
                self.screenshot_area = config.get("screenshot_area", None)
                self.similarity_threshold = config.get("similarity_threshold", 0.8)
                self.delay_time = config.get("delay_time", 0.1)
                self.loop_count = config.get("loop_count", 1)
                self.loop_count_entry.delete(0, tk.END)
                self.loop_count_entry.insert(0, str(self.loop_count))
                self.root.bind(self.hotkey, self.toggle_script)
                self.update_image_listbox()
            print("配置已加载")
            logging.info("配置已加载")

if __name__ == "__main__":
    root = tk.Tk()
    app = ImageRecognitionApp(root)
    root.mainloop()


已添加图片预览
沙发
ID08 发表于 2024-9-19 23:59
3#
kim945 发表于 2024-9-20 00:11
这我一直用按键精灵一点点试着做的...为了每天填写各种单位上报的网站..早要是有这个,起码我能省20个小时T_T
4#
helh0275 发表于 2024-9-20 01:06
老大就不能顺手打个包?伪装成exe的样子
6#
yueguangxiaxian 发表于 2024-9-20 06:45
希望有编译好的,谢谢楼主
7#
yjn866y 发表于 2024-9-20 08:43
学习使人进步。。。
8#
wasm2023 发表于 2024-9-20 08:49
学习了,感谢分享
9#
Rx0 发表于 2024-9-20 09:05
这种软件,还是得 高速、大批量 处理才更实用。可以参考Duplicate Cleaner 来做。
10#
vyuermeng 发表于 2024-9-20 09:41
我运行了一下  框选截图   点运行  鼠标会移到对应的图标上  但没有点击操作,是我配置的不对吗
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-9-20 14:55

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表