当前位置:   article > 正文

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

python opencv图像匹配
可以直接通过pip获取,无需手动安装其他依赖
pip install xug

示例:

  1. import xug
  2. xug.find_image_on_screen(,,,)

=========================================================================

一、依赖安装

  1. pip install opencv-python
  2. pip install pyautogui

二、获取系统缩放比例

注意:必须先通过ctypes获取wid之后才能导入pyautogui,如果需要在其它代码中引用该模块,最好把获取分辨率这部分代码放到程序入口处,然后传递给识图函数,避免提前导入pyautogui导致获取分辨率失败。

  1. # 获取当前系统缩放比例
  2. import ctypes
  3. # wid必须在导入pyautogui之前赋值
  4. wid = ctypes.windll.user32.GetSystemMetrics(0)
  5. import pyautogui
  6. screen_width , _ = pyautogui.size()
  7. true_scale=screen_width/wid

 三、定义匹配结果类

x,y表示中心坐标,x1,y1,x2,y2表示四个顶点的坐标,match表示匹配度,取值范围0-100。

  1. from dataclasses import dataclass
  2. # 定义匹配结果类
  3. @dataclass
  4. class MatchInfo:
  5. match: float = 0
  6. x: int = 0
  7. y: int = 0
  8. x1: int = 0
  9. y1: int = 0
  10. x2: int = 0
  11. y2: int = 0
  12. @staticmethod
  13. def not_found():
  14. return MatchInfo()
  15. def __str__(self):
  16. return (
  17. f"匹配度={self.match:.2f}, "
  18. f"中心坐标: ({self.x}, {self.y}) "
  19. )

四、完整代码

参数:

template:模板图片,字符串,即待匹配图片,支持两种形式,可以传入图片地址,也可以直接传入图片名称,此时会从代码中设定的图片文件夹寻找图片;

min_threshold:最小匹配度,浮点数,只返回匹配度大于等于该值的结果,取值范围0-100

gray:灰度匹配,布尔值,为真时则忽略颜色,可以大幅提升匹配速度,适用于不考虑颜色的情况

a,b,c,d:区域匹配坐标,整数,都为0时不生效,否则只在该区域匹配,但是返回的结果坐标任然是相对于整个屏幕

image_sacle:图片缩放,浮点数,即传入的图片的缩放,也就是截图时电脑对应的缩放,默认和1.25,即125%,需要自己根据情况修改,取值是(1,1.25,1.5,1.75,2)

max_deviation:最大偏差值,整数,多个匹配结果之间距离的最小值,如果存在同一个目标被识别成两个结果的情况,可以适当增加这个参数的值

返回值:

