吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4286|回复: 65
收起左侧

[Windows] 全屏搜索指定图像并点击小工具

  [复制链接]
Murphy916 发表于 2024-6-27 10:21
本帖最后由 Murphy916 于 2024-7-3 09:09 编辑

纯小白,根据自身的使用需求,通过与AI的反复拉扯,写了个全屏自动搜索指定图像并点击的小工具,功能比较简单大家根据需求调整使用。
下载地址:
https://wwi.lanzoup.com/b0maq6arc
密码:1ayj

因为我也是小白,有些问题可能没能力修改,以下是源代码,有需要调整的可以集思广益
[Python] 纯文本查看 复制代码
import tkinter as tk
from tkinter import filedialog, messagebox
import pyautogui
import time
import threading
import keyboard
import cv2
import numpy as np
import os
import json
import logging

# 日志记录器配置
logging.basicConfig(level=logging.DEBUG)

# 全局变量
monitoring = False
target_images = []  # 存储目标图像 (文件名, 图像数据)
threshold = 0.8  # 图像匹配的相似度阈值
monitoring_interval = 0.5  # 扫描等待时间(秒)
click_wait_time = 0.3  # 点击等待时间(秒)
blinking_color = "red"  # 默认圆点颜色为红色

# 文件名前缀
FILE_PREFIX = "target_image_"

# Function to save settings
def save_settings():
    settings = {
        'threshold': threshold,
        'monitoring_interval': monitoring_interval,
        'click_wait_time': click_wait_time
    }
    try:
        with open('settings.json', 'w') as f:
            json.dump(settings, f)
            logging.info("Settings saved successfully.")
    except Exception as e:
        logging.error(f"Error saving settings: {e}")

# Function to load settings
def load_settings():
    global threshold, monitoring_interval, click_wait_time
    try:
        with open('settings.json', 'r') as f:
            settings = json.load(f)
            threshold = settings.get('threshold', 0.8)
            monitoring_interval = settings.get('monitoring_interval', 0.5)
            click_wait_time = settings.get('click_wait_time', 0.3)
            logging.info("Settings loaded successfully.")
    except Exception as e:
        logging.error(f"Error loading settings: {e}")

# Call load_settings at startup
load_settings()

# Function to save target images
def save_target_images():
    try:
        for file_name, img_data in target_images:
            np.save(f"{FILE_PREFIX}{file_name}", img_data)
        logging.info(f"Saved {len(target_images)} images.")
    except Exception as e:
        logging.error(f"Error saving target images: {e}")

# Function to load saved images
def load_saved_images():
    global target_images

    try:
        target_images.clear()  # 清空现有的图像列表
        for file_name in os.listdir("."):  # 遍历当前文件夹中的文件
            if file_name.startswith(FILE_PREFIX) and file_name.endswith(".npy"):
                file_path = os.path.join(".", file_name)
                img_data = np.load(file_path, allow_pickle=True)  # 加载图像数据,允许使用 pickle
                original_file_name = file_name[len(FILE_PREFIX):].replace(".npy", "")  # 去掉扩展名和前缀
                target_images.append((original_file_name, img_data))  # 将文件名和图像数据存储在列表中
        logging.info(f"Loaded {len(target_images)} images.")
        update_selected_images_listbox()  # 更新显示
    except Exception as e:
        logging.error(f"Error loading saved images: {e}")
        target_images = []  # 加载失败时清空列表

# Function to update selected images listbox
def update_selected_images_listbox():
    selected_images_listbox.delete(0, tk.END)
    for idx, (file_name, _) in enumerate(target_images, start=1):
        selected_images_listbox.insert(tk.END, f"{idx}. {file_name}")

    # 绑定右键点击事件
    selected_images_listbox.bind('<Button-3>', show_context_menu)

# Function to clear target images
def clear_target_images():
    global target_images
    
    try:
        folder_path = os.getcwd()  # 获取当前工作目录
        target_images.clear()
        
        for file_name in os.listdir(folder_path):
            if file_name.startswith(FILE_PREFIX) and file_name.endswith(".npy"):
                file_path = os.path.join(folder_path, file_name)
                os.remove(file_path)
        
        # 重新加载已保存的图像
        load_saved_images()
        
        # 更新显示已选图像列表框
        update_selected_images_listbox()
        
        messagebox.showinfo("Info", "已清除所有目标图像。")
    except Exception as e:
        logging.error(f"清除目标图像时出错: {e}")
        messagebox.showerror("错误", "清除图像时发生错误。")

