微信跳一跳python辅助软件思路及图像识别源码解析


Posted in Python onJanuary 04, 2018

本文将梳理github上最火的wechat_jump_game的实现思路,并解析其图像处理部分源码

首先废话少说先看效果

微信跳一跳python辅助软件思路及图像识别源码解析

核心思想

获取棋子到下一个方块的中心点的距离
计算触摸屏幕的时间
点击屏幕

重要方法

计算棋子到下一个方块中心点的距离

  • 使用 adb shell screencap -p 命令获取手机当前屏幕画面
  • 再通过图像上的信息找出棋子的坐标和下一个方块中心点的坐标
  • 然后通过两点间距离公式计算出距离

计算触摸屏幕的时间

T=A * S

其中S为上步算出的像素距离,T为按压时间(ms),A为一个系数这个系数会随着屏幕分辨率的变化而变化,在1920*1080的屏幕下这个系数为1.35,在2560*1440的屏幕下这个系数为1.475

点击屏幕

adb shell input swipe x y x y time(ms)

这条命令能够点击手机屏幕x,y位置time(ms)

图像处理部分源码解析

图像处理部分代码都在 find_piece_and_board(im) 方法中

通过输入的图像im计算出棋子的坐标点以及下一个方块中心的坐标点

在find_piece_and_board的方法中一进来就是下面的两个嵌套在一起的for循环:

for i in range(int(h / 3), int(h * 2 / 3), 50):
    last_pixel = im_pixel[0, i]
    for j in range(1, w):
      pixel = im_pixel[j, i]
      # 不是纯色的线,则记录 scan_start_y 的值,准备跳出循环
      if pixel[0] != last_pixel[0] or pixel[1] != last_pixel[1] or pixel[2] != last_pixel[2]:
        scan_start_y = i - 50
        break
    if scan_start_y:
      break

这段代码的作用就是从屏幕2/3的位置向下寻找不是纯色的线。并将找到位置的纵坐标-50作为,寻找棋子和方块的起始坐标。这样可以简化以后搜索的工作量,因为在这个横坐标以上是没有东西的。

接下来是查找棋子坐标的代码

# 查找棋子坐标
  # piece_x_sum 横坐标总量 piece_x_c 点的个数 piece_y_max 纵坐标最大值
  # 从 scan_start_y 开始往下扫描,棋子应位于屏幕上半部分,这里暂定不超过 2/3
  for i in range(scan_start_y, int(h * 2 / 3)):
    for j in range(scan_x_border, w - scan_x_border): # 横坐标方面也减少了一部分扫描开销
      pixel = im_pixel[j, i]
      # 根据棋子的最低行的颜色判断,找最后一行那些点的平均值,这个颜色这样应该 OK,暂时不提出来
      if (50 < pixel[0] < 60) and (53 < pixel[1] < 63) and (95 < pixel[2] < 110):
        piece_x_sum += j
        piece_x_c += 1
        piece_y_max = max(i, piece_y_max)

  if not all((piece_x_sum, piece_x_c)):
    return 0, 0, 0, 0
  # 平均横坐标
  piece_x = int(piece_x_sum / piece_x_c)
  # 纵坐标最大值-底座一半的高度
  piece_y = piece_y_max - piece_base_height_1_2 # 上移棋子底盘高度的一半

查找棋子的重要依据就是棋子的颜色较为单一并且和方块的颜色有较大差距。如果一个像素点的RGB像素值在B(50, 60), G(53, 63), R(95, 110)范围内那么就认为这个像素点是属于棋子的。根据以上信息就能计算出棋子的平均横坐标,以及最大的纵坐标值。

所以不难计算出棋子坐标(棋子平均横坐标, 棋子最大纵坐标 - 底座一半的高度)其中底座一半的高度因手机分辨率而异。需要提前配置好。

最后是查找下一个方块中心点的坐标的代码