列表类型,包含所有符合条件的匹配结果(MatchInfo对象),如果没有匹配到则是空列表

  1. # 获取当前系统缩放比例
  2. import ctypes
  3. # wid必须在导入pyautogui之前赋值
  4. wid = ctypes.windll.user32.GetSystemMetrics(0)
  5. import pyautogui
  6. screen_width , _ = pyautogui.size()
  7. true_scale=screen_width/wid
  8. from dataclasses import dataclass
  9. # 定义匹配结果类
  10. @dataclass
  11. class MatchInfo:
  12. match: float = 0
  13. x: int = 0
  14. y: int = 0
  15. x1: int = 0
  16. y1: int = 0
  17. x2: int = 0
  18. y2: int = 0
  19. @staticmethod
  20. def not_found():
  21. return MatchInfo()
  22. def __str__(self):
  23. return (
  24. f"匹配度={self.match:.2f}, "
  25. f"中心坐标: ({self.x}, {self.y}) "
  26. )
  27. import cv2
  28. import os
  29. import numpy as np
  30. # 识图函数
  31. def find_image_on_screen(template, min_threshold, gray=False, a=0, b=0, c=0, d=0,image_sacle=1.25,max_deviation = 13):
  32. # 图片存放地址
  33. image_path='D:\\test\\image'
  34. # 处理传入的匹配度
  35. min_threshold = min_threshold / 100
  36. # 路径处理,如果传入的参数只是图片名称,就从默认路径寻找改图片
  37. if not os.path.isabs(template):
  38. template = os.path.join(image_path, template)
  39. # 读取模板图片
  40. templ = cv2.imread(template)
  41. # 获取屏幕截图
  42. screenshot = cv2.cvtColor(np.array(pyautogui.screenshot()), cv2.COLOR_RGB2BGR)
  43. # 获取模板图片长宽
  44. xx, yy = templ.shape[:-1]
  45. # 如果实际缩放和图片缩放不一致,就进行调整
  46. if true_scale != image_sacle:
  47. screenshot = cv2.resize(screenshot, None, fx=image_sacle / true_scale, fy=image_sacle / true_scale)
  48. # 判断是否需要灰度匹配
  49. if gray:
  50. screenshot = cv2.cvtColor(screenshot, cv2.COLOR_BGR2GRAY)
  51. templ = cv2.cvtColor(templ, cv2.COLOR_BGR2GRAY)
  52. # 判断是否需要区域匹配
  53. if a==0 and b==0 and c==0 and d==0:
  54. screenshot_region = screenshot # 默认情况下,使用整个截图
  55. else:
  56. # 这里需要特殊处理,避免裁剪后的截图比模板图片小导致报错
  57. c = max(a + yy, c)
  58. d = max(b + xx, d)
  59. # 裁剪截图
  60. screenshot_region = screenshot[b:d, a:c]
  61. # 执行模板匹配
  62. result = cv2.matchTemplate(screenshot_region, templ, cv2.TM_CCOEFF_NORMED)
  63. # 获取满足匹配度的结果
  64. locations = np.where(result >= min_threshold)
  65. locations = list(zip(*locations[::-1]))
  66. match_info = {}
  67. # 对匹配结果进行筛选和去重,避免同一个目标被识别成多个结果,可以通过调整max_deviation的值来调整效果
  68. for loc in locations:
  69. x, y = loc
  70. x = x + a # 调整x坐标以匹配整个截图
  71. y = y + b # 调整y坐标以匹配整个截图
  72. match_value = result[y - b, x - a]
  73. skip_current = False
  74. for (prev_x, prev_y), prev_match_value in match_info.items():
  75. if abs(x - prev_x) <= max_deviation and abs(y - prev_y) <= max_deviation:
  76. if match_value > prev_match_value:
  77. match_info[(x, y)] = match_value
  78. del match_info[(prev_x, prev_y)]
  79. else:
  80. skip_current = True
  81. break
  82. if not skip_current:
  83. match_info[(x, y)] = match_value
  84. # 构建匹配结果列表
  85. match_info_objects = []
  86. for (x, y), match_value in sorted(
  87. match_info.items(), key=lambda x: x[1], reverse=True
  88. ):
  89. h, w = xx, yy
  90. top_left = (x, y)
  91. bottom_right = (x + w, y + h)
  92. center = (x + w // 2, y + h // 2)
  93. matche = MatchInfo(
  94. match_value * 100,
  95. center[0],
  96. center[1],
  97. top_left[0],
  98. top_left[1],
  99. bottom_right[0],
  100. bottom_right[1],
  101. )
  102. match_info_objects.append(matche)
  103. return match_info_objects

五、示例用法

  1. if __name__=='__main__':
  2. # 根据图片名称匹配,其他参数取默认值
  3. print("test1:")
  4. for s in (find_image_on_screen('test1.png')):
  5. print(s)
  6. print("test2:")
  7. # 根据图片路径匹配,匹配度85
  8. for s in (find_image_on_screen('D:\\test\\image\\test2.png',min_threshold=85)):
  9. print(s)
  10. print("test3:")
  11. # 根据路径匹配,忽略颜色,在指定区域匹配
  12. for s in (find_image_on_screen('D:\\test\\image\\test3.png',gray=True,a=11,b=35,c=983,d=639)):
  13. print(s)

运行结果:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/923697
推荐阅读
相关标签
  

闽ICP备14008679号