首页 > 编程语言 >利用Python+OpenCV实现截图匹配图像,支持自适应缩放、灰度匹配、区域匹配、匹配多个结果

利用Python+OpenCV实现截图匹配图像,支持自适应缩放、灰度匹配、区域匹配、匹配多个结果

时间:2024-05-25 16:29:34浏览次数:15  
标签:匹配 screenshot 缩放 int image cv2 灰度 match

一、依赖安装

pip install opencv-python
pip install pyautogui

二、获取系统缩放比例

注意:必须先通过ctypes获取wid之后才能导入pyautogui,如果需要在其它代码中引用该模块,最好把获取分辨率这部分代码放到程序入口处,然后传递给识图函数,避免提前导入pyautogui导致获取分辨率失败。

# 获取当前系统缩放比例
import ctypes
# wid必须在导入pyautogui之前赋值
wid = ctypes.windll.user32.GetSystemMetrics(0)
import pyautogui
screen_width , _ = pyautogui.size()
true_scale=screen_width/wid

 三、定义匹配结果类

x,y表示中心坐标,x1,y1,x2,y2表示四个顶点的坐标,match表示匹配度,取值范围0-100。

from dataclasses import dataclass
# 定义匹配结果类
@dataclass
class MatchInfo:
    match: float = 0
    x: int = 0
    y: int = 0
    x1: int = 0
    y1: int = 0
    x2: int = 0
    y2: int = 0

    @staticmethod
    def not_found():
        return MatchInfo()

    def __str__(self):
        return (
            f"匹配度={self.match:.2f}, "
            f"中心坐标: ({self.x}, {self.y}) "
        )

四、完整代码

参数:

template:模板图片,字符串,即待匹配图片,支持两种形式,可以传入图片地址,也可以直接传入图片名称,此时会从代码中设定的图片文件夹寻找图片;

min_threshold:最小匹配度,浮点数,只返回匹配度大于等于该值的结果,取值范围0-100

gray:灰度匹配,布尔值,为真时则忽略颜色,可以大幅提升匹配速度,适用于不考虑颜色的情况

a,b,c,d:区域匹配坐标,整数,都为0时不生效,否则只在该区域匹配,但是返回的结果坐标任然是相对于整个屏幕

image_sacle:图片缩放,浮点数,即传入的图片的缩放,也就是截图时电脑对应的缩放,默认和1.25,即125%,需要自己根据情况修改,取值是(1,1.25,1.5,1.75,2)

max_deviation:最大偏差值,整数,多个匹配结果之间距离的最小值,如果存在同一个目标被识别成两个结果的情况,可以适当增加这个参数的值

返回值:

列表类型,包含所有符合条件的匹配结果(MatchInfo对象),如果没有匹配到则是空列表

# 获取当前系统缩放比例
import ctypes
# wid必须在导入pyautogui之前赋值
wid = ctypes.windll.user32.GetSystemMetrics(0)
import pyautogui
screen_width , _ = pyautogui.size()
true_scale=screen_width/wid


from dataclasses import dataclass
# 定义匹配结果类
@dataclass
class MatchInfo:
    match: float = 0
    x: int = 0
    y: int = 0
    x1: int = 0
    y1: int = 0
    x2: int = 0
    y2: int = 0

    @staticmethod
    def not_found():
        return MatchInfo()

    def __str__(self):
        return (
            f"匹配度={self.match:.2f}, "
            f"中心坐标: ({self.x}, {self.y}) "
        )


import cv2
import os
import numpy as np