# 寻找最高的棋盘
  # 棋盘不会和棋子在同一侧
  # 限制棋盘扫描的横坐标,避免音符 bug
  if piece_x < w / 2:
    board_x_start = piece_x
    board_x_end = w
  else:
    board_x_start = 0
    board_x_end = piece_x
  for i in range(int(h / 3), int(h * 2 / 3)):
    last_pixel = im_pixel[0, i]
    if board_x or board_y:
      break
    board_x_sum = 0
    board_x_c = 0
    for j in range(int(board_x_start), int(board_x_end)):
      pixel = im_pixel[j, i]
      # 下一个棋盘紧贴着棋子
      # 修掉脑袋比下一个小格子还高的情况的 bug
      if abs(j - piece_x) < piece_body_width:
        continue
      # 修掉圆顶的时候一条线导致的小 bug,这个颜色判断应该 OK,暂时不提出来
      if abs(pixel[0] - last_pixel[0]) + abs(pixel[1] - last_pixel[1]) + abs(pixel[2] - last_pixel[2]) > 10:
        board_x_sum += j
        board_x_c += 1
    if board_x_sum:
      # 最高棋盘的平均横坐标
      board_x = board_x_sum / board_x_c
  last_pixel = im_pixel[board_x, i]

代码开头通过棋子所在的屏幕位置限制搜索的宽度,如果棋子在屏幕左边那么就在屏幕右边搜索方块,反之亦然。因为方块和棋子不会在屏幕同一侧。

然后就是自上而下得搜索方块的上顶点。

方块上顶点坐标( 平均横坐标,当前行的纵坐标)

然后再往下纵坐标+247的位置开始向上找颜色与上顶点一样的点,为下顶点。
当然此方法有一点局限性对于纯色的平面效果很好但是对于非纯色的平面。可能会判断出错。

如果上一跳命中中间,则下个目标中心会出现 r245 g245 b245 的点,利用这个属性弥补上一段代码可能存在的判断错误
若上一跳由于某种原因没有跳到正中间,而下一跳恰好有无法正确识别花纹,则有可能游戏失败,由于花纹面积通常比较大,失败概率较低

可改进方案

首先是目前方案对于多分辨率需要多个配置文件来记录不同分辨率下的系数以及棋子底盘一半的高度。随机测试了6台手机其中有两台手机因没有配饰而无法正常运作

首先是系数A,观察方程T=A * S,A就是一个可训练量,利用机器学习框架比如TensorFlow,对这个一元一次方程进行拟合。

观察棋子底盘一半的高度在代码中的作用。不难发现是为了求出棋子底盘中心的纵坐标。而棋子底盘中心的位置恰恰是棋子最宽的地方。所以可以通过找出棋子最宽处的纵坐标的方式找到棋子底盘中心的纵坐标。这样就摆脱了对配置文件的依赖,能让代码在任何手机上正常运行。

其次是对于方块中心坐标位置的判断方法出错率较高,虽然有中心白点可以弥补但是在大量跳跃的过程中还是会出现错误。3太手机不停运行了一下午,最高分只有2009分。

现方法出错率高的原因是使用纯颜色方法判断,但是在实际游戏中颜色丰富的方块也不少。如果想改变就不能依赖颜色方法判断,而应该通过几何图像的形状来计算方块的位置。不难发现游戏中方块只有棱形和圆形两种形状。

首先通过canny或其他轮廓查找算子提取出图像的轮廓,然后通过霍夫变换提取出圆形和棱形的中心坐标。

总结

