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

2024-03-22 17:36

本文主要是介绍详细分析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('无法定位图像。')# 否则返回Noneelse: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_DEFAULTneedleFileObj = Noneif isinstance(needleImage, (str, unicode)):# 'image' 是一个文件名,加载图像对象needleFileObj = open(needleImage, 'rb')needleImage = Image.open(needleFileObj)haystackFileObj = Noneif 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)  # 因为代码总是考虑区域,所以设置为0if 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.sizehaystackWidth, haystackHeight = haystackImage.sizeneedleImageData = 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 = _kmpelse:firstFindFunc = _steppingFindfor y in range(haystackHeight):for matchx in firstFindFunc(needleImageFirstRow, haystackImageData[y * haystackWidth:(y + 1) * haystackWidth], step):foundMatch = Truefor searchy in range(1, needleHeight, step):haystackStart = (searchy + y) * haystackWidth + matchxif needleImageData[searchy * needleWidth:(searchy + 1) * needleWidth] != haystackImageData[haystackStart:haystackStart + needleWidth]:foundMatch = Falsebreakif foundMatch:# 找到匹配,报告匹配区域在haystack中的x、y、宽度、高度。numMatchesFound += 1yield 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 pyautoguitarget_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 pyautoguitarget_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))

截图如下所示:

在这里插入图片描述

这篇关于详细分析PyAutoGUI中的locate函数(附Demo)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/835820

相关文章

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

C++ Sort函数使用场景分析

《C++Sort函数使用场景分析》sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变,如果某些场景需要保持相同元素间的相对顺序,可使... 目录C++ Sort函数详解一、sort函数调用的两种方式二、sort函数使用场景三、sort函数排序

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

C/C++错误信息处理的常见方法及函数

《C/C++错误信息处理的常见方法及函数》C/C++是两种广泛使用的编程语言,特别是在系统编程、嵌入式开发以及高性能计算领域,:本文主要介绍C/C++错误信息处理的常见方法及函数,文中通过代码介绍... 目录前言1. errno 和 perror()示例:2. strerror()示例:3. perror(

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda

C++中::SHCreateDirectoryEx函数使用方法

《C++中::SHCreateDirectoryEx函数使用方法》::SHCreateDirectoryEx用于创建多级目录,类似于mkdir-p命令,本文主要介绍了C++中::SHCreateDir... 目录1. 函数原型与依赖项2. 基本使用示例示例 1:创建单层目录示例 2:创建多级目录3. 关键注

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程