├── 0.png ├── 1.jpg ├── README.md └── demo.py /0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohenghui/tiaoyitiao/HEAD/0.png -------------------------------------------------------------------------------- /1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mohenghui/tiaoyitiao/HEAD/1.jpg -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tiaoyitiao 2 | python-opencv adb跳一跳游戏辅助 3 | 可连接模拟器或者手机 4 | 运行时先自行打开跳一跳小程序 5 | 哔哩哔哩视频演示 6 | https://www.bilibili.com/video/BV1dK4y1P7Le 7 | -------------------------------------------------------------------------------- /demo.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import cv2 3 | import numpy as np 4 | from matplotlib import pyplot as plt 5 | import time 6 | import subprocess 7 | import random 8 | import imutils 9 | import os 10 | press_coefficient = 1.68/2*pow(3,0.5) 11 | swipe_x1 = 0; swipe_y1 = 0; swipe_x2 = 0; swipe_y2 = 0 12 | def plt_show0(img): 13 | # print(img.shape) 14 | b, g, r = cv2.split(img) 15 | img = cv2.merge([r, g, b]) 16 | plt.imshow(img) 17 | plt.show() 18 | def self_detect(img): 19 | # shape[1]是宽shape[0]是高 20 | region_upper=int(img.shape[0]*0.3) 21 | region_lower=int(img.shape[0]*0.7) 22 | # 原本是1080 23 | # 1080*0.3到1080*0.7的范围 24 | region=img[region_upper:region_lower,:] 25 | color_lower=np.int32([105,25,45]) 26 | color_upper=np.int32([135,125,130]) 27 | img_hsv=cv2.cvtColor(region,cv2.COLOR_BGR2HSV) 28 | print(img_hsv.shape) 29 | # channels=cv2.split(img_hsv) 30 | # 打印通道情况 31 | # print(len(channels)) 32 | # for i in range(len(channels)): 33 | # print(channels[i]) 34 | # cv2.imshow("hsv",img_hsv) 35 | # inRange相当于threshold()函数将感兴趣的区域变成255(白色), 36 | # 将不感兴趣去的区域设置为0黑色 37 | color_mask=cv2.inRange(img_hsv,color_lower,color_upper) 38 | # 打印二值图 39 | # cv2.imshow("color_mask",color_mask) 40 | contours = cv2.findContours(color_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 41 | contours = contours[1] if imutils.is_cv3() else contours[0] 42 | 43 | # 打印轮廓信息 44 | # print("轮廓信息,坐标%s,轮廓数量%d"%(contours,len(contours))) 45 | # 寻找轮廓 46 | if len(contours)>0: 47 | # 将最大的那组轮廓拿出 48 | # 最小的话就定位到头部 49 | # max_contour=min(contours,key=cv2.contourArea) 50 | max_contour=max(contours,key=cv2.contourArea) 51 | 52 | max_contour=cv2.convexHull(max_contour) 53 | # 轮廓的凸包 54 | # 把点连接起来 55 | # print(max_contour) 56 | # cv2.imshow("max_contour",max_contour) 57 | # 获取矩形的位置信息 58 | rect=cv2.boundingRect(max_contour) 59 | x,y,w,h=rect 60 | center_coord=(x+int(w/2),y+h+region_upper-20) 61 | cv2.circle(img,center_coord,5,(0,255,0),-1) 62 | # return center_coord 63 | return center_coord 64 | # 返回点的位置信息 65 | # return color_mask 66 | else: 67 | return False 68 | def goal_detect(img,body_position): 69 | region_upper=int(img.shape[0]*0.3) 70 | region_lower=int(img.shape[0]*0.6) 71 | # 判断小人在左边还是右边 72 | # 小人在左,方块在右 73 | if body_position[0]<(img.shape[1]/2.0): 74 | region_left=body_position[0]+30 75 | region_right=img.shape[1]-30 76 | else: 77 | region_left=30 78 | region_right=body_position[0]-30 79 | region = img[region_upper:region_lower,region_left:region_right] 80 | # cv2.imshow("test1",region) 81 | 82 | edge_list = [0, 0, 0, 0] 83 | for i in range(3): 84 | region_gray = cv2.cvtColor(region, cv2.COLOR_BGR2HSV)[:, :, i] 85 | # 获取三个通道 86 | 87 | # region_gray=cv2.equalizeHist(region_gray) 88 | # 全都进行轮廓检测,存入数组里 89 | edge_list[i] = cv2.Canny(region_gray, 100, 160) 90 | # cv2.imshow(str(i),edge_list[i]) 91 | # 原格子图转换为灰度图 92 | region_gray = cv2.cvtColor(region, cv2.COLOR_BGR2GRAY) 93 | # region_gray = cv2.equalizeHist(region_gray) 94 | # egion_gray = cv2.GaussianBlur(region_gray, (5, 5), 0) 95 | # cv2.imshow("gray",region_gray) 96 | # 设置算子的大小5*5 97 | edge_list[3] = cv2.Canny(region_gray, 100, 160, apertureSize=5) 98 | # 大于max阈值则为边界,通过梯度进行判断 99 | edge_list[1] = np.bitwise_or(edge_list[0], edge_list[1]) 100 | edge_list[2] = np.bitwise_or(edge_list[2], edge_list[1]) 101 | edge_final = np.bitwise_or(edge_list[3], edge_list[2]) 102 | 103 | # cv2.imshow('edge', edge_final) 104 | 105 | contours = cv2.findContours(edge_final, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) 106 | contours = contours[1] if imutils.is_cv3() else contours[0] 107 | # 寻找轮廓 108 | # max_contour = max(contours, key=cv2.contourArea) 109 | # max_contour = cv2.convexHull(max_contour) 110 | 111 | y = 99999 112 | for contour in contours: 113 | # 将轮廓进行排序 114 | # lambda函数 115 | sorted_top = sorted(contour, key=lambda contour: contour[0][1]) 116 | # print(sorted_top) 117 | if sorted_top[0][0][1] < y: 118 | raw_x = x = sorted_top[0][0][0] 119 | raw_y = y = sorted_top[0][0][1] 120 | 121 | # 确定第一个白点的位置 122 | print((int(x + region_left), int(y + region_upper))) 123 | # 在方块定义一个全零的矩阵 124 | # 如果是对于完整图像都要使用,则掩码层大小为原图行数 + 2,列数 + 2. 125 | # 是一个二维的0矩阵,边缘一圈会在使用算法是置为1。而只有对于掩码层上对应为0的位置才能泛洪,所以掩码层初始化为0矩阵 126 | # seed:为泛洪算法的种子点,也是根据该点的像素判断决定和其相近颜色的像素点,是否被泛洪处理 127 | mask = np.zeros((region_lower - region_upper + 2, region_right - region_left + 2), np.uint8) 128 | mask = cv2.floodFill(region, mask, (raw_x, raw_y + 16), [0, 100, 0])[2] 129 | # 感兴趣部分填1 130 | # print(mask) 131 | cv2.circle(img, (int(x + region_left), int(y + region_upper)), 5, (255, 0, 5), -1) 132 | # cv2.imshow("region",region) 133 | # 画第一个白点 134 | # 135 | M = cv2.moments(mask) 136 | # 计算中心距离 137 | x = int(M["m10"] / M["m00"]) 138 | y = int(M["m01"] / M["m00"]) 139 | print("yuan",[x,y]) 140 | if y < raw_y or abs(x - raw_x) > 40: 141 | x = raw_x 142 | y = raw_y 143 | y += region_upper 144 | x += region_left 145 | y = (-abs(x - body_position[0]) / pow(3, 0.5) + body_position[1]) 146 | print("TESTTEST") 147 | 148 | # cv2.imshow("test",mask) 149 | # cv2.imshow("edge", edge_final) 150 | else: 151 | y += region_upper 152 | x += region_left 153 | 154 | # y = (-abs(x-body_position[0])/pow(3,0.5)+body_position[1]) 155 | cv2.circle(img, (int(x), int(y)), 5, (0, 0, 255), -1) 156 | # cv2.imshow('dealed', img) 157 | plt_show0(img) 158 | return [x, y] 159 | 160 | def set_button_position(im): 161 | global swipe_x1, swipe_y1, swipe_x2, swipe_y2 162 | w, h = im 163 | left = int(w / 2) 164 | top = int(1584 * (h / 1920.0)) 165 | left = int(random.uniform(left-50, left+50)) 166 | top = int(random.uniform(top-10, top+10)) # 随机防 ban 167 | swipe_x1, swipe_y1, swipe_x2, swipe_y2 = left, top, left, top 168 | 169 | 170 | 171 | def getdistance(playerpos,cubepos): 172 | distance = (playerpos[0] - cubepos[0]) ** 2 + (playerpos[1] - cubepos[1]) ** 2 173 | distance = distance ** 0.5 174 | return distance 175 | 176 | def jump(distance): 177 | global press_coefficient 178 | set_button_position([900,1600]) 179 | # press_time = distance * press_coefficient 180 | press_time = distance * 2.26 181 | press_time = max(press_time, 200) # 设置 200ms 是最小的按压时间 182 | press_time = int(press_time) 183 | cmd = 'adb shell input swipe {x1} {y1} {x2} {y2} {duration}'.format( 184 | x1=swipe_x1, 185 | y1=swipe_y1, 186 | x2=swipe_x2, 187 | y2=swipe_y2, 188 | duration=press_time 189 | ) 190 | print(cmd) 191 | os.system(cmd) 192 | 193 | def get_screenshot(id): 194 | os.system('adb shell screencap -p /sdcard/%s.png' % str(id)) 195 | os.system('adb pull /sdcard/%s.png .' % str(id)) 196 | 197 | if __name__=='__main__': 198 | while(1): 199 | get_screenshot(0) 200 | img=cv2.imread('%s.png' % 0) 201 | # img=cv2.imread('1.jpg') 202 | # 调整图片大小 203 | img=cv2.resize(img,(720,1080)) 204 | print(img.shape) 205 | # cv2.imshow('test',img) 206 | PlayPos=self_detect(img) 207 | print("棋子的点",PlayPos) 208 | CubePos=goal_detect(img,PlayPos) 209 | print("方块的点",CubePos) 210 | distance=getdistance(PlayPos,CubePos) 211 | print(distance) 212 | jump(distance) 213 | # print(img.shape[1],img.shape[0]) 214 | # cv2.waitKey(0) 215 | time.sleep(0.1) 216 | # 给与截图判断的时间 --------------------------------------------------------------------------------