图像识别 OpenCV 解决安全键盘输入密码问题

问题描述

支付场景中常常遇到安全键盘的问题,app自动化无法抓取,而且键盘随机变化,每次都不一样。
自动化测试场景中必须要点击安全键盘比如:

解决思路

网上查找了一下比较稳妥的有两种方法:

  1. 图像识别,然后点击坐标
  2. 开发配合,给特定的app包,解除安全键盘

我选择了自己解决,毕竟找开发还有愿不愿配合的问题。。。
图像识别找到了OpenCV 里面有matchTemplate 方法,可以在图片中找指定的图片
简直完美了,那就开干吧

  1. 每个需要操作的位置进行截图并保存起来,切记按原图大小截取,尽可能小,比如:
  2. 然后就是在截取的屏幕上面查找这些数字对应的位置
  3. 按照位置在屏幕上点击

实现代码

以需要输入密码为例,我写了如下代码,需要传入截屏图片路径,还有需要输入的密码。
前面我们已经将各个数字的图片保存在本地,并以n0.jpg, n1.jpg … 保存,并和脚本放在一起。

我使用的python写的脚本,当然你还需要安装OpenCV, 下载路径:http://opencv.org/releases.html
下载后把build 下面的 python 里面的cv2.pyd 文件复制到 python目录下的Lib\site-packages 里面

import cv2
import os
import numpy as np
import time

def get_pay_keyboard_number_location(im, pwd):
    numbers = set(list(pwd))
    templates = {}
    positions = {}
    nimgpath = ""   #数字图片不在同目录时使用
    for i in numbers:
        templates[i]  = os.path.join(nimgpath, "n{}.jpg".format(i))

    start = time.time()
    img_rgb = cv2.imread(im)
    for teNum, tepath in templates.items():
        # print(tepath)
        template = cv2.imread(tepath)
        h, w = template.shape[:-1]

        res = cv2.matchTemplate(img_rgb, template, cv2.TM_CCOEFF_NORMED)
        threshold = .95    # 匹配度参数,1为完全匹配
        loc = np.where(res >= threshold)
        if len(loc) > 0:
            positions[teNum] = zip(*loc[::-1])[0]
        else:
            print("Can not found number: [{}] in image: [{}].".format(tepath, im))

    end = time.time()
    print(end-start)

    return [positions[n] for n in pwd]

if __name__ == "__main__":
    ls = get_pay_keyboard_number_location('D:\test\img\sekeyboard.png', '123456')
    print(ls)

上面代码实现了获取每个数字的坐标,并以列表返回。
拿到坐标后面就可以直接操作了

执行效果:

代码不一定严谨,欢迎指正。