# Function to load target image
def load_target_image():
    global target_images

    try:
        file_paths = filedialog.askopenfilenames(
            title="选择目标图像",
            filetypes=[("Image files", "*.jpg *.png *.jpeg *.bmp *.tiff")]
        )
        if file_paths:
            target_images.clear()  # 清空已选择的图像列表
            for file_path in file_paths:
                file_name = os.path.basename(file_path)
                target_image = cv2.imread(file_path, cv2.IMREAD_COLOR)
                if target_image is None:
                    messagebox.showerror("Error", "无法加载图像文件。")
                else:
                    target_images.append((file_name, target_image))  # 存储 (文件名, 图像数据)
                    logging.info(f"Loaded image: {file_path}")

            # 保存已选择的图像数据
            save_target_images()

            # 更新已选图像列表框
            update_selected_images_listbox()

            # 弹出提示信息
            num_images = len(target_images)
            messagebox.showinfo("Info", f"已成功导入 {num_images} 张图片。")

    except Exception as e:
        logging.error(f"Error loading target images: {e}")
        messagebox.showerror("Error", "加载图像时出现错误。")

# Function to delete selected image
def delete_selected_image(index):
    global target_images
    
    try:
        file_name, _ = target_images.pop(index)
        os.remove(f"{FILE_PREFIX}{file_name}.npy")
        update_selected_images_listbox()  # 更新列表框
        messagebox.showinfo("Info", f"已删除图像: {file_name}")
    except Exception as e:
        logging.error(f"删除图像时出错: {e}")
        messagebox.showerror("错误", f"删除图像时发生错误: {e}")

# Function to show context menu
def show_context_menu(event):
    try:
        # 获取选中的项目索引
        index = selected_images_listbox.nearest(event.y)
        selected_images_listbox.selection_set(index)

        # 创建上下文菜单
        context_menu = tk.Menu(root, tearoff=0)
        context_menu.add_command(
            label="删除",
            command=lambda: delete_selected_image(index)
        )
        context_menu.post(event.x_root, event.y_root)
    except Exception as e:
        logging.error(f"显示上下文菜单时出错: {e}")