# 识图函数
def find_image_on_screen(template, min_threshold, gray=False, a=0, b=0, c=0, d=0,image_sacle=1.25,max_deviation = 13):    
    # 图片存放地址
    image_path='D:\\test\\image'
    # 处理传入的匹配度
    min_threshold = min_threshold / 100
    # 路径处理,如果传入的参数只是图片名称,就从默认路径寻找改图片
    if not os.path.isabs(template):
        template = os.path.join(image_path, template)
    # 读取模板图片
    templ = cv2.imread(template)
    # 获取屏幕截图
    screenshot = cv2.cvtColor(np.array(pyautogui.screenshot()), cv2.COLOR_RGB2BGR)
    # 获取模板图片长宽
    xx, yy = templ.shape[:-1]
    # 如果实际缩放和图片缩放不一致,就进行调整
    if true_scale != image_sacle:
        screenshot = cv2.resize(screenshot, None, fx=image_sacle / true_scale, fy=image_sacle / true_scale)
    # 判断是否需要灰度匹配
    if gray:
        screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)
        templ = cv2.cvtColor(templ, cv2.COLOR_BGR2GRAY)
    # 判断是否需要区域匹配
    if a==0 and b==0 and c==0 and d==0:
        screenshot_region = screenshot  # 默认情况下,使用整个截图
    else:
        # 这里需要特殊处理,避免裁剪后的截图比模板图片小导致报错
        c = max(a + yy, c)
        d = max(b + xx, d)
        # 裁剪截图
        screenshot_region = screenshot[b:d, a:c]

    # 执行模板匹配
    result = cv2.matchTemplate(screenshot_region, templ, cv2.TM_CCOEFF_NORMED)
    # 获取满足匹配度的结果
    locations = np.where(result >= min_threshold)
    locations = list(zip(*locations[::-1]))
    match_info = {}
    # 对匹配结果进行筛选和去重,避免同一个目标被识别成多个结果,可以通过调整max_deviation的值来调整效果
    for loc in locations:
        x, y = loc
        x = x + a  # 调整x坐标以匹配整个截图
        y = y + b  # 调整y坐标以匹配整个截图
        match_value = result[y - b, x - a]
        skip_current = False
        for (prev_x, prev_y), prev_match_value in match_info.items():
            if abs(x - prev_x) <= max_deviation and abs(y - prev_y) <= max_deviation:
                if match_value > prev_match_value:
                    match_info[(x, y)] = match_value
                    del match_info[(prev_x, prev_y)]
                else:
                    skip_current = True
                break
        if not skip_current:
            match_info[(x, y)] = match_value
    # 构建匹配结果列表
    match_info_objects = []
    for (x, y), match_value in sorted(
        match_info.items(), key=lambda x: x[1], reverse=True
    ):
        h, w = xx, yy
        top_left = (x, y)
        bottom_right = (x + w, y + h)
        center = (x + w // 2, y + h // 2)
        matche = MatchInfo(
            match_value * 100,
            center[0],
            center[1],
            top_left[0],
            top_left[1],
            bottom_right[0],
            bottom_right[1],
        )
        match_info_objects.append(matche)
    return match_info_objects

五、示例用法

if __name__=='__main__':
    # 根据图片名称匹配,其他参数取默认值
    print("test1:")
    for s in (find_image_on_screen('test1.png')):
        print(s)
    
    print("test2:")
    # 根据图片路径匹配,匹配度85
    for s in (find_image_on_screen('D:\\test\\image\\test2.png',min_threshold=85)):
        print(s)

    print("test3:")
    # 根据路径匹配,忽略颜色,在指定区域匹配
    for s in (find_image_on_screen('D:\\test\\image\\test3.png',gray=True,a=11,b=35,c=983,d=639)):
        print(s)

运行结果:

标签:匹配,screenshot,缩放,int,image,cv2,灰度,match
From: https://blog.csdn.net/weixin_45660535/article/details/139196740

相关文章

  • 实验21-正向最大匹配算法
    出现UnicodeDecodeError:'gbk'codeccan'tdecodebyte0x9finposition16:illegalmultibytesequence 修改为 即可实验结果: ......
  • python将矩阵转化为灰度图
    1.python将矩阵转化为灰度图的方法要将一个矩阵(通常是一个二维数组,其中每个元素代表一个像素的灰度值)转换为灰度图,我们可以使用Python的matplotlib库。下面是一个详细的步骤和完整的代码示例:(1)准备数据:首先,我们需要一个二维数组(矩阵),其中每个元素代表一个灰度值。灰度值通常在0(黑......
  • python将矩阵转化为灰度图
    1.python将矩阵转化为灰度图的方法要将一个矩阵(通常是一个二维数组,其中每个元素代表一个像素的灰度值)转换为灰度图,我们可以使用Python的matplotlib库。下面是一个详细的步骤和完整的代码示例:(1)准备数据:首先,我们需要一个二维数组(矩阵),其中每个元素代表一个灰度值。灰度值通常在0......
  • 【达梦问题解决】to_date转换之【文字与格式字符串不匹配】
    【问题描述】因为要转换的值中包含了不属于时间格式的字符(T,Z),这可能是数据迁移时时间参数设置不对导致的。具体没有进行考究【问题解决】使用DATE分隔符解决【手册链接】格式符解释实际分隔符的处理办法【自定义转换函数】这里的自定函数是不完善的,因为我的数......
  • 图论-二分图匹配匈牙利算法
    不得不说,如果以现实角度代入此算法的理解,就合理了很多,虽然有悖道德准则重点在于以下几点每次给女生分配男生前,都把男生全部初始化为可预定状态(即使他已经被别人成功匹配了)在所有女生中意的男生中遍历,如果发现该男生可预订就先预定,然后看他是否已经有主了,如果有主了,就dfs(matc......
  • shader 代码 分享:粒子的 缩放 和 位移(贝塞尔曲线控制不同粒子的位置) -- shader
    原始代码:shader_typeparticles;uniformintamount:hint_range(1,1000)=8;uniformfloatmax_rope_distance:hint_range(1.0,1000.0)=20.0;uniformfloatscale:hint_range(0.0,10.0)=1.0;uniformvec3start=vec3(-5.0,5.0,0.0);uniformvec3end......
  • 记录一个多对多数据匹配,但是效率不高
    importitertoolsimportosimportpandasaspddefget_result(hope,list_input,used):""":paramhope:#期望相加所得参数:paramlist_input:#所有数值:paramused:#已使用过列表,起始数据为空......
  • d3 v7树图实现动态边框,新增/编辑兄弟节点、子节点,删除节点和拖拽、缩放,动态边框
    d3版本:v7。PS:在用d3之前需要先了解SVG和CSS相关知识。树图生成部分和部分效果都是用SVG相关标签完成的。 效果图:  全部代码:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=devi......
  • 【Halcon】实现分离通道、创建矩形、获取灰度级、求最大最小均值、求大于某一灰度级的
    read_image(Image,'D:/image/123.jpg')rgb1_to_gray(Image,GrayImage)gen_rectangle1(Rectangle,100,100,200,200)rectangle1_domain(GrayImage,ImageReduced,100,100,200,200)crop_domain(ImageReduced,ImagePart)get_region_points(ImageP......
  • uniApp生成的h5页面禁止浏览器上缩放页面(支持安卓,ios)
    项目场景:uniapph5内嵌原生appios样式问题:1.双击和双指滑动,内嵌的h5页面均会被放大缩小2.修改ios底部的安全距离的背景色,默认是白色问题描述1.双击和双指滑动,内嵌的h5页面均会被放大缩小2.解决ios底部的安全距离和修改背景色,默认是白色解决方案:安卓只需要在h5.template.h......