以上所述是小编给大家介绍的微信跳一跳python辅助软件思路及图像识别源码解析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Python 相关文章推荐
Python学习资料
Feb 08 Python
python使用win32com在百度空间插入html元素示例
Feb 20 Python
Python运行报错UnicodeDecodeError的解决方法
Jun 07 Python
Python爬取京东的商品分类与链接
Aug 26 Python
VSCode下好用的Python插件及配置
Apr 06 Python
PyQt5响应回车事件的方法
Jun 25 Python
Windows下Pycharm远程连接虚拟机中Centos下的Python环境(图文教程详解)
Mar 19 Python
python里的单引号和双引号的有什么作用
Jun 17 Python
python判断一个变量是否已经设置的方法
Aug 13 Python
Django中ORM的基本使用教程
Dec 22 Python
Python编写万花尺图案实例
Jan 03 Python
如何判断pytorch是否支持GPU加速
Jun 01 Python
Python操作MongoDB数据库的方法示例
Jan 04 #Python
Python字典操作详细介绍及字典内建方法分享
Jan 04 #Python
Python tkinter实现的图片移动碰撞动画效果【附源码下载】
Jan 04 #Python
Python给你的头像加上圣诞帽
Jan 04 #Python
Python编程实现线性回归和批量梯度下降法代码实例
Jan 04 #Python
Python语言描述随机梯度下降法
Jan 04 #Python
微信小程序跳一跳游戏 python脚本跳一跳刷高分技巧
Jan 04 #Python
You might like
反射调用private方法实践(php、java)
2015/12/21 PHP
Yii2前后台分离及migrate使用(七)
2016/05/04 PHP
php实现的中秋博饼游戏之掷骰子并输出结果功能详解
2017/11/06 PHP
php和C#的yield迭代器实现方法对比分析
2019/07/17 PHP
JS 对输入框进行限制(常用的都有)
2013/07/30 Javascript
解析offsetHeight,clientHeight,scrollHeight之间的区别
2013/11/20 Javascript
浅谈JSON和JSONP区别及jQuery的ajax jsonp的使用
2014/11/23 Javascript
Nodejs学习笔记之Stream模块
2015/01/13 NodeJs
jQuery老黄历完整实现方法
2015/01/16 Javascript
Jquery实现动态切换图片的方法
2015/05/18 Javascript
javascript常用经典算法实例详解
2015/11/25 Javascript
简单讲解jQuery中的子元素过滤选择器
2016/04/18 Javascript
ECMAScript6轮播图实践知识总结
2016/08/17 Javascript
移动端点击图片放大特效PhotoSwipe.js插件实现
2016/08/25 Javascript
轻松掌握JavaScript享元模式
2016/08/27 Javascript
jQuery实现弹窗居中效果类似alert()
2017/02/27 Javascript
利用jquery去掉时光轴头尾部线条的方法实例
2017/06/16 jQuery
小程序自定义单页面、全局导航栏的实现代码
2019/03/15 Javascript
微信小程序页面传多个参数跳转页面的实现方法
2019/05/17 Javascript
mpvue实现左侧导航与右侧内容的联动
2019/10/21 Javascript
解决vue cli4升级sass-loader(v8)后报错问题
2020/07/30 Javascript
python正则表达式match和search用法实例
2015/03/26 Python
python 找出list中最大或者最小几个数的索引方法
2018/10/30 Python
详解python使用turtle库来画一朵花
2019/03/21 Python
python django生成迁移文件的实例
2019/08/31 Python
Tensorflow 定义变量,函数,数值计算等名字的更新方式
2020/02/10 Python
Python爬取新型冠状病毒“谣言”新闻进行数据分析
2020/02/16 Python
Python实现Canny及Hough算法代码实例解析
2020/08/06 Python
matplotlib 三维图表绘制方法简介
2020/09/20 Python
英国领先的奢侈品零售商之一:CRUISE
2016/12/02 全球购物
介绍一下Python下range()函数的用法
2013/11/07 面试题
医生进修自我鉴定
2014/01/19 职场文书
雷锋式好少年事迹材料
2014/08/17 职场文书
工作态度检讨书范文
2015/05/06 职场文书
捐书仪式主持词
2015/07/04 职场文书
新娘父亲婚礼致辞
2015/07/27 职场文书