# Function to monitor screen
def monitor_screen():
    global monitoring, target_images, threshold, monitoring_interval, click_wait_time

    while monitoring:
        screenshot = pyautogui.screenshot()
        screenshot = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)

        for file_name, target_image in target_images:
            if isinstance(target_image, np.ndarray):
                result = cv2.matchTemplate(screenshot, target_image, cv2.TM_CCOEFF_NORMED)
                min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

                if max_val >= threshold:
                    logging.info(f"图像匹配度: {max_val}, 位置: {max_loc}")
                    target_height, target_width = target_image.shape[:2]
                    click_position = (max_loc[0] + target_width // 2, max_loc[1] + target_height // 2)
                    pyautogui.click(click_position)
                    time.sleep(click_wait_time)  # 等待点击间隔时间

                    # 将匹配信息添加到匹配度显示框
                    current_time = time.strftime("%H:%M:%S")  # 获取当前时间
                    formatted_info = f"时间: {current_time} | 文件名: {file_name} | 匹配度: {int(max_val * 100)}%"
                    add_match_info(formatted_info)

                    # 将鼠标移动到屏幕中心
                    screen_center = (pyautogui.size()[0] // 2, pyautogui.size()[1] // 2)
                    pyautogui.moveTo(screen_center)

        time.sleep(monitoring_interval)  # 控制监控间隔时间

# Function to add match information to the match info listbox
def add_match_info(info):
    match_info_listbox.insert(tk.END, info)
    if match_info_listbox.size() > 5:
        match_info_listbox.delete(0)  # 保持仅显示最新的5条信息
    match_info_listbox.see(tk.END)  # 滚动到最新的信息

# Function to toggle monitoring
def toggle_monitoring():
    global monitoring, target_images

    if monitoring:
        monitoring = False
        status_label.config(text="监控状态: 已停止")
    else:
        if not target_images:
            messagebox.showwarning("Warning", "请先选择至少一个目标图像。")
            return

        monitoring = True
        monitor_thread = threading.Thread(target=monitor_screen, daemon=True)
        monitor_thread.start()
        status_label.config(text="监控状态: 正在运行")

    # 启动或停止闪烁效果
    start_blinking() if monitoring else stop_blinking()

# Function to increase threshold
def increase_threshold():
    global threshold
    threshold = min(1.0, threshold + 0.01)
    threshold_label.config(text=f"当前匹配阈值: {int(threshold * 100)}%")
    save_settings()  # 保存设置到文件

# Function to decrease threshold
def decrease_threshold():
    global threshold
    threshold = max(0.0, threshold - 0.01)
    threshold_label.config(text=f"当前匹配阈值: {int(threshold * 100)}%")
    save_settings()  # 保存设置到文件

# Function to increase monitoring interval
def increase_monitoring_interval():
    global monitoring_interval
    monitoring_interval = round(min(10.0, monitoring_interval + 0.1), 1)
    monitoring_interval_label.config(text=f"扫描等待时间: {monitoring_interval}秒")
    save_settings()  # 保存设置到文件

# Function to decrease monitoring interval
def decrease_monitoring_interval():
    global monitoring_interval
    monitoring_interval = round(max(0.1, monitoring_interval - 0.1), 1)
    monitoring_interval_label.config(text=f"扫描等待时间: {monitoring_interval}秒")
    save_settings()  # 保存设置到文件

# Function to increase click wait time
def increase_click_wait_time():
    global click_wait_time
    click_wait_time = round(min(5.0, click_wait_time + 0.1), 1)
    click_wait_time_label.config(text=f"点击等待时间: {click_wait_time}秒")
    save_settings()  # 保存设置到文件

# Function to decrease click wait time
def decrease_click_wait_time():
    global click_wait_time
    click_wait_time = round(max(0.1, click_wait_time - 0.1), 1)
    click_wait_time_label.config(text=f"点击等待时间: {click_wait_time}秒")
    save_settings()  # 保存设置到文件

# 创建主窗口
root = tk.Tk()
root.title("自动监控工具")

# 创建标签和按钮
instruction_label = tk.Label(root, text="选择一个或多个目标图像进行监控")
instruction_label.pack(pady=10)

select_button = tk.Button(root, text="选择图像", command=load_target_image)
select_button.pack(pady=5)

# 新增清除图像按钮
clear_button = tk.Button(root, text="清除所有图像", command=clear_target_images)
clear_button.pack(pady=5)

# 已选图像显示框和匹配信息显示框的父框架
info_frame = tk.Frame(root)
info_frame.pack(pady=10)

# 已选图像显示框
selected_images_frame = tk.Frame(info_frame)
selected_images_frame.pack(side=tk.LEFT, padx=5)

selected_images_label = tk.Label(selected_images_frame, text="已选图像:")
selected_images_label.pack(side=tk.TOP)

# 调整显示框的宽度和高度
selected_images_listbox = tk.Listbox(selected_images_frame, width=40, height=5)
selected_images_listbox.pack()

# 实时匹配信息显示框
match_info_frame = tk.Frame(info_frame)
match_info_frame.pack(side=tk.LEFT, padx=5)

match_info_label = tk.Label(match_info_frame, text="实时匹配信息:")
match_info_label.pack(side=tk.TOP)

# 匹配信息显示栏,可以显示5条信息
match_info_listbox = tk.Listbox(match_info_frame, width=40, height=5)
match_info_listbox.pack()

# 加载已保存的图像
load_saved_images()  # 在启动时加载已保存的图像
update_selected_images_listbox()  # 更新显示

# 添加状态标签和闪烁的圆点
status_frame = tk.Frame(root)
status_frame.pack(pady=10)

status_label = tk.Label(status_frame, text="监控状态: 未开始")
status_label.pack(side=tk.LEFT)

# 添加 Canvas 用于绘制圆点
canvas = tk.Canvas(status_frame, width=20, height=20, bg='white')
canvas.pack(side=tk.LEFT, padx=10)

circle_id = canvas.create_oval(5, 5, 15, 15, fill=blinking_color)  # 初始为红色

def blink():
    global blinking_color, monitoring
    if monitoring:
        # 切换颜色
        new_color = "green" if blinking_color == "red" else "red"
        canvas.itemconfig(circle_id, fill=new_color)
        blinking_color = new_color
        root.after(500, blink)  # 每 500 毫秒切换一次颜色

def start_blinking():
    blink()  # 启动闪烁

def stop_blinking():
    canvas.itemconfig(circle_id, fill="red")  # 停止时固定为红色

threshold_frame = tk.Frame(root)
threshold_frame.pack(pady=5)

threshold_label = tk.Label(threshold_frame, text=f"当前匹配阈值: {int(threshold * 100)}%")
threshold_label.pack(side=tk.LEFT)

increase_button = tk.Button(threshold_frame, text="+", command=increase_threshold)
increase_button.pack(side=tk.LEFT, padx=5)

decrease_button = tk.Button(threshold_frame, text="-", command=decrease_threshold)
decrease_button.pack(side=tk.LEFT, padx=5)

# 监控间隔和点击等待时间框架
options_frame = tk.Frame(root)
options_frame.pack(pady=5)

monitoring_interval_label = tk.Label(options_frame, text=f"扫描等待时间: {monitoring_interval}秒")
monitoring_interval_label.pack(side=tk.LEFT)

monitoring_interval_increase_button = tk.Button(options_frame, text="+", command=increase_monitoring_interval)
monitoring_interval_increase_button.pack(side=tk.LEFT, padx=5)

monitoring_interval_decrease_button = tk.Button(options_frame, text="-", command=decrease_monitoring_interval)
monitoring_interval_decrease_button.pack(side=tk.LEFT, padx=5)

click_wait_time_label = tk.Label(options_frame, text=f"点击等待时间: {click_wait_time}秒")
click_wait_time_label.pack(side=tk.LEFT)

click_wait_time_increase_button = tk.Button(options_frame, text="+", command=increase_click_wait_time)
click_wait_time_increase_button.pack(side=tk.LEFT, padx=5)

click_wait_time_decrease_button = tk.Button(options_frame, text="-", command=decrease_click_wait_time)
click_wait_time_decrease_button.pack(side=tk.LEFT, padx=5)

# 功能说明标签
function_label = tk.Label(root, text=(
    "程序功能说明:\n"
    "1. 点击 '选择图像' 选择一个或多个目标图像\n"
    "2. 按 F12 开始/停止监控。\n"
    "3. 监控过程中,如屏幕中找到与目标图像相似的区域,程序将在该位置执行点击操作。\n"
    "4. 程序会自动保存已导入图像以及参数设置,并在下次启动时自动载入。"
))
function_label.pack(pady=10)

# 绑定 F12 键来切换监控状态
keyboard.add_hotkey('F12', toggle_monitoring)

# 启动主循环
root.mainloop()

# 运行此行以确保程序关闭时删除键盘快捷键监听器
keyboard.unhook_all_hotkeys()

工具界面

工具界面

免费评分

参与人数 8吾爱币 +6 热心值 +8 收起 理由
hongkong168 + 1 如果还能识别文字或者数字,自动点击那就太完美了
itszy + 1 + 1 正需要这个,pyautogui的不行。
nike766 + 1 + 1 源代码可以用,exe可能是打包问题。
dogox + 1 + 1 我很赞同!
ice7733 + 1 + 1 我很赞同!
macolma + 1 谢谢@Thanks!
viconly + 1 + 1 谢谢@Thanks!
dfdndz1 + 1 + 1 我很赞同!

查看全部评分

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

whitetiger28 发表于 2024-6-28 10:52
职称培训课太有用了
viconly 发表于 2024-6-28 07:42
想不出来用在什么地方,可否分享一下应用场景,玩游戏么
dfdndz1 发表于 2024-6-27 19:49
WIN7系统不能
出现故障   图像自动监控工具v2.0.exe -系统错误
无法度动此理序;因为计算机中失opims win ceptr--.
●尝试重新安装该程序以解决此问题。
确定
dfdndz1 发表于 2024-6-28 07:02
楼主,适配一下WIN7系统,正需要这个软件
gmsm125 发表于 2024-6-28 07:30
W10系统,选择图片时显示错误 无法加载图像文件
 楼主| Murphy916 发表于 2024-6-28 08:45
dfdndz1 发表于 2024-6-28 07:02
楼主,适配一下WIN7系统,正需要这个软件

等我搞个WIN7虚拟机试试
 楼主| Murphy916 发表于 2024-6-28 08:47
gmsm125 发表于 2024-6-28 07:30
W10系统,选择图片时显示错误 无法加载图像文件

支持的文件格式为 *.jpg, *.png, *.jpeg, *.bmp, *.tiff。
目标图像不宜过大,特别是高分辨率图像,处理和匹配可能会导致性能问题。
我是用来检测类似图标大小的截图的
 楼主| Murphy916 发表于 2024-6-28 09:58
viconly 发表于 2024-6-28 07:42
想不出来用在什么地方,可否分享一下应用场景,玩游戏么

这可能不太好分享我的使用场景
woshidxl2004 发表于 2024-6-28 10:59
幻想神域制作料理可以用用
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-23 07:19

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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