python3中图像识别的应用open-CV库
什么是open-CV?
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法(百度百科)。
代码:
定义图像识别的类
import cv2
import os
from PIL import ImageGrab
# 定义一个图像识别的类ImageMatch
class ImageMatch:
# 图像识别算法的核心,传入模版图片的文件名,返回识别后的中心点坐标
def find_image(self, target):
# 构造一个基本的图片路径
base_path = os.path.join(os.getcwd(), 'source')
# 构造截屏大图的保存路径
screen_path = os.path.join(base_path, 'screen.png')
# 利用pillow库的ImageGrab类来去完成截图的动作
ImageGrab.grab().save(screen_path)
# 利用opencv库分别读取大图和小图对象
screen = cv2.imread(screen_path)
template = cv2.imread(os.path.join(base_path, target))
# 利用matchTemplate方法进行模板匹配
result = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED)
# 利用minMaxLoc方法提取similarity和匹配时的左顶点坐标
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
similarity = max_val
if similarity < 0.95:
return -1, -1
# 计算中心点坐标
# 利用template对象的shape属性来获取模板图片的宽高数据,但是要注意这个属性返回的是(高,宽)这样的元组数据。
# x = 左顶点的x值 + 模版图片对象的shape属性值的宽度数据,也就是其属性值的第二个元素,下标是[1]
# y = 左顶点的y值 + 模板图片对象的shape属性值的高度数据,也就是其属性值的第一个元素,小标是[0]
x = max_loc[0] + int(template.shape[1] / 2)
y = max_loc[1] + int(template.shape[0] / 2)
return x, y
# 定义检查指定模版是否存在的方法,用于断言
def check_exist(self, target):
x, y = self.find_image(target)
return x != -1 and y != -1
模板匹配进行操作
from image_match.image_match import ImageMatch
from pykeyboard import PyKeyboard
from pymouse import PyMouse
import os
import time
class ImageTest:
def __init__(self):
self.matcher = ImageMatch()
# 分别构造键盘、鼠标操作对象。
self.keyboard = PyKeyboard()
self.mouse = PyMouse()
# 启动应用
def start_app(self, cmd):
os.system(f'start /b {cmd}')
time.sleep(3)
# 单击操作,参数是定位图片
def on_click(self, target):
x, y = self.matcher.find_image(target)
# 检查过滤未找到指定图片的情况
if x == -1 or y == -1:
print(f'not found {target}.')
return -1, -1
# 找到后进行鼠标单击操作
self.mouse.click(x, y)
print(f'click {target} at [{x}, {y}].')
# 为操作留出一点时间,防止操作过速导致的误动作
time.sleep(0.5)
return x, y
# 双击操作
def on_double_click(self, target):
x, y = self.matcher.find_image(target)
if x == -1 or y == -1:
print(f'not found {target}.')
return -1, -1
self.mouse.click(x, y, n=2)
print(f'double click {target} at [{x}, {y}].')
time.sleep(0.5)
return x, y
# 输入操作,参数分别为指定的图片和待输入内容
def input_text(self, target, content):
x, y = self.on_double_click(target)
if x == -1 or y == -1:
return
self.keyboard.type_string(str(content))
print(f'input {content} at {target}.')
time.sleep(0.5)
# 下拉操作
def select(self, target, count=0):
# 因为下拉选择只有4个可选值,所以这里对输入的次数进行一个预处理
x, y = self.on_click(target)
if x == -1 or y == -1:
return
count = count % 4
for _ in range(count):
self.keyboard.press_key(self.keyboard.down_key)
time.sleep(0.5)
self.keyboard.press_key(self.keyboard.enter_key)
time.sleep(0.5)
def start_test(self):
self.start_app('java -jar JavaSwingCalc.jar')
self.input_text('numberx.png', 200)
self.input_text('numbery.png', 100)
self.select('calctype.png', 1)
self.on_click('docalc.png')
assert self.matcher.check_exist('result.png'), f'计算结果与期望值100不相等。'
self.on_click('doclose.png')