基于OpenCV图像识别实现UI自动化测试


一、框架实现思路

使用模板匹配的思路,在程序运行的时候,使用python pillow模块进行截图,获取当前程序运行的大图,提前准备好模板图片,进行匹配验证

1.模板匹配

a.需要安装cv2就是安装OpenCV

pip install opencv-python

b.OpenCV中使用matchTemplate函数来实现模板匹配

cv2.matchTemplate(image, templ, method, result=None, mask=None)

image:待搜索图像
templ:模板图像
result:匹配结果
method:计算匹配程度的方法

c.匹配方法

关于匹配方法,使用不同的方法产生的结果的意义可能不太一样,有些返回的值越大表示匹配程度越好,而有些方法返回的值越小表示匹配程度越好。

关于参数 method:

CV_TM_SQDIFF 平方差匹配法:该方法采用平方差来进行匹配;最好的匹配值为0;匹配越差,匹配值越大。
CV_TM_CCORR 相关匹配法:该方法采用乘法操作;数值越大表明匹配程度越好。
CV_TM_CCOEFF 相关系数匹配法:1表示完美的匹配;-1表示最差的匹配。
CV_TM_SQDIFF_NORMED 归一化平方差匹配法
CV_TM_CCORR_NORMED 归一化相关匹配法
CV_TM_CCOEFF_NORMED 归一化相关系数匹配法  #本次使用

d.通过MinMaxLoc获取最后的最佳匹配结果

利用OpenCV minMaxLoc 传入的参数就是matchTemplate的返回值,minMaxLoc自己的返回值是一个元素,分别为(最小值,最大值,最小值所在点坐标,最大值所在点坐标)

2.截图

使用pillow模块,安装:

pip install pillow

截图代码如下:

from PIL import ImageGrab

#截取当前屏幕图片,并保存
ImageGrab.grab().save(图片路径以及名字)

3.调用鼠标键盘事件

需要安装python鼠标键盘模块

pip install PyUserInput

导入模块

#鼠标事件
from
pymouse import PyMouse
#键盘事件
from pykeyboard import PyKeyboard

二、实例代码

以完成win10自带计算器中计算功能为例:

1.封装图像识别核心算法,创建ImageTemplate.py文件,内容如下:

import os
from PIL import ImageGrab
import cv2

class ImageTemplate:

    def find_image(self, tmplate_image):
        #构造图片路径
        base_path = os.path.join(os.getcwd(), "source")
        #截图文件保存路径
        Screenshot_file = os.path.join(base_path, "screen.png")

        #截取当前屏幕图片,并保存
        ImageGrab.grab().save(Screenshot_file)
        #使用opencv库的imread方法分别读取需要匹配的原始大图和模板图片
        screen = cv2.imread(Screenshot_file) #使用截取的图片为原始大图
        template = cv2.imread(os.path.join(base_path, tmplate_image))  #传入模板图片

        #使用opencv库的matchTemplate方法静态模块匹配,如果模板图片在原始大图上匹配时,则返回模板左顶点在每一个位置的匹配度,它是一个二维列表数据。
        result = cv2.matchTemplate(screen, template, cv2.TM_CCOEFF_NORMED) #参数分别是 元素大图、模板图片、匹配算法
        #利用OpenCV minMaxLoc 传入的参数就是matchTemplate的返回值,minMaxLoc自己的返回值是一个元素,分别为(最小值,最大值,最小值所在点坐标,最大值所在点坐标)
        min, max, min_loc, max_loc = cv2.minMaxLoc(result)

        if max <= 0.95:
            return -1,-1
        else:
            #此时意味着找到了匹配位置,需要计算中心点的坐标(后边点击,以及其他操作都是根据中心的坐标点击的)
            #由max_loc可获得匹配度最高的左顶点
            #中心点坐标计算公式:左顶点坐标分别加上模块的宽高除以2
            #模板的宽高需要从模板对象template中获取,具体template.shape属性,这个属性得到的是一个元素数据(高、宽)
            #中心点x坐标 = 左顶点x坐标 + int(template.shape[1]/2)
            #中心点y坐标 = 左顶点y坐标 + int(template.shape[0]/2)
            x = max_loc[0] + int(template.shape[1]/2)
            y = max_loc[1] + int(template.shape[0]/2)
            return x,y

    #断言查找的图片是否存在,
    def assertion(self, image):
        x,y = self.find_image(image)
        #如果x y都不等于-1则匹配上了,返回true,测试通过
        if x != -1 and y != -1:
            return True
        else:
            return False

2.封装日常操作如点击、双击、下拉、输入等方法,创建MethodOperation.py文件,内容如下:

import os
import time
from pymouse import PyMouse
from pykeyboard import PyKeyboard
from imagetemplate import ImageTemplate

class MethodOperation:

    def __init__(self):
        self.keyboard = PyKeyboard() #键盘事件
        self.mouse = PyMouse() #鼠标事件
        self.imagemath = ImageTemplate()

    #启动程序
    def start_app(self, cmd):
        os.system(cmd)
        time.sleep(2)

    #点击
    def click(self, image):
        #传入需要点击的图片,获取中心点的坐标,然后点击
        x, y = self.imagemath.find_image(image)
        #如果x y 有一个为-1,则表示没有匹配上
        if x == -1 or y == -1:
            print(f"没有找到图片{image}")
            return x, y
        #点击图片
        self.mouse.click(x, y)
        print(f"点击了图片{image},中心点坐标为{x}/{y}")
        time.sleep(0.5)

    def double_click(self, image):
        #传入需要点击的图片,获取中心点的坐标,然后点击
        x, y = self.imagemath.find_image(image)
        #如果x y 有一个为-1,则表示没有匹配上
        if x == -1 or y == -1:
            print(f"没有找到图片{image}")
            return x, y
        #点击图片中心点 n=2 代表点击2次
        self.mouse.click(x, y, n=2)
        time.sleep(1)
        return x,y
    #输入内容
    def input_text(self, image, content):
        x, y = self.double_click(image)
        #type_string输入内容,这里内容必须是字符串
        self.keyboard.type_string(str(content))
        print(f"在坐标为{x}/{y},输入了内容:{content}")
        time.sleep(2)

    #测试方法
    def testmeth(self):
        #启动计算器
        self.start_app("calc.exe")
        #点击
        self.click("5.png")
        self.click("multiplication.png")
        self.click("1.png")
        self.click("0.png")
        self.click("equal.png")

        #断言
        if self.imagemath.assertion("51.png"):
            print("测试通过")
        else:
            print("断言失败,计算结果错误")

        #关闭计算器
        self.click("close.png")

注意:

  上面将模板图片都放在了source包中


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM