wxjump.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import os
  2. import cv2
  3. import numpy as np
  4. import time
  5. import random
  6. class Wxjump(object):
  7. '''微信跳一跳助手 '''
  8. def __init__(self):
  9. pass
  10. def get_screenshot(id):
  11. os.system('adb shell screencap -p /sdcard/%s.png' % str(id))
  12. os.system('adb pull /sdcard/%s.png ./data/result/' % str(id))
  13. def jump(distance):
  14. # 这个参数还需要针对屏幕分辨率进行优化
  15. press_time = int(distance * 1.35)
  16. # 生成随机手机屏幕模拟触摸点
  17. # 模拟触摸点如果每次都是同一位置,成绩上传可能无法通过验证
  18. rand = random.randint(0, 9) * 10
  19. cmd = ('adb shell input swipe %i %i %i %i ' + str(press_time)) \
  20. % (320 + rand, 410 + rand, 320 + rand, 410 + rand)
  21. os.system(cmd)
  22. print(cmd)
  23. def get_center(img_canny, ):
  24. # 利用边缘检测的结果寻找物块的上沿和下沿
  25. # 进而计算物块的中心点
  26. y_top = np.nonzero([max(row) for row in img_canny[400:]])[0][0] + 400
  27. x_top = int(np.mean(np.nonzero(canny_img[y_top])))
  28. y_bottom = y_top + 50
  29. for row in range(y_bottom, H):
  30. if canny_img[row, x_top] != 0:
  31. y_bottom = row
  32. break
  33. x_center, y_center = x_top, (y_top + y_bottom) // 2
  34. return img_canny, x_center, y_center
  35. # 第一次跳跃的距离是固定的
  36. # jump(530)
  37. time.sleep(1)
  38. # 匹配小跳棋的模板
  39. temp1 = cv2.imread('data/template/temp_player.jpg', 0)
  40. w1, h1 = temp1.shape[::-1] #77*209
  41. # 匹配游戏结束画面的模板
  42. temp_end = cv2.imread('data/template/temp_end.jpg', 0)
  43. # 匹配中心小圆点的模板
  44. temp_white_circle = cv2.imread('data/template/temp_white_circle.jpg', 0)
  45. w2, h2 = temp_white_circle.shape[::-1]
  46. # 循环直到游戏失败结束
  47. for i in range(100):
  48. get_screenshot(i)
  49. img_rgb = cv2.imread('data/result/%s.png' % i, 0)
  50. # 如果在游戏截图中匹配到带"再玩一局"字样的模板,则循环中止
  51. res_end = cv2.matchTemplate(img_rgb, temp_end, cv2.TM_CCOEFF_NORMED)
  52. if cv2.minMaxLoc(res_end)[1] > 0.95:
  53. print('Game over!')
  54. break
  55. # 模板匹配截图中小跳棋的位置
  56. res1 = cv2.matchTemplate(img_rgb, temp1, cv2.TM_CCOEFF_NORMED)
  57. min_val1, max_val1, min_loc1, max_loc1 = cv2.minMaxLoc(res1)
  58. center1_loc = (max_loc1[0] + 39, max_loc1[1] + 189)
  59. # 先尝试匹配截图中的中心原点,
  60. # 如果匹配值没有达到0.95,则使用边缘检测匹配物块上沿
  61. res2 = cv2.matchTemplate(img_rgb, temp_white_circle, cv2.TM_CCOEFF_NORMED)
  62. min_val2, max_val2, min_loc2, max_loc2 = cv2.minMaxLoc(res2)
  63. if max_val2 > 0.95:
  64. print('found white circle!')
  65. x_center, y_center = max_loc2[0] + w2 // 2, max_loc2[1] + h2 // 2
  66. else:
  67. # 边缘检测
  68. img_rgb = cv2.GaussianBlur(img_rgb, (5, 5), 0)
  69. canny_img = cv2.Canny(img_rgb, 1, 10)
  70. H, W = canny_img.shape
  71. # 消去小跳棋轮廓对边缘检测结果的干扰
  72. for k in range(max_loc1[1] - 10, max_loc1[1] + 189):
  73. for b in range(max_loc1[0] - 10, max_loc1[0] + 100):
  74. canny_img[k][b] = 0
  75. cv2.imwrite('data/result/canny_img%s.png' % i, canny_img)
  76. img_rgb, x_center, y_center = get_center(canny_img)
  77. # 将图片输出以供调试
  78. img_rgb = cv2.circle(img_rgb, (x_center, y_center), 10, 255, -1)
  79. # cv2.rectangle(canny_img, max_loc1, center1_loc, 255, 2)
  80. cv2.imwrite('data/result/last.png', img_rgb)
  81. distance = (center1_loc[0] - x_center) ** 2 + (center1_loc[1] - y_center) ** 2
  82. distance = distance ** 0.5
  83. jump(distance)
  84. time.sleep(random.randrange(11,20)/10.0)