MSS&OpenCV

使用 MSS 进行高速截图,并将模板图像只加载一次进内存,再使用 OpenCV 匹配。此脚本适用于游戏等图像频繁更新场景,每次识别都尽可能快速且高效。

示例 1 : 识别图像一次,并将结果保存在变量中

将图像文件: 1.tif 加载一次进内存(该示例中的1.tif.py 的目录相同),再使用 OpenCV 匹配,将找到的图像坐标保存在found_x found_y中,最后在控制台输出结果.

需要安装的依赖

pip install mss opencv-python numpy
语法示例:
import cv2
import numpy as np
import mss
import time
import os

# -----------------------------
# 模板图像路径(推荐 PNG 或 JPG)
# -----------------------------
template_path = "1.tif"  # 请替换为你的图像路径

# -----------------------------
# 匹配阈值(0~1之间)
# 越接近1要求越严格,一般0.8为起点
# -----------------------------
threshold = 0.8

# -----------------------------
# 初始化变量
# -----------------------------
Result = 0
found_x, found_y = None, None

# -----------------------------
# 读取模板图像,只执行一次
# 使用灰度图加快匹配速度
# -----------------------------
template = cv2.imread(template_path, cv2.IMREAD_GRAYSCALE)
if template is None:
    raise FileNotFoundError(f"模板图像未找到:{template_path}")

# 获取模板图尺寸
template_h, template_w = template.shape[:2]

# -----------------------------
# 创建 mss 实例,进行截图
# -----------------------------
with mss.mss() as sct:
    # 可指定屏幕区域:top, left, width, height
    # monitor = {"top": 0, "left": 0, "width": 1920, "height": 1080}
    monitor = sct.monitors[1]  # 全屏(第1号显示器)

    # 延迟等待游戏加载完成(可视情况修改)
    time.sleep(1)

    # 截图一次
    screenshot = np.array(sct.grab(monitor))

    # mss 返回的是 BGRA 图像,转换为灰度图以便匹配
    screenshot_gray = cv2.cvtColor(screenshot, cv2.COLOR_BGRA2GRAY)

    # -----------------------------
    # 模板匹配(使用标准相关系数方法)
    # 返回匹配结果矩阵,每个像素点代表匹配得分
    # -----------------------------
    MSSResult = cv2.matchTemplate(screenshot_gray, template, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(MSSResult)

    # -----------------------------
    # 判断是否匹配成功
    # -----------------------------
    if max_val >= threshold:
        Result = 1
        found_x, found_y = max_loc  # 左上角坐标

# -----------------------------
# 控制台输出匹配结果
# 可用于后续逻辑判断
# -----------------------------
if Result:
    print(f"Result 1 {found_x} {found_y}")
else:
    print("Result 0")

示例 2 : 循环持续识别图像,支持热键控制,END 暂停/恢复,Ctrl+End 退出.

将图像文件: 1.tif 加载一次进内存(该示例中的1.tif.py 的目录相同),再使用 OpenCV 匹配,将找到的图像坐标保存在found_x found_y中,最后在控制台输出结果.

pip install mss opencv-python numpy keyboard
语法示例:
import cv2
import numpy as np
import mss
import time
import os
import keyboard
import threading

# -----------------------------
# 模板图像路径(推荐 PNG 或 JPG)
# -----------------------------
template_path = "1.tif"

# -----------------------------
# 匹配阈值(0~1)
# -----------------------------
threshold = 0.8

# -----------------------------
# 读取模板图像,只执行一次
# -----------------------------
template = cv2.imread(template_path, cv2.IMREAD_GRAYSCALE)
if template is None:
    raise FileNotFoundError(f"模板图像未找到:{template_path}")

template_h, template_w = template.shape[:2]

# -----------------------------
# 状态控制变量(用线程安全的方式)
# -----------------------------
paused = False
should_exit = False

# -----------------------------
# 热键回调函数
# -----------------------------
def toggle_pause():
    global paused
    paused = not paused
    print("[暂停中]" if paused else "[已恢复] 继续检测...")

def exit_program():
    global should_exit
    should_exit = True
    print("[退出指令] 脚本即将终止...")

# 注册热键(非阻塞监听)
keyboard.add_hotkey('end', toggle_pause)
keyboard.add_hotkey('ctrl+end', exit_program)

print("脚本开始运行。按 END 暂停/恢复,按 Ctrl+End 退出。")

# -----------------------------
# 创建 mss 实例(只创建一次)
# -----------------------------
with mss.mss() as sct:
    monitor = sct.monitors[1]  # 全屏截图

    while not should_exit:
        if paused:
            time.sleep(0.1)
            continue

        # 截屏并灰度处理
        screenshot = np.array(sct.grab(monitor))
        screenshot_gray = cv2.cvtColor(screenshot, cv2.COLOR_BGRA2GRAY)

        # 模板匹配
        result = cv2.matchTemplate(screenshot_gray, template, cv2.TM_CCOEFF_NORMED)
        _, max_val, _, max_loc = cv2.minMaxLoc(result)

        if max_val >= threshold:
            found_x, found_y = max_loc
            print(f"Result 1 {found_x} {found_y}")
        else:
            print("Result 0")

        time.sleep(0.3)

print("脚本已退出。")