Skip to content
🎨 作者:mikigo 📔 阅读量:

一种定位目标图片坐标的图像识别技术交底书

0、缩略语和关键术语定义

缩写全称描述
OpencvOpen Source Computer Vision Library是一个开源的计算机视觉库。
RGB红(R)、绿(G)、蓝(B)RGB即是代表红、绿、蓝三个通道的颜色, 强度值为0~255,比如:白色(0 0 0),黑色(255 255 255)
DogtailDogtail一个使用Accessibility定位Qt应用中元素控件坐标的工具,是一个基于Python的开源三方库。
AccessibilityAccessibility即辅助功能,在应用中提供Accessibility接口,使得外部软件可以操作相应的功能,技术诞生的初衷是为了让身体残疾的人能使用计算机。

1、相关技术背景(背景技术),与本发明最相近似的现有实现方案(现有技术)

元素的定位是自动化测试的核心内容,无论是web自动化测试还是app自动化测试都会存在元素定位不到的问题,此时可以考虑采用图像识别实现,通常采用Opencv提供的模板匹配技术,通过对比目标小图和屏幕大图,即可计算出小图在屏幕中的位置。

1.1、与本发明相关的现有技术一

1.1.1、现有技术一的技术方案

基于Accessibility对Qt应用的元素控件添加ObjectName,使用Dogtail工具提供的方法去定位元素控件。

1.1.2、现有技术一的缺点

(1)定位速度慢,对于元素控件继承的层级太多,在树形结构里面层级就会很深,Dogtail寻找元素的时候会去遍历树形结构里面所有的东西,导致元素定位速度慢。

(2)Dogtail工具本身存在不稳定性,在寻找元素的时候,存在找不到的情况,比如右键菜单里面的选项,使用Dogtail定位时,返回坐标始终为(0, 0)。

(3)如果应用中某些元素无法添加ObjectName时,只能通过索引的方式去找,不利于自动化测试用例的维护性。

1.2、与本发明相关的现有技术二

1.2.1、现有技术二的技术方案

基于Opencv提供的模板匹配功能,对比目标小图和屏幕大图,计算出在屏幕中的位置。

1.2.2、现有技术二的缺点

(1)使用Opencv的模板匹配函数,需要通过Opencv提供的imread函数读取图片,而imread函数只能传入图片的路径,也就是说必须要有目标小图和屏幕大图的本地文件,在自动化测试用例中,目标小图是提前截好的,放到一个固定位置,而屏幕大图是在用例执行的过程中实时截取的,这样就必须要将实时截取的屏幕大图保存为本地文件,这点就会有一些问题。

在AMD平台上由于计算机处理速度相对较快,实时保存图片文件的动作不会有明显的感觉,而在ARM和MIPS平台上计算机处理速度相对较慢,用例执行的过程中,屏幕大图保存的文件相对于要识别的时间点是滞后的,最主要原因就在于要生成本地图片文件。

(2)Opencv在ARM和MIPS上没有对应的官方包,无法使用pip安装Opencv的问题,在搭建自动化测试环境的时候,比较费时间。

2、本发明技术方案的详细阐述

2.1、本发明所要解决的技术问题

(1)在国产化平台UI自动化测试过程中,定位元素控件时不稳定,且速度较慢。

(2)自动化测试操作步骤中,需要准确获取元素控件的坐标。

(3)在UI自动化测试过程中,UI界面变化大,且容易受到环境影响,断言的准确性问题。

2.2、本发明提供的完整技术方案

在自动化测试的过程中,通常将需要识别的按钮或控件区域截取为一个小图,然后在整个屏幕中对小图进行匹配。为了实现识别图像的目的,我们可以通过将图片的每个像素的RGB值,与整个屏幕中的RGB进行对比,如果小图上的RGB值与对应大图位置的RGB都相等,则匹配成功,即可返回小图在大图中的中心坐标点。

图1 图像识别流程图

2.2.1 读取小图和大图的RGB值

(1)小图的RGB值

small_data = small_pic.load() # load()会将图片的RGB值获取到,数据格式为一个二维列表,赋值给一个变量small_data。

(2)大图的RGB值

big_data = big_pic.load()

2.2.2 将小图与大图的RGB值进行匹配

(1)匹配从大图的坐标(0,0)开始匹配,匹配小图里面所有的坐标点(0,0)—(small_pic.width,small_pic.height)

图2 匹配启始位置

(2)如果在大图的(0,0)对应的所有小图的RGB值不相等,则移动到下一个坐标点(1,0),同样匹配小图里面所有的坐标点(0,0)—(small_pic.width,small_pic.height)

图3 逐个像素点移动

(3)按照这样的规律将这一行每移动一个坐标点,都将小图所有的RGB与对应大图的值进行匹配。

图4 移动到一行的最右边

(4)如果在大图的其中一个坐标点上匹配到了小图的所有RGB值,则此时返回小图在大图中的坐标点。

图5 找到在屏幕中的位置

(5)如果匹配了大图所有的坐标点,都没有匹配到,则说明大图中不存在小图,匹配失败。

图6 移动到最右下角都没有找到

2.2.3 关键技术

根据以上的设计思路,代码实现如下:

python
import pyscreenshot
import random
from PIL import Image

def check_match(x, y, small_pic, big_data, small_data):
    '''设置匹配度0.9'''
    same = 0
    diff = 0
    for i in range(small_pic.width):
        for j in range(small_pic.height):
            if big_data[x + i, y + j] == small_data[i, j]:
                same = same + 1
            else:
                diff = diff + 1
    # 设置匹配度0.9
    similarity = same / (same + diff)
    if similarity >= 0.9:
        return True
    else:
        return False


