详细分析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

相关文章

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

函数式编程思想

我们经常会用到各种各样的编程思想,例如面向过程、面向对象。不过笔者在该博客简单介绍一下函数式编程思想. 如果对函数式编程思想进行概括,就是f(x) = na(x) , y=uf(x)…至于其他的编程思想,可能是y=a(x)+b(x)+c(x)…,也有可能是y=f(x)=f(x)/a + f(x)/b+f(x)/c… 面向过程的指令式编程 面向过程,简单理解就是y=a(x)+b(x)+c(x)

利用matlab bar函数绘制较为复杂的柱状图,并在图中进行适当标注

示例代码和结果如下:小疑问:如何自动选择合适的坐标位置对柱状图的数值大小进行标注?😂 clear; close all;x = 1:3;aa=[28.6321521955954 26.2453660695847 21.69102348512086.93747104431360 6.25442246899816 3.342835958564245.51365061796319 4.87

OpenCV结构分析与形状描述符(11)椭圆拟合函数fitEllipse()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C++11 算法描述 围绕一组2D点拟合一个椭圆。 该函数计算出一个椭圆,该椭圆在最小二乘意义上最好地拟合一组2D点。它返回一个内切椭圆的旋转矩形。使用了由[90]描述的第一个算法。开发者应该注意,由于数据点靠近包含的 Mat 元素的边界,返回的椭圆/旋转矩形数据

Unity3D 运动之Move函数和translate

CharacterController.Move 移动 function Move (motion : Vector3) : CollisionFlags Description描述 A more complex move function taking absolute movement deltas. 一个更加复杂的运动函数,每次都绝对运动。 Attempts to

✨机器学习笔记(二)—— 线性回归、代价函数、梯度下降

1️⃣线性回归(linear regression) f w , b ( x ) = w x + b f_{w,b}(x) = wx + b fw,b​(x)=wx+b 🎈A linear regression model predicting house prices: 如图是机器学习通过监督学习运用线性回归模型来预测房价的例子,当房屋大小为1250 f e e t 2 feet^

JavaSE(十三)——函数式编程(Lambda表达式、方法引用、Stream流)

函数式编程 函数式编程 是 Java 8 引入的一个重要特性,它允许开发者以函数作为一等公民(first-class citizens)的方式编程,即函数可以作为参数传递给其他函数,也可以作为返回值。 这极大地提高了代码的可读性、可维护性和复用性。函数式编程的核心概念包括高阶函数、Lambda 表达式、函数式接口、流(Streams)和 Optional 类等。 函数式编程的核心是Lambda

PHP APC缓存函数使用教程

APC,全称是Alternative PHP Cache,官方翻译叫”可选PHP缓存”。它为我们提供了缓存和优化PHP的中间代码的框架。 APC的缓存分两部分:系统缓存和用户数据缓存。(Linux APC扩展安装) 系统缓存 它是指APC把PHP文件源码的编译结果缓存起来,然后在每次调用时先对比时间标记。如果未过期,则使用缓存的中间代码运行。默认缓存 3600s(一小时)。但是这样仍会浪费大量C

PHP7扩展开发之函数方式使用lib库

前言 首先说下什么是lib库。lib库就是一个提供特定功能的一个文件。可以把它看成是PHP的一个文件,这个文件提供一些函数方法。只是这个lib库是用c或者c++写的。 使用lib库的场景。一些软件已经提供了lib库,我们就没必要再重复实现一次。如,原先的mysql扩展,就是使用mysql官方的lib库进行的封装。 在本文,我们将建立一个简单的lib库,并在扩展中进行封装调用。 代码 基础