详细分析PyAutoGUI中的locate函数(附Demo)

目录

  • 前言
  • 1. 基本知识
  • 2. 源代码分析
  • 3. Demo

前言

起因是实战中locate对个别定位会有偏差,导致一直识别错误

相应的基本知识推荐阅读:详细分析Python中的Pyautogui库(附Demo)

1. 基本知识

pyautogui.locate()函数用于在屏幕上定位指定图像或颜色的区域

作用:

  • 定位屏幕上的指定图像或颜色区域
  • 用于自动化任务,例如查找特定的应用程序窗口、按钮、图标等

函数如下:locate(needleImage, haystackImage, **kwargs): 在haystackImage中查找needleImage的位置

  • needleImage: 要搜索的图像(可以是字符串文件名或PIL.Image对象)
  • haystackImage: 要搜索的图像或区域(可以是字符串文件名、PIL.Image对象或(left, top, width, height)元组)
  • **kwargs: 传递给locateAll的其他关键字参数

最终的结果返回值:如果找到匹配点,则返回第一个匹配点,否则返回None

对于**kwargs的关键字参数,可以详细参考下locateAll的函数源码,补充其参数如下:

  • grayscale: 可选参数,指定是否将图像转换为灰度图像。默认为None
  • limit: 可选参数,指定要返回的匹配数量的上限。默认为None,表示没有限制
  • region: 可选参数,指定在哪个区域内搜索图像(以(left, top, width, height)元组形式指定)。默认为None,表示整个图像
  • step: 可选参数,指定搜索时的步长。默认为1,表示逐像素搜索
  • confidence: 可选参数,置信度阈值。仅当安装了OpenCV时才可用。默认为None

该函数的返回值为 所有匹配的位置的Box对象

2. 源代码分析

源代码已加入注释:

def locate(needleImage, haystackImage, **kwargs):
    # 将limit设置为1,仅返回第一个匹配点
    kwargs['limit'] = 1

    # 查找所有匹配点
    points = tuple(locateAll(needleImage, haystackImage, **kwargs))

    # 如果至少找到一个匹配点
    if len(points) > 0:
        return points[0]
    else:
        # 如果USE_IMAGE_NOT_FOUND_EXCEPTION为True,则抛出异常
        if USE_IMAGE_NOT_FOUND_EXCEPTION:
            raise ImageNotFoundException('无法定位图像。')
        # 否则返回None
        else:
            return None

其中使用到了locateAll函数,再次给出源代码:

@requiresPillow
def _locateAll_python(needleImage, haystackImage, grayscale=None, limit=None, region=None, step=1, confidence=None):
    """
    在haystackImage中查找所有的needleImage的位置。

    Args:
        needleImage: 要搜索的图像(可以是字符串文件名或PIL.Image对象)。
        haystackImage: 要搜索的图像或区域(可以是字符串文件名、PIL.Image对象或(left, top, width, height)元组)。
        grayscale: 可选参数,指定是否将图像转换为灰度图像。默认为None。
        limit: 可选参数,指定要返回的匹配数量的上限。默认为None,表示没有限制。
        region: 可选参数,指定在哪个区域内搜索图像(以(left, top, width, height)元组形式指定)。默认为None,表示整个图像。
        step: 可选参数,指定搜索时的步长。默认为1,表示逐像素搜索。
        confidence: 可选参数,置信度阈值。仅当安装了OpenCV时才可用。默认为None。

    Returns:
        生成器,用于生成所有匹配的位置的Box对象。

    Raises:
        NotImplementedError: 如果confidence参数在没有安装OpenCV时被使用。
        ImageNotFoundException: 如果未找到匹配点且USE_IMAGE_NOT_FOUND_EXCEPTION为True时引发。
    """
    if confidence is not None:
        raise NotImplementedError('当没有安装OpenCV时,confidence关键字参数不可用。')

    # 设置所有参数
    if grayscale is None:
        grayscale = GRAYSCALE_DEFAULT

    needleFileObj = None
    if isinstance(needleImage, (str, unicode)):
        # 'image' 是一个文件名,加载图像对象
        needleFileObj = open(needleImage, 'rb')
        needleImage = Image.open(needleFileObj)

    haystackFileObj = None
    if isinstance(haystackImage, (str, unicode)):
        # 'image' 是一个文件名,加载图像对象
        haystackFileObj = open(haystackImage, 'rb')
        haystackImage = Image.open(haystackFileObj)

    if region is not None:
        haystackImage = haystackImage.crop((region[0], region[1], region[0] + region[2], region[1] + region[3]))
    else:
        region = (0, 0)  # 因为代码总是考虑区域,所以设置为0

    if grayscale:  # 如果启用了灰度模式,则将needle和haystack图像转换为灰度图像
        needleImage = ImageOps.grayscale(needleImage)
        haystackImage = ImageOps.grayscale(haystackImage)
    else:
        # 如果不使用灰度,则确保比较的是RGB图像,而不是RGBA图像
        if needleImage.mode == 'RGBA':
            needleImage = needleImage.convert('RGB')
        if haystackImage.mode == 'RGBA':
            haystackImage = haystackImage.convert('RGB')

    # 设置一些常量
    needleWidth, needleHeight = needleImage.size
    haystackWidth, haystackHeight = haystackImage.size

    needleImageData = tuple(needleImage.getdata())
    haystackImageData = tuple(haystackImage.getdata())

    needleImageRows = [needleImageData[y * needleWidth:(y + 1) * needleWidth] for y in range(needleHeight)]
    needleImageFirstRow = needleImageRows[0]

    assert len(needleImageFirstRow) == needleWidth, '计算出的第一行的宽度与图像宽度不同。'
    assert [len(row) for row in needleImageRows] == [needleWidth] * needleHeight, 'needleImageRows的大小与原始图像大小不同。'

    numMatchesFound = 0

    # 注意: 经过在以下代码上运行测试/基准测试.py之后,似乎步长大于1并不会带来任何显著的性能改进。
    # 由于使用大于1的步长会导致匹配不够精确,因此将其设置为1。
    step = 1  # 硬编码步长为1,直到找到改进的方法。

    if step == 1:
        firstFindFunc = _kmp
    else:
        firstFindFunc = _steppingFind

    for y in range(haystackHeight):
        for matchx in firstFindFunc(needleImageFirstRow, haystackImageData[y * haystackWidth:(y + 1) * haystackWidth], step):
            foundMatch = True
            for searchy in range(1, needleHeight, step):
                haystackStart = (searchy + y) * haystackWidth + matchx
                if needleImageData[searchy * needleWidth:(searchy + 1) * needleWidth] != haystackImageData[
                                                                                           haystackStart:haystackStart + needleWidth]:
                    foundMatch = False
                    break
            if foundMatch:
                # 找到匹配,报告匹配区域在haystack中的x、y、宽度、高度。
                numMatchesFound += 1
                yield Box(matchx + region[0], y + region[1], needleWidth, needleHeight)
                if limit is not None and numMatchesFound >= limit:
                    # 达到限制。关闭文件句柄。
                    if needleFileObj is not None:
                        needleFileObj.close()
                    if haystackFileObj is not None:
                        haystackFileObj.close()
                    return

    # 没有限制或限制未达到,但是无论如何都要关闭文件句柄。
    if needleFileObj is not None:
        needleFileObj.close()
    if haystackFileObj is not None:
        haystackFileObj.close()

    if numMatchesFound == 0:
        if USE_IMAGE_NOT_FOUND_EXCEPTION:
            raise ImageNotFoundException('无法定位图像。')
        else:
            return

3. Demo

(×)错误版: (这里使用默认参数,有可能会错误,建议加上置信度参数)
我们先给一个Demo:(截图区域为当前,jd.jpg为当前区域的某一区域)

import pyautogui

target_image = 'target_image.png'

# 截取屏幕指定区域并保存为图像文件
screenshot = pyautogui.screenshot('shot.png')
print("截图已保存为 'shot.png'")

target_position = pyautogui.locate(target_image, screenshot)
print(target_position)

if target_position is not None:
    center_x = target_position.left + (target_position.width / 2)
    center_y = target_position.top + (target_position.height / 2)
    print("目标图像中心坐标:", center_x, center_y)

结果输出如下:

在这里插入图片描述

在PyAutoGUI中,locate()函数用于在屏幕截图(screenshot)中查找目标图像(target_image)的位置。它默认使用图像的灰度模式,并且没有指定置信度阈值时,默认置信度阈值为None。这意味着如果未指定置信度阈值,则需要确保目标图像与屏幕截图非常相似,才能成功定位。如果目标图像与屏幕截图不是完全相同,例如在颜色、尺寸或旋转方面有细微差异,那么可能会导致无法成功定位,此时返回的位置将为None。

在没有设置confidence参数的情况下,默认的阈值为None,这意味着需要与完全相同的图像匹配。而当设置了confidence参数时,PyAutoGUI会尝试寻找与目标图像非常相似的区域,只要相似度超过了设置的置信度阈值,就会返回匹配的位置

(√)正确版:

截图如下:

import pyautogui

target_image = 'target_image.png'

# 截取屏幕指定区域并保存为图像文件
screenshot = pyautogui.screenshot('shot.png')
print("截图已保存为 'shot.png'")

# 注意此处修改的位置
target_position = pyautogui.locate(target_image, screenshot,confidence=0.68)
print(target_position)

if target_position is not None:
    center_x = target_position.left + (target_position.width / 2)
    center_y = target_position.top + (target_position.height / 2)
    print("目标图像中心坐标:", center_x, center_y)

截图如下:

在这里插入图片描述

对于其他的参数还有region 以及 grayscale等
以下虽然可以执行,但是对于作者来说输出为None

  • 默认参数:
    target_position = pyautogui.locate('target_image.png', screenshot)
  • 区域参数:
    target_position = pyautogui.locate('target_image.png', screenshot, region=(100, 100, 800, 600))
  • 灰度参数:
    target_position = pyautogui.locate('target_image.png', screenshot, grayscale=True)

确保confidence可选参数在的话,在额外加其他可选参数,结果会正常:

# 注意此处修改的位置
target_position = pyautogui.locate(target_image, screenshot, confidence = 0.68 ,region=(1264, 32, 86, 24))

截图如下所示:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/482093.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DBO优化朴素贝叶斯分类预测(matlab代码)

DBO-朴素贝叶斯分类预测matlab代码 蜣螂优化算法(Dung Beetle Optimizer, DBO)是一种新型的群智能优化算法,在2022年底提出,主要是受蜣螂的的滚球、跳舞、觅食、偷窃和繁殖行为的启发。 数据为Excel分类数据集数据。 数据集划分为训练集、验证集、测试…

YOLO-v8-seg实例分割使用

最近需要实例分割完成一些任务,一直用的SAM(segment anything)速度慢,找一个轻量分割模型。 1. YOLO-v8-seg使用 git clone https://github.com/ultralytics/ultralytics.git cd ultralytics vim run.py from ultralytics import YOLO# L…

鸿蒙一次开发,多端部署(十三)功能开发的一多能力介绍

应用开发至少包含两部分工作: UI页面开发和底层功能开发(部分需要联网的应用还会涉及服务端开发)。前面章节介绍了如何解决页面适配的问题,本章节主要介绍应用如何解决设备系统能力差异的兼容问题。 系统能力 系统能力&#xff…

RK3568驱动指南|第十三篇 输入子系统-第143章 多对多的匹配关系分析

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…

有哪些强大好用的AI表格数据处理工具或者 AI Excel工具?

在繁忙的工作和生活中,处理大量的表格数据往往令人感到头疼。面对一列列数字、一行行文字,我们需要花费大量的时间和精力去整理、核对。然而,随着科技的飞速发展,人工智能(AI)技术正逐渐改变这一现状。 如…

LLM 面试知识点——模型基础知识

1、主流架构 目前LLM(Large Language Model)主流结构包括三种范式,分别为Encoder-Decoder、Causal Decoder、Prefix Decode。对应的网络整体结构和Attention掩码如下图。 、 各自特点、优缺点如下: 1)Encoder-Decoder 结构特点:输入双向注意力,输出单向注意力。 代表…

Flutter开发进阶之瞧瞧RenderObject

Flutter开发进阶之瞧瞧RenderObject 通过上回我们了解到Flutter执行buildTree的逻辑线,当Tree构建完成后会交给Flutter底层的渲染事件循环去执行将内容渲染到屏幕的操作。 但是渲染的操作到底是如何串起来的呢?这篇文章将会从Element联系到RenderObject…

点餐小程序php毕设项目

主要技术框架: 主要功能模块: 商品管理 订单管理 用户管理 优惠券管理 商品分类管理 评论管理 轮播图管理 截图 获取源码 https://blog.lusz.top/article?article_id-2

【Linux系统编程(进程编程)】创建进程的场景,fork和vfork的使用及区别

文章目录 一、进程关键概念二、创建进程函数fork的使用一、进程创建实战 三、创建进程函数fork的使用补充四、进程创建发生了什么事?五、创建新进程的实际应用场景 & fork总结一、fork创建一个子进程的一般目的?二、fork编程实战 六、vfork也能创建进…

grid布局

文章目录 1. 概念2. 组成2.1. 网格行2.2. 网格列2.3. 网格间距2.4. 网格线2.5. 网格容器2.6. fr 单位 3. 网格跨行跨列3.1. 跨列3.2. 跨行 4. 网格布局案例4.1. 演示效果4.2. 分析思路4.3. 代码实现 1. 概念 网格是一组相交的水平线和垂直线,它定义了网格的列和行。…

【排序算法】实现快速排序值(霍尔法三指针法挖坑法优化随即选key中位数法小区间法非递归版本)

文章目录 📝快速排序🌠霍尔法🌉三指针法🌠挖坑法✏️优化快速排序 🌠随机选key🌉三位数取中 🌠小区间选择走插入,可以减少90%左右的递归🌉 快速排序改非递归版本&#x1…

工业相机采图方式、图像格式(BYTE、HObject和Mat)转换

1、概述 机器视觉项目中,如何采集到合适的图像是项目的第一步,也是最重要的一步,直接关系到后面图像处理算法及最终执行的结果。所以采用不同的工业相机成像以及如何转换成图像处理库所需要的格式成为项目开发中首先要考虑的问题。 2、工业…

分布式组件 Nacos

1.在之前的文章写过的就不用重复写。 写一些没有写过的新东西 2.细节 2.1命名空间 : 配置隔离 默认: public (默认命名空间):默认新增所有的配置都在public空间下 2.1.1 开发 、测试 、生产:有不同的配置文件 比如…

【ZYNQ】基于ZYNQ 7020的OPENCV源码交叉编译

目录 安装准备 检查编译器 安装OpenCV编译的依赖项 下载OpenCV源码 下载CMake 编译配置 编译器说明 参考链接 安装准备 使用的各个程序的版本内容如下: 类别 软件名称 软件版本 虚拟机 VMware VMware-workstation-full-15.5.0-14665864 操作系统 Ub…

【QT入门】 Qt实现自定义信号

往期回顾: 【QT入门】图片查看软件(优化)-CSDN博客 【QT入门】 lambda表达式(函数)详解-CSDN博客 【QT入门】 Qt槽函数五种常用写法介绍-CSDN博客 【QT入门】 Qt实现自定义信号 一、为什么需要自定义信号 比如说现在一个小需求,我们想要实现跨ui通信&a…

Hive入门

什么是hive? - Hive是Facebook开发并贡献给Hadoop开源社区的。它是建立在 Hadoop体系架构上的一层 SQL抽象,使得数据相关人 员使用他们最为熟悉的SQL语言就可以进行海量数据的处理、 分析和统计工作 - Hive将数据存储于HDFS的数据文件映射为一张数据库…

Java程序设计 4、5章 练习题

一、填空题 1.假设有 String s1 "Welcome to Java"; String s2 s1; String s3 new String("Welcome to Java"); 那么下面表达式的结果是什么? (1) s1 s2 ___________true_______________ (2) s1 s3 ______…

SOPHON算能服务器SDK环境配置和相关库安装

目录 1 SDK大包下载 2 安装libsophon 2.1 安装依赖 1.2 安装libsophon 2 安装 sophon-mw 参考文献: 1 SDK大包下载 首先需要根据之前的博客,下载SDK大包:SOPHON算能科技新版SDK环境配置以及C demo使用过程_sophon sdk yolo-CSDN博客 …
最新文章