Van♂Python |
您所在的位置:网站首页 › 为什么origin坐标没有数字 › Van♂Python |
0x1、引言
春节前最后一周,留守的同事都在摸鱼,杰哥也是如此,百无聊赖中点开了一个小游戏。本想着打发时间,结果被其中一个 "孤岛求生" 的玩法给拿捏了😭: 这不妥妥滴 2D版的微信跳一跳?玩法也很简单: 长按建造生成木板 (按得越久木板越长); 松开按钮,木板放下,搭到另一个石头上,人借着木板挪到下一块石头; 木板过短或者过长,人就会掉到水里,游戏结束!(当然,氪金是可以复活滴~)手残杰哥就没跳过20+,每次都是差一点点,死了几次,气到想砸手机,焯! 这哪能忍啊?有道是 科技才是第一生产力,得想办法整个 辅助!搜了一圈没有找到现成能用的,估摸着是冷门氪金小游戏,玩的人不多。又看了下微信跳一跳的脚本,场景不同,改的话基本是重新写了。索性,就自己手搓一个吧! 思路分析 把上面的玩法简单抽象下,其实就是 小学三四年级的常见数学问题 → 《速度、时间与路程间的关系》,怎么说? 速度 → 木板变长的速度,单位:像素/毫秒 时间 → 手指按压按钮的时间,单位:毫秒 路程/距离 → 生成木板的长度,单位:像素而这里很明显就是 求时间,想办法采集到 路程和速度,一相除,答案就出来了~ 行吧,有思路了,直接开整!! 0x2、采集路程合适的木头长度就是 两块石头间的距离,而人物会一直处于石头的中心,所以更准确的描述是:两个石头中心点的距离,即图中黄线: 接着是石头中心点的确定,它也是 数字编号的中心点,所以这里的思路是 识别出编号的区域,然后求出中心点。 数字文字?我尝试用 《破大防!这个开源库,竟能让APP日常任务自动化变得如此简单》 提到的OCR库-chineseocr_lite 进行识别: em...并没有识别出数字1,那就只能自己来处理图片了,把图片中数字部分放大: 数字区域是白色的 可以尝试 灰度二值化 处理下,只关注数字区域,先裁剪下图片,提高处理速度: def crop_area(pic_path, save_dir, start_x, start_y, end_x, end_y): """ 裁剪图片 :param save_dir: 保存路径 :param pic_path: 图片路径 :param start_x: x轴起始坐标 :param start_y: y轴起始坐标 :param end_x: x轴终点坐标 :param end_y: y轴终点坐标 :return: 生成的截图路径 """ img = Image.open(pic_path) region = img.crop((start_x, start_y, end_x, end_y)) save_path = os.path.join(save_dir, "crop_" + str(round(time.time() * 1000)) + ".png") region.save(save_path) print(save_path) return save_path crop_pic = crop_area(screenshot_pic, temp_dir, 0, 1260, 1080, 1338) 复制代码裁剪后的图片: 接着灰度二值化一下,试了几次,发现240比较合适: def picture_to_black_white(pic_path, save_dir, threshold=127): """ 图片二值化(黑白) :param save_dir: :param pic_path: 图片路径 :param threshold: 灰度阈值,默认127 :return: 转换后的图片路径 """ img = Image.open(pic_path) save_path = os.path.join(save_dir, "bw_" + str(round(time.time() * 1000)) + ".jpg") if threshold == 127: img.convert('1').save(save_path) else: img.convert('L').point([0 if x < threshold else 1 for x in range(256)], '1').save(save_path) return save_path bw_pic = picture_to_black_white(crop_pic, temp_dir, 240) 复制代码处理后的图片: 可以,效果很Nice,紧接着就是检测文字区域了,这里有两个思路~ 思路①:卷积运算进行边缘检测借鉴《python实现图像边缘检测》,采用 卷积运算 来进行边缘检测,具体方法如下: 看不太懂?没关系,直接CV代码: # 求卷积 def convolution(img, x, y): convolution_list = [1, 1, 1, 1, -8, 1, 1, 1, 1] # 卷积核列表 color_list = [] xl = [x - 1, x, x + 1] yl = [y - 1, y, y + 1] for j in yl: for i in xl: color = img.getpixel((i, j)) # 取出色值 color_list.append(color) c = 0 for i, j in zip(convolution_list, color_list): c = c + i * j return c # 边缘检测 def edge_detection(origin_pic): origin_img = Image.open(origin_pic) w, h = origin_img.size new_img = Image.new('L', (w, h), "white") for x in range(1, w - 1): for y in range(1, h - 1): c = convolution(origin_img, x, y) if c > 0: s = 0 else: s = 255 new_img.putpixel((x, y), s) new_img.save("test_n.png") 复制代码运行看看: em?好像不太对劲,没有想象中的框,一开始还以为是算法问题,后面看了下二值化后的图片,发现竟然有0和255外的色值: 搜了下有人说是PIL模块的point()二值化不彻底,于是我遍历每个元素手动设置了一波,后面发现也是如此。折腾了好一会儿,才找到了问题的根源: 保存的图片格式为 .jpg,默认清晰度是75,有损压缩导致出现 马赛克。清晰度可以通过 quality 参数指定,1(最差)到95(最佳),使用时应尽量避免高于95的值,100会禁用部分JPEG压缩算法,并导致大文件图像质量几乎没有任何增益。 说的很好,我选择保存成 .png 格式,再次运行: 牛批,真的把数字的轮廓抠出来了,接着就是计算中心点咯,找到两个数字各自的左右x坐标,求平均值: 在 edge_detection() 的循环中,加个 Set (自带去重),把边缘的点的x坐标都丢进去。 接着转化为List,升序排列,列表头尾元素 分别为第一个数字的左边 和 第二个数字的右边。从左到右遍历,如果前后两个x坐标相差大于50,说明前一个元素是 第一个数字的右边,后一个元素是 第二个数字的左边,得到四个x坐标,依次求出两中心点和距离,具体代码如下: 运行输出结果: 卷积运算进行边缘检测可以,接着来试试第二个思路。 思路②:土方法无脑遍历坐标点还是那个二值化后的图片,图中的数字有两个: 从前和后开始扫,可以快速得出:第一个数字的左边坐标 和 第二个数字的右边坐标,然后 取中点,一个向前,一个向后扫,可以快速得出 第一个数字的右边坐标 和 第二个数字的左边坐标,这样可以减少无效遍历次数,直接写出具体代码: 运行输出结果如下: 虽然x坐标和卷积计算检测出来的结果差1,但最终计算出的 距离是一样的,为什么差1,读者可以自己思考下~ 行吧,路程的测量方法已经get√到了,接着到速度~ 0x3、采集速度这个就简单些了,控制变量 → 固定长按的时间,比如:100ms,然后 按压前截图,按压后截图,计算两块木板的长度差,除以100ms,就能拿到 木板变长的速度。 看到这里估计有些童鞋会收:你仿佛在逗我,来,给你个秒表,按压个100ms我看看? em...手动肯定是不行的,但是 自动 可以哇,利用在 《杰哥带你玩转Android自动化》 专栏学到的姿势就阔以~ 先是 长按屏幕,ADB中并 没有直接提供长按屏幕的命令,但是我们可以通过 滑动来模拟长按。当 滑动前后两个坐标差值足够小,android系统就会认为我们进行了长按操作。直接写出工具代码: def long_click_xy(x, y, duration): return start_cmd('adb shell input swipe %d %d %d %d %d' % (x, y, x + 1, y + 1, duration)) 复制代码接着就是点击坐标的确定,直接打开 开发者模式 → 找到 指针位置 → 打开开关,此时点击屏幕,就能看到触摸点的XY坐标了~ 行吧,接着代码自动生成按压前后的截图了: def get_speed(): long_click_xy(546, 1774, 100) sleep(0.1) screenshot(temp_dir) 复制代码运行一下: 100ms有些快了,这都要掉水里了,而且截图也是需要时间的(不是实时的),改成500ms看看吧,也不休眠,直接截图: 行吧,截图拿到了,接着量下木板有多长,即 木板起点到终点距离多少个像素,这里也不整些花里花哨的,直接 PS 取。 电脑没装,直接搜 photoshop在线网页版,然后打开截图,右键吸管,找到 标尺工具: 点击起点拖拽到终点,右上角就能拿到 木板的最终长度 然后其实状态的截图也是这样操作,拿到 木板的初始长度 两个长度相减,然后除以500ms,最终得出木板的变长速度约为:86px/100ms 0x4、计算时间距离和速度都获取到了,接着就是相除求时间了。另外,这个棍子并不是居中的,计算出距离后还要减去棍子的偏移值。代码如下: # 求出距离 distance = second_center_x - first_center_x - 55 # 除以速度,求出按压时间 duration = int(float(distance / 86) * 100) # 模拟按压 long_click_xy(546, 1774, duration) 复制代码加个循环,调用上述代码,运行看下效果: 控制台输出信息如下: 有些朋友看到这里估计还不信:这是录屏,而且就前四关,不会是你自己玩然后装成脚本在玩吧? 这波石锤了,杰哥真的是玩游戏开 "辅助",从现在开始这里叫做XXX广场!!!2333,🐶消费一下~ 行吧,就折腾到这里,对源码感兴趣的可以移步至:sssf.py 自行查看,谢谢,也提前祝各位读者 春节快乐,阖家安康~ |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |