找回密码
 会员注册
查看: 18|回复: 0

利用Python+OpenCV实现截图匹配图像,支持自适应缩放、灰度匹配、区域匹配、匹配多个结果

[复制链接]

2

主题

0

回帖

7

积分

新手上路

积分
7
发表于 2024-9-10 23:10:09 | 显示全部楼层 |阅读模式
可以直接通过pip获取,无需手动安装其他依赖pipinstallxug示例:importxugxug.find_image_on_screen(,,,)=========================================================================一、依赖安装pipinstallopencv-pythonpipinstallpyautogui二、获取系统缩放比例注意:必须先通过ctypes获取wid之后才能导入pyautogui,如果需要在其它代码中引用该模块,最好把获取分辨率这部分代码放到程序入口处,然后传递给识图函数,避免提前导入pyautogui导致获取分辨率失败。#获取当前系统缩放比例importctypes#wid必须在导入pyautogui之前赋值wid=ctypes.windll.user32.GetSystemMetrics(0)importpyautoguiscreen_width,_=pyautogui.size()true_scale=screen_width/wid 三、定义匹配结果类x,y表示中心坐标,x1,y1,x2,y2表示四个顶点的坐标,match表示匹配度,取值范围0-100。fromdataclassesimportdataclass#定义匹配结果类@dataclassclassMatchInfo:match:float=0x:int=0y:int=0x1:int=0y1:int=0x2:int=0y2:int=0@staticmethoddefnot_found():returnMatchInfo()def__str__(self):return(f"匹配度={self.match:.2f},"f"中心坐标{self.x},{self.y})")四、完整代码参数:template:模板图片,字符串,即待匹配图片,支持两种形式,可以传入图片地址,也可以直接传入图片名称,此时会从代码中设定的图片文件夹寻找图片;min_threshold:最小匹配度,浮点数,只返回匹配度大于等于该值的结果,取值范围0-100gray:灰度匹配,布尔值,为真时则忽略颜色,可以大幅提升匹配速度,适用于不考虑颜色的情况a,b,c,d:区域匹配坐标,整数,都为0时不生效,否则只在该区域匹配,但是返回的结果坐标任然是相对于整个屏幕image_sacle:图片缩放,浮点数,即传入的图片的缩放,也就是截图时电脑对应的缩放,默认和1.25,即125%,需要自己根据情况修改,取值是(1,1.25,1.5,1.75,2)max_deviation:最大偏差值,整数,多个匹配结果之间距离的最小值,如果存在同一个目标被识别成两个结果的情况,可以适当增加这个参数的值返回值:列表类型,包含所有符合条件的匹配结果(MatchInfo对象),如果没有匹配到则是空列表#获取当前系统缩放比例importctypes#wid必须在导入pyautogui之前赋值wid=ctypes.windll.user32.GetSystemMetrics(0)importpyautoguiscreen_width,_=pyautogui.size()true_scale=screen_width/widfromdataclassesimportdataclass#定义匹配结果类@dataclassclassMatchInfo:match:float=0x:int=0y:int=0x1:int=0y1:int=0x2:int=0y2:int=0@staticmethoddefnot_found():returnMatchInfo()def__str__(self):return(f"匹配度={self.match:.2f},"f"中心坐标{self.x},{self.y})")importcv2importosimportnumpyasnp#识图函数deffind_image_on_screen(template,min_threshold,gray=False,a=0,b=0,c=0,d=0,image_sacle=1.25,max_deviation=13):#图片存放地址image_path='D:\\test\\image'#处理传入的匹配度min_threshold=min_threshold/100#路径处理,如果传入的参数只是图片名称,就从默认路径寻找改图片ifnotos.path.isabs(template):template=os.path.join(image_path,template)#读取模板图片templ=cv2.imread(template)#获取屏幕截图screenshot=cv2.cvtColor(np.array(pyautogui.screenshot()),cv2.COLOR_RGB2BGR)#获取模板图片长宽xx,yy=templ.shape[:-1]#如果实际缩放和图片缩放不一致,就进行调整iftrue_scale!=image_sacle:screenshot=cv2.resize(screenshot,None,fx=image_sacle/true_scale,fy=image_sacle/true_scale)#判断是否需要灰度匹配ifgray:screenshot=cv2.cvtColor(screenshot,cv2.COLOR_BGR2GRAY)templ=cv2.cvtColor(templ,cv2.COLOR_BGR2GRAY)#判断是否需要区域匹配ifa==0andb==0andc==0andd==0:screenshot_region=screenshot#默认情况下,使用整个截图else:#这里需要特殊处理,避免裁剪后的截图比模板图片小导致报错c=max(a+yy,c)d=max(b+xx,d)#裁剪截图screenshot_region=screenshot[b:d,a:c]#执行模板匹配result=cv2.matchTemplate(screenshot_region,templ,cv2.TM_CCOEFF_NORMED)#获取满足匹配度的结果locations=np.where(result>=min_threshold)locations=list(zip(*locations[::-1]))match_info={}#对匹配结果进行筛选和去重,避免同一个目标被识别成多个结果,可以通过调整max_deviation的值来调整效果forlocinlocations:x,y=locx=x+a#调整x坐标以匹配整个截图y=y+b#调整y坐标以匹配整个截图match_value=result[y-b,x-a]skip_current=Falsefor(prev_x,prev_y),prev_match_valueinmatch_info.items():ifabs(x-prev_x)prev_match_value:match_info[(x,y)]=match_valuedelmatch_info[(prev_x,prev_y)]else:skip_current=Truebreakifnotskip_current:match_info[(x,y)]=match_value#构建匹配结果列表match_info_objects=[]for(x,y),match_valueinsorted(match_info.items(),key=lambdax:x[1],reverse=True):h,w=xx,yytop_left=(x,y)bottom_right=(x+w,y+h)center=(x+w//2,y+h//2)matche=MatchInfo(match_value*100,center[0],center[1],top_left[0],top_left[1],bottom_right[0],bottom_right[1],)match_info_objects.append(matche)returnmatch_info_objects五、示例用法if__name__=='__main__':#根据图片名称匹配,其他参数取默认值print("test1:")forsin(find_image_on_screen('test1.png')):print(s)print("test2:")#根据图片路径匹配,匹配度85forsin(find_image_on_screen('D:\\test\\image\\test2.png',min_threshold=85)):print(s)print("test3:")#根据路径匹配,忽略颜色,在指定区域匹配forsin(find_image_on_screen('D:\\test\\image\\test3.png',gray=True,a=11,b=35,c=983,d=639)):print(s)运行结果:
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-3 03:04 , Processed in 0.781160 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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