Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 1|回复: 0

了解Python SIFT找图工具 - 替代pyautogui现精准图像匹配

[复制链接]

36万

主题

0

回帖

109万

积分

超级版主

Rank: 8Rank: 8

积分
1092248
发表于 前天 20:07 | 显示全部楼层 |阅读模式
前言:
在游戏脚本类辅助中,找图坐标是一个常见需求。现成工具和方法虽然不少,但要保证高精度并不容易。

比如python自带的pyautogui的locateOnScreen只支持100%图像匹配度,这是一个点,精准找图,但也是个缺点,背景一变化就找不到了。

再例如按键精灵的找图功能,虽然能自定义设置找图匹配率,但依然在某些背景的变换下仍然法匹配到图像。

本篇教程将使用匹配精度比较高的SIFT算法来现一个多参数可控的找图功能。为什么说精度比较高因为在这类图像匹配算法中著的有ORB、SURF、SIFT,而SIFT算法是一种即便图像在不同尺度、旋转、光照变化的情况下,它依然可以保持良好的匹配性能的算法,当然SIFT的效率自然也是比其他低一些的,不过就算低也低不了多少,对吧,所以我们还是用精度比较高的SIFT算法。

关于算法各位不用担心,比较后会我会封装为一个工具函数,直接使用就行了。

所需库:
importos
importcv2
importpyautogui

正文:
首步:获取屏幕截图与目标图片数据
我们将使用pyautogui截取全屏图片,然后通过OpenCV读取屏幕截图和待匹配的目标图像。以下代码将截屏并读取图像数据,numpy数组:

importpyautogui
importcv2

pyautoguiscreenshot(imageFilename="screenpng")
screenPic=cv2imread("screenpng")
img_url=r"C:\testpic\wxpng"
myPic=cv2imread(img_url)
第二步:获取图像的关键点与描述符
使用SIFT算法提取屏幕截图和目标图片的关键点及描述符:

sift=cv2SIFT_create()
screenPicKP,screenPicDES=siftdetectAndCompute(screenPic,None)
myPicKP,myPicDES=siftdetectAndCompute(myPic,None)
第步:配置Flann匹配器
接下来,设置Flann匹配器的参数。Flann是一种速匹配算法,适合大数据集的匹配。我们可以通过设置trees和checks参数来调整精度和速度的平衡:

indexParams=dict(algorithm=0,trees=100)
searcheParams=dict(checks=1000)
flann=cv2FlannBasedMatcher(indexParams,searcheParams)
第四步:进行图像匹配
使用Flann的knn匹配法获取初步匹配结果,并根据特征点的距离对结果进行排序:

matches=flannknnMatch(screenPicDES,myPicDES,k=2)
matches=sorted(matches,key=lambdax:x[0]distance)
第五步:筛选比较匹配并坐标
通过循环调整匹配率,找到比较匹配并坐标。比较大搜索系数和初始匹配率都可自定义,以确保找到图像的比较位置:

x,y=None,None
max_init_num=04
init_num=01

whileinit_num<=max_init_num:
goodMatches=
form,ninmatches:
ifmdistance<init_num*ndistance:
goodMatches脚本end(m)
index=int(len(goodMatches)2)
try:
x,y=screenPicKP[goodMatches[index]queryIdx]pt
break
except:
init_num+=01

osremove("screenpng")
print(f"图像在屏幕上的x坐标为:{x}")
print(f"图像在屏幕上的y坐标为:{y}")
封装为工具函数
importos
importpyautogui
importcv2

'''
注意:文件路径不能含有中文!!!文件也不能含有中文!!!
picPath:要找的图的路劲
tress:kd树的数量,数值越大,精度越大,但耗时越高,建议设置为100足够
checks:节点检查数量,数值越大,精度越大,但耗时越高,建议设置为1000足够
maxInit:比较大搜索系数,范围为大于0~1的小数,建议设置为05或者07。数值越小找的越精确,但是也可能找不到;数值越大找到的可能性更大,但也可能会找错。
'''
defFindPicSIFT(picPath,trees,checks,maxInit):
#首步:获取屏幕截图与目标图片数据
pyautoguiscreenshot(imageFilename="screenpng")
screenPic=cv2imread("screenpng")
imgPath=r""+picPath
myPic=cv2imread(imgPath)

#第二步:获取图像的关键点与描述符
sift=cv2SIFT_create()
screenPicKP,screenPicDES=siftdetectAndCompute(screenPic,None)
myPicKP,myPicDES=siftdetectAndCompute(myPic,None)

#第步:配置Flann匹配器
indexParams=dict(algorithm=0,trees=trees)
searchParams=dict(checks=checks)
flann=cv2FlannBasedMatcher(indexParams,searchParams)

#第四步:进行图像匹配
matches=flannknnMatch(screenPicDES,myPicDES,k=2)
matches=sorted(matches,key=lambdax:x[0]distance)

#第五步:筛选比较匹配并坐标
x,y=None,None
max_init_num=maxInit
init_num=01

whileinit_num<=max_init_num:
goodMatches=
form,ninmatches:
ifmdistance<init_num*ndistance:
goodMatches脚本end(m)
index=int(len(goodMatches)2)
try:
x,y=screenPicKP[goodMatches[index]queryIdx]pt
break
except:
init_num+=01

#第六步:移除截图,并坐标
osremove("screenpng")
returnx,y
初步测试
初步测试显示该方法可以成功找到图像,并通过pyautoguimoveTo移动鼠标至找到的图像位置。



模糊测试
即便对目标图片进行了模糊处理,SIFT算法依然能够有效识别,可见其识别能力还是很不错的,这里用的比较大搜索系数为01



我们的络技术交流Q群:307531422



于是源码网也得到了很多的关注,也想加入到这个行列当中。提供经过严格测试的免费源码、各种线上兼职和网络兼职的网创教程、编程及网络相关的技术教程分享,助您轻松获取资源和技术支持。https://www.youluoyuan.com/

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|足球新闻网

GMT+8, 2025-4-22 00:10 , Processed in 0.055625 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表