基于录制回放的白板效果自动化对比技术

背景

白板是教育产品里的常见功能,类似于电子化的黑板,基础的业务逻辑是教师端(windows)老师在白板上写字或者画图,学生端(android)可以同步接收到该内容。

现在有两套基于不同技术的白板功能方案,需要对比他们的效果差异,由于底层代码无法放开,无法通过修改代码埋点的形式进行,因此需要通过ui层面进行对比。

基础测试流程

  1. 在pc教师端运行一次画图脚本,在Android学生端确认正确后,选取该图案作为基准图片
  2. 在pc教师端进行ui操作,在白板上再次画出该图案
  3. 在android学生端上,截取白板画面
  4. 对比截取的白板画面和基准图片,计算相似度,大于阈值(95%)则视为该次准确,否则认为该次失败,计入失败次数,并记录该失败图案供分析
  5. 清空pc教师端白板图案,再次重复2~4操作

自动化技术

airtest(pywinauto)& pynput完成对pc端ui操作

在pc端ui自动化中,首先选用的是比较经典的ui操作库pywinauto,airtest对其进行了封装,为减少二次开发量,这里直接选用了airtest。

基础的ui操作如元素定位、点击、滑动等,airtest都有较为成熟的api,但模拟老师在白板上画图,只靠自己定义滑动坐标使用鼠标事件执行的话,太过生硬不符合实际情形,因此,最后决定采用实际录制操作坐标再回放的形式进行,这样基本可以模拟真实的笔迹。

airtest不具备录制鼠标轨迹功能,在调研后,选用pynput进行鼠标事件的录制。

pynput也是一个提供windows操作api的库,但其提供了对鼠标和键盘事件的监听功能;通过添加监听线程pynput.mouse.Listener,每发生一个鼠标事件,就使用预先定义的格式进行本地化存储,这样就完成了鼠标操作的事件收集;再通过解析存储的事件文本,就可以完成鼠标事件的回放。

需要说明的是,pynput本身也有操作windows鼠标事件的api,但实测下来,虽然通过pynput进行回放整体轨迹是对的,但在白板上的笔画平滑度和粗细每次都不太一致,因此不适合选用其作为回放手段,最终测试,还是通过airtest的mouse_move、mouse_up、mouse_down组合进行回放,效率较pynput低,但胜在一致性高,基本每次回放的轨迹都一致。

opencv2进行图像识别判断

在进行教师端的操作后,需要在学生端截图并进行对比,这里对比技术采用了opencv2的api,代码如下:

def img_similarity(img1_path,img2_path):
    """
    :param img1_path: 图片1路径
    :param img2_path: 图片2路径
    :return: 图片相似度
    """
    try:
        # 读取图片
        img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
        img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)

        # 初始化ORB检测器
        orb = cv2.ORB_create()
        kp1, des1 = orb.detectAndCompute(img1, None)
        kp2, des2 = orb.detectAndCompute(img2, None)

        # 提取并计算特征点
        bf = cv2.BFMatcher(cv2.NORM_HAMMING)

        # knn筛选结果
        matches = bf.knnMatch(des1, trainDescriptors=des2, k=2)

        # 查看最大匹配点数目
        good = [m for (m, n) in matches if m.distance < 0.75 * n.distance]
        #print(len(good))
        #print(len(matches))
        similary = len(good) / len(matches)
        #print("两张图片相似度为:%s" % similary)
        return similary

    except:
        print('无法计算两张图片相似度')
        return 0

由于其中一个方案学生端界面上会有动态的时间显示,影响对比结果,因此,需要对该截图进行裁剪,只保留白板的内容部分,裁剪代码如下:

        screen_path =  "D:\PycharmProjects\omoboard\{filename}".format(filename=screen)
        img = cv2.imread(screen_path)
        cropped = img[100:1050, 0:1500]
        cv2.imwrite(screen_path, cropped)

你可能感兴趣的:(基于录制回放的白板效果自动化对比技术)