def random_point(small_pic):
    ''' 每次随机取10-20个点,并在小图中随机取坐标
'''
    point_list = []
    count = random.randrange(10, 16)
    for i in range(count):
        sx = random.randrange(0, small.width)
        sy = random.randrange(0, small.height)
        point_list.append([sx, sy])
    return point_list

def random_match(x, y, point_list, big_data, small_data):
    '''在小图中随机取几个点进行匹配,随机点同样设置匹配度0.9'''
    same = 0
    diff = 0
    for point in point_list:
        if big_data[x + point[0], y + point[1]] == small_data[point[0], point[1]]:
            same = same + 1
        else:
            diff = diff + 1

    if same / (same + diff) >= 0.9:
        return True
    else:
        return False

def match_image(pic_name):
    '''通过一张小图,找到对应当前屏幕中的位置'''
    # 打开小图和大图,获取RGB值
    file_path = "/home/uos/Documents/" + pic_name
    small_pic = Image.open(file_path)
    samll_data = small_pic.load()
    big_pic = pyscreenshot.grab()
    big_data = big_pic.load()
    point_list = random_point(small_pic)
    # 遍历大图和小图的横纵坐标
    for x in range(big_pic.width - small_pic.width):
        for y in range(big_pic.height - small_pic.height):
            # 判断随机点
            if random_match(x, y, point_list, big_data, small_data):
                # 判断匹配度
                if check_match(x, y, small_pic, big_data, small_data):
                    # 返回中心坐标
                    return (x + small_pic.width / 2, y + small_pic.height / 2)
    return False

通过match_image()这个函数,传入目标小图的文件名称,即可返回在当前屏幕中的中心坐标。

在UI自动化测试项目中,测试用例如果需要通过图像识别去获取目标控件的坐标,只需调用这个函数即可。

2.2.3.1 小图在大图中匹配的逻辑算法

$$ smallRGB[i, j] = bigRGB[x + i, y + j] $$

其中,x是大图的横坐标的遍历的值,y是大图的纵坐标的遍历的值,i是小图的横坐标的遍历的值,j是小图的纵坐标的遍历的值,RGB的取值是在(0, 0 ,0)~(255, 255, 255)之间。

2.2.3.2 快速匹配

在小图中随机选取一些坐标点,如果选取的这些坐标点存在与大图中RGB值不相等的情况,则直接跳出本次匹配,进行大图的下一个坐标点的匹配,如果选取的坐标点都匹配成功,再进行剩余坐标点的匹配,这样可以实现小图在大图中快速匹配的效果,提升图像识别的速度。

2.2.3.3 匹配度

在实际应用中,我们需要对错误匹配的坐标点有一定的容忍度,这里我称为”匹配度“。比如,匹配度为90%,也就是说,只要小图中90%的坐标点的 RGB,与大图中对应位置能匹配上,那么就判定为匹配成功。

同时,我们对随机选取做”预匹配“的几个点也设置一个匹配度,这样可以进一步提升匹配效率。

在实际项目中,我将匹配度设置为90%时,在近三个月的自动化用例执行过程中,每天执行857条用例,没有出现误报的情况。

2.2.3.4 在UI自动化测试中的应用

(1)获取到元素控件的坐标之后,使用 xdotool 或者 pyautogui 等工具,对元素进行点击、双击、拖拽、输入等动作,实现 UI 自动化测试中的操作步骤。

(2)通过判断屏幕中是否存在元素,用于 UI 自动化测试中的断言。

(3)由元素控件的定位及操作,以及在关键步骤的断言,构成了 UI 自动化测试的完整解决方案。

2.3、本发明技术方案带来的有益效果

(1)解决了 UI 自动化测试中,在国产化平台系统资源不足的情况下,快速实现元素控件定位。

(2)降低了自动化测试环境搭建的复杂度,同时减少了自动化测试环境搭建的时间,从而提升测试效率。

(3)在 UI 自动化测试中,能准确对自动化用例执行结果进行断言。

2.4、针对上述技术方案,是否还有替代方案同样能完成发明目的

暂无

3、本发明的技术关键点和欲保护点是什么

(1)将屏幕大图的RGB值保存到内存中,然后通过算法:$smallRGB[i, j] = bigRGB[x + i, y + j]$ 对比目标图片与屏幕大图 RGB 值,从而获取到目标图片在屏幕中的坐标位置。同时,在对比图像的过程中,通过随机选取一些点进行预匹配,提高图像识别的的速度,解决了在图像对比过程中,消耗大量 CPU 资源的问题。通过设置匹配度,提供图像识别的成功率,提高在 UI 自动化测试中使用图像识别的稳定性,同时提升了自动化测试脚本的健壮性和稳定性,解决了在图像识别的过程中,国产化架构平台生成本地图片文件速度慢的问题,实现了在国产化平台上执行UI自动化测试过程中,快速、稳定的定位目标元素控件的效果。

(2)通过获取到元素控件的坐标,再配合使用 xdotool 或者 pyautogui 等工具,控制鼠标和键盘进行操作,从而实现 UI 自动化测试中模拟人工测试的操作步骤的技术方案运用。

(3)通过获取到元素控件的坐标,进而可以判断目标元素是否存在,可用于UI自动化测试中的关键位置的断言方案运用。

4、附件:

参考文献(如专利/论文/标准等)

l random:

n https://docs.python.org/zh-cn/3/library/random.html

l pyscreenshot:

n https://github.com/ponty/pyscreenshot/tree/2.3

l PIL

n https://pillow.readthedocs.io/en/stable/