Python微信跳一跳自动化脚本
- 前言
- 准备
- 模块及版本
- 思路与流程
- 详细步骤
- 总结
前言
这是我在CSDN上的第一篇文章,以后会陆续记录我的学习生涯,希望我的知识能帮助到更多的朋友~
准备
这篇将详细讲述如何利用Python中相关模块,来完成微信跳一跳的自动化脚本,该技术只作为交流,其中有些知识点都是借鉴了很多大佬的经验。
模块及版本
Python
3.7.2
PIP
20.0.2
opencv
4.2.0.32
numpy
1.18.1
思路与流程
通过adb连接手机
获取游戏截图
图片裁剪
计算玩家位置
计算落脚点位置
计算玩家和落脚点距离
计算模拟点击时间
模拟点击屏幕
详细步骤
1.所需要的的模块
1
2
3
4
5
6
7
8 1import cv2 as cv
2import numpy as np
3import math
4import os
5import threading
6import random
7
8
2.获取手机屏幕截图
1
2
3
4
5
6
7 1# 获取手机屏幕截图,xxx代表adb.exe所在路径
2# 如果使用PyCharm的话没办识别adb命令,配置了环境变量页没用,不知道咋回事
3os.system('xxx/adb shell screencap -p /sdcard/screen.png')
4# 将截图保存到当前项目路径下
5os.system('xxx/adb pull /sdcard/screen.png')
6
7
3.对截图进行切片操作,缩小目标区域
1
2
3
4
5
6
7
8 1# 先读取游戏画面截图
2img = cv.imread("图片文件")
3# 对图片上下部分进行切片操作,缩小目标区域
4up_cut = int(img .shape[0]*0.3)
5down_cut = int(img .shape[0]*0.7)
6img = img [up_cut:down_cut]
7
8
4.根据色彩范围,提取小人的色彩通道信息
1
2
3
4
5
6
7
8 1# 将图片色彩空间转换为hsv
2img_hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
3# 根据目标小人的身体颜色范围,提取目标小人,注意:这里面的颜色范围格式是hsv
4color_min = np.int32([105,30,30])
5color_max = np.int32([200,200,120])
6color_mask = cv.inRange(img_hsv,color_min,color_max)
7
8
5.根据轮廓信息计算小人落脚点位置
1
2
3
4
5
6
7
8
9
10
11
12 1# 勾画目标小人边缘,返回的第一个参数是轮廓信息
2contours = cv.findContours(color_mask,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[0]
3# 绘制目标小人坐标信息
4max_contours = max(contours,key=cv.contourArea)
5max_contours = cv.convexHull(max_contours)
6rect = cv.boundingRect(max_contours)
7x,y,w,h = rect
8point_pos = (x+int(w/2),y+h-15)
9cv.rectangle(img, (x,y), (x+w,y+h), (0, 0, 255), 5)
10cv.circle(img, point_pos, 8, (0, 0, 255), -1)
11
12
6.准备计算落脚点信息,先将图片进行边缘检测,构建轮廓
1
2
3
4
5
6 1# 高斯模糊,为了去除一些噪点
2img_blur = cv.GaussianBlur(img, (5, 5), 0)
3# 边缘检测
4canny_img = cv.Canny(img_blur, 1, 15)
5
6
7.对像素进行修正,去除玩家小人附近的像素点,防止之后的干扰
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 1# 将图片色彩空间转换为hsv
2img_hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
3# 根据目标小人的身体颜色范围,提取目标小人,注意:这里面的颜色范围格式是hsv
4color_min = np.int32([105,30,30])
5color_max = np.int32([200,200,120])
6color_mask = cv.inRange(img_hsv,color_min,color_max)
7# 勾画目标小人边缘,返回的第一个参数是轮廓信息
8contours = cv.findContours(color_mask,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)[0]
9max_contours = max(contours,key=cv.contourArea)
10max_contours = cv.convexHull(max_contours)
11rect = cv.boundingRect(max_contours)
12# 移除小人头部附近像素
13r_x,r_y,r_w,r_h = rect
14for y in range(r_y-150, r_y+r_h):
15 for x in range(r_x-20, r_x+r_w+20):
16 canny_img[y][x] = 0
17
18
8.计算目标中心点,这里比较复杂,可以看看图片上我写的思路
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 1 # 计算目标中心点
2crop_h, crop_w = canny_img.shape
3center_x, center_y = 0, 0
4max_x = 0
5for y in range(crop_h):
6 for x in range(crop_w):
7 if canny_img[y, x] == 255:
8 if center_x == 0:
9 center_x = x
10 if x > max_x:
11 # 如果发现两次y轴的像素点间隔超过了一定值,就认为已经找到中心点了
12 if(center_y!=0 and y-center_y>50):
13 point_pos = (center_x, center_y)
14 if(show_data):
15 cv.circle(img, point_pos, 5,(0,0,255), -1)
16 cv.circle(canny_img, point_pos, 5,255, -1)
17 showImg("canny_img",canny_img)
18 return point_pos
19 else:
20 cv.circle(img, (center_x, center_y), 1,(255,0,0), -1)
21 center_y = y
22 max_x = x
23point_pos = (center_x, center_y)
24
25
9.计算两点之间的距离
1
2
3
4
5
6 1# 创建np数组,这里其实不需要abs,正数和负数无关紧要
2distance = np.array("第一个点的信息")-np.array("第二个点的信息")
3# 用hypot函数进行计算距离
4distance = int(math.hypot(distance[0],distance[1]))
5
6
10.根据距离计算点击时间长度
1
2
3
4 1# 这个1.35别问我咋来的,一点点试出来的 o(゚Д゚)っ!
2click_time = int(distance * 1.35)
3
4
11.模拟点击屏幕
1
2
3
4
5 1# 原本想用input的,后来发现input去模拟长按特别麻烦,就在网上找到了swipe
2# swipe本来是滑动的意思,不过这个里面可以设置时间~~~
3os.system('xxx/adb shell input swipe 367 469 367 469 '+str(time))
4
5
12.收尾
- 主要是我不喜欢11这个数字,所以写了个12,其他的技术点也没什么特别的了,无非就是创建一个死循环,开个线程之类的。
- 不过要提别注意的是,如果写循环的话,不能用time.sleep()这个函数,opencv自带的cv2.waitKey()函数中的参数可以代表每个周期的刷新时间~
总结
作者很懒,懒得写总结了。。。源码在最上面。。。