详细分析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中COALESCE函数示例详解

《MySQL中COALESCE函数示例详解》COALESCE是一个功能强大且常用的SQL函数,主要用来处理NULL值和实现灵活的值选择策略,能够使查询逻辑更清晰、简洁,:本文主要介绍MySQL中C... 目录语法示例1. 替换 NULL 值2. 用于字段默认值3. 多列优先级4. 结合聚合函数注意事项总结C

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

golang panic 函数用法示例详解

《golangpanic函数用法示例详解》在Go语言中,panic用于触发不可恢复的错误,终止函数执行并逐层向上触发defer,最终若未被recover捕获,程序会崩溃,recover用于在def... 目录1. panic 的作用2. 基本用法3. recover 的使用规则4. 错误处理建议5. 常见错

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

Java function函数式接口的使用方法与实例

《Javafunction函数式接口的使用方法与实例》:本文主要介绍Javafunction函数式接口的使用方法与实例,函数式接口如一支未完成的诗篇,用Lambda表达式作韵脚,将代码的机械美感... 目录引言-当代码遇见诗性一、函数式接口的生物学解构1.1 函数式接口的基因密码1.2 六大核心接口的形态学

Windows自动化Python pyautogui RPA操作实现

《Windows自动化PythonpyautoguiRPA操作实现》本文详细介绍了使用Python的pyautogui库进行Windows自动化操作的实现方法,文中通过示例代码介绍的非常详细,对大... 目录依赖包睡眠:鼠标事件:杀死进程:获取所有窗口的名称:显示窗口:根据图片找元素:输入文字:打开应用:依

Oracle的to_date()函数详解

《Oracle的to_date()函数详解》Oracle的to_date()函数用于日期格式转换,需要注意Oracle中不区分大小写的MM和mm格式代码,应使用mi代替分钟,此外,Oracle还支持毫... 目录oracle的to_date()函数一.在使用Oracle的to_date函数来做日期转换二.日