专栏名称: 朝阳35处
互联网金融大数据挖掘哪家强,平安前海征信帮你忙。分享数据挖掘和人工智能前沿技术,探讨其在风险控制、反欺诈等金融业务中的实际应用。每周涨点知识,多点谈资,定期举办行业沙龙。
目录
相关文章推荐
经济参考报  ·  3000亿元!央行最新操作! ·  17 小时前  
21世纪经济报道  ·  重磅!DeepSeek:今天启动 ·  昨天  
神嘛事儿  ·  我回答了 @大瑙璊子 ... ·  昨天  
财经杂志  ·  DeepSeek究竟创新了什么? ·  2 天前  
51好读  ›  专栏  ›  朝阳35处

利用人工智能实现小程序自动答题

朝阳35处  · 公众号  ·  · 2018-08-14 17:00

正文

作者:Yiutto,编程浪子

GitHub: github.com/Yiutto

之前有看到有人用python实现自动运行 微信小程序《跳一跳》 ,后来看到别人用hash码实现《加减大师》的自动答题领取娃娃,最近一直在研究深度学习,为啥不用机器学习实现呢?不就是一个分类问题吗!

如何实现自动答题微信小游戏《加减大师》?

思考:

  • 图像识别吗?

  • 如何建立特征工程?

  • 选用什么算法?

一、图像特征工程

如何获取手机游戏上的图片?

  • 使用adb命令截取手机屏幕;

  • 在PC端和手机端同时运行APowerMirror软件,将手机投屏到电脑上,然后使用Pillow包中的截图方法截取电脑上对应手机屏幕的 区域。

  • 在PC端和手机端同时运行APowerMirror软件,将手机投屏到电脑上,然后使用Python调用windows的原生API截取电脑上对应手机屏幕的区域。

实验结果: 三种截屏方式花费的时间差异很大,第一种每次截屏需要0.7s左右,第二种0.3s左右,第三种0.04s左右。

当然选择第3种咯,下载地址 [https://www.apowersoft.cn/phone-mirror] ,一个好的软件是成功的关键(够清晰)。

获取训练样本

相关步骤:

1. util.py 中的 shotByWinAPI 函数:首先利用window自带api获取全屏图片,然后自定义 config.py 的相关参数。

  1. # 从PC端截屏时,截取区域左上角相对桌面的x坐标

  2. 'projection_x': 32,

  3. # 从PC端截屏时,截取区域左上角相对桌面的y坐标

  4. 'projection_y': 278,

  5. # 从PC端截屏时,截取区域的宽度

  6. 'projection_width': 482,

  7. # 从PC端截屏时,截取区域的高度

  8. 'projection_height': 854,

可以用window命令键 PrtScSysRq (F12的右边),然后复制到画图中(1920x1080)。


用画图的放大镜放大,图中红色框的小方块位置(32x278) projection_x 即32, projection_y 即278。


在画图中计算出截图的宽度和高度,即 projection_width projection_height (482x854)

2. img_tool.py 函数介绍:主要是通过 all(img,filename) 函数进行图片分割

  1. srcImg = cv2.imread(os.path.join("ScreenShotForTrain", f), 0)

上述代码是为了将彩色图片灰度模式加载

  1. def all(img, filename):

  2.    """封装对图片的所有操作"""

  3.    img = cropImg(img)

  4.    img = binaryImg(img)

  5.    img1, img2 = cropAgain(img)

  6.    imgs = cutImg(img1, filename + '_1') + cutImg(img2, filename + '_2')

  7.    return imgs

  8. def cropImg(img):

  9.    """裁剪原始截图"""

  10.    height = img.shape[0]

  11.    img2 = img[ int(config.config['exp_area_top_rate'] * height):int(config.config['exp_area_bottom_rate'] * height),:]

  12.    #print('裁剪完毕')

  13.    return  img2

cropImg(img) 函数主要是为了裁剪含有数字的区域,通过设置参数

  1. #表达式区域的顶部处于整张图片的位置(307/854=0.359)

  2. 'exp_area_top_rate': 0.36,

  3. #表达式区域的底部处于整张图片的位置(478/854=0.559)

  4. 'exp_area_bottom_rate': 0.56,

如果觉得设置比例太麻烦,可以直接写死位置( img2=img[int(307):int(478),:] )。得到如下图:

  1. def binaryImg(img):

  2.    """二值化图片"""

  3.    ret, thresh1 = cv2.threshold(img, config.config['binary_threshold'], 255, cv2.THRESH_BINARY)

  4.    # ret, thresh1 = cv2.threshold(img, config.config['binary_threshold'], 255, cv2.THRESH_BINARY_INV)

  5.    #print('二值化完毕')

  6.    return thresh1

binaryImg(img) 函数主要是为了将图片二值化,可以参考 Python+OpenCV教程6:阈值分割 。得到的图片如下图:


  1. def cropAgain(img):

  2.    """再次裁剪"""

  3.    height = img.shape[ 0]

  4.    img1 = img[0:int(0.5 * height), :]

  5.    img2 = img[int(0.5 * height):height, :]

  6.    #print('再次裁剪完毕')

  7.    return img1, img2

cropAgain(img) 函数主要是为了将图片分成上下两部分


  1. def cutImg(img, filename):

  2.    """水平分割图片"""

  3.    sb = np.array(img)

  4.    print(sb.shape)

  5.    sum_list = np.array(img).sum(axis=0)

  6.    start_index = -1

  7.    res = []

  8.    names = []

  9.    index = 0

  10.    for sum in sum_list:

  11.        if sum > 255 * 4:

  12.            if start_index == -1:

  13.                start_index = index

  14.        else:

  15.            if start_index != -1:

  16.                if config.config['type'] == 0:

  17.                    sigleCharWidth = config.config['abd_single_char_width']

  18.                else:

  19.                    sigleCharWidth = config.config['pc_single_char_width']

  20.                #为了防止字符粘连,需要在此处宽度进行判断

  21.                if index - start_index > sigleCharWidth * 2:

  22.                    res.append((start_index,start_index + (index - start_index) // 2))

  23.                    res.append((start_index + (index - start_index) // 2, index))

  24.                else:

  25.                    res.append((start_index, index))

  26.                start_index = -1

  27.        index += 1

  28.    imgs = []

  29.    count = 0

  30.    for single_char in res:

  31.        start = single_char[0]

  32.        end = single_char[1 ]

  33.        sub_img = img[:, start:end]

  34.        sub_img = cv2.resize(sub_img, (120, 240), interpolation=cv2.INTER_CUBIC)

  35.        #cv2.imwrite('SingleChar/%s_%d.png' % (filename, count), sub_img)

  36.        #names.append('%s_%d.png' % (filename, count))

  37.        # cv2.imshow(str(count), sub_img)

  38.        imgs.append(sub_img)

  39.        count += 1

  40.    # cv2.waitKey()

  41.    #print('分割,重新设置大小 %s 完毕' %filename)

  42.    return  imgs

设置 pc_single_char_width 参数值,得到如下图:


  1. c = 0

  2. def v_cut(img):

  3.    global c

  4.    """竖直方向切割图片"""

  5.    sb1 = np.array(img)

  6.    print(sb1.shape)

  7.    sum_list = np.array(img).sum(axis=1)

  8.    start_index = -1

  9.    end = -1

  10.    index = 0

  11.    for sum in sum_list:

  12.        if sum > 255 * 2:

  13.            start_index = index

  14.            break

  15.        index += 1

  16.    for i in range(1, len(sum_list) + 1):

  17.        if sum_list[-i] > 255 * 2:

  18.            end = len(sum_list) + 1 - i

  19.            break

  20.    img = img[start_index:end, :]

  21.    img = cv2.resize(img, (30, 60), interpolation=cv2.INTER_CUBIC)

  22.    #cv2.imwrite('SingleChar/%d.png' %c, img)

  23.    c += 1

  24.    return img

重新固定图片的大小(30x60),得到如下图:







请到「今天看啥」查看全文