前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我用Python合成大西瓜!

我用Python合成大西瓜!

作者头像
Datawhale
发布2021-02-05 14:28:09
6090
发布2021-02-05 14:28:09
举报
文章被收录于专栏:Datawhale专栏

这周五没漂亮妹妹带我出去玩了呜呜,无聊在家扣手机,发现大家都在合成大西瓜 。作为一个未来年轻无为的计算机科学家(或许是人民艺术家),我是不屑于玩这种浪费时间又无聊的游戏的(因为玩了四小时才合成了第一个大西瓜),但为了投身到人民群众中去,我决定尝试写一个程序挂机跑一下。

写了一下午,我的第一版Python大西瓜终于写完了,虽然还是挺智障的,但至少打败了50%的人,也算通过图灵测试了哈哈哈哈哈哈。其实是怕过两天我写个最终版,大家都玩够了,小丑就是我自己了,为了吃一口热乎的s**t,我就现在发了哈哈哈哈。

如果下周五还有人玩这游戏,我还会继续写的。

本文章分为六个部分(如果我能坚持写完不睡着的话):

  1. 图像捕捉
  2. 水果检测
  3. 水果识别
  4. 去除噪声
  5. 点击控制
  6. 游戏策略

话不多说,开冲!


1. 图像捕捉

作为一个计算机程序,合成大西瓜的第一步就是能够看到大西瓜

这一步超级简单了,只需要使用python自带的windows图形界面接口win32gui就可以操作。其中最重要的环节就是获取浏览器窗口的上下左右四个顶点的坐标,调用FindWindow方法获取窗口对象,然后把窗口对象传给GetWindowRect获取顶点坐标。

这地方我卡了很久,因为FindWindow需要首先知道窗口的名字,我试了试“Edge”不对,“合成大西瓜”也不对,最后机智的我打开了Alt + del,发现它叫“小游戏:合成大西瓜 - 个人 - Microsoft\u200b Edge”仿佛在对我说:“我不叫喂,我叫……”

然后再用PIL库的ImageGrab方法截图屏幕窗口内的像素,转化成numpy数组,就可以进行后续处理啦。

2. 水果检测

在我们获取到图像后,下一步就是识别水果的位置了,一个自然的思路就是识别圆,因为这里的水果都是圆的(我真谢谢作者没有加个香蕉。什么?你说甘蔗也是水果……)

然后我还想吐槽一下,下面这个到底是什么东西啊?是两排牙齿吗?有没有人和我一样觉得莫名很恶心?而且这玩意转换成灰度图以后更恶心……

Ok 基于这个思路,我们只需要找到图里面的圆形就好啦!

这里的思路是OpenCV里面已经实现好的经典圆形识别方法——霍夫圆检测法(看清楚,不是霍夫曼,不是霍夫曼,不是霍夫曼)。基本思路就是找几个边缘点,然后边走边画圆,最后看圆心是不是在一起吧……我不是搞CV的,如果有错误请大佬们评论区指正。

这一步主要有两个难点吧。第一个就是水果都叠在一起,两个圆形很容易连通在一起,从而找不到圆。我是通过设置一个13乘13的高斯滤波器,先把边缘模糊一下,然后再提取会好很多。

第二个难点是cv2.HoughCircles有三四个要调整的参数,怎么选对最后的识别效果影响很大……我是通过GridSearch遍历参数看识别效果选定的最后参数,老深度学习炼丹师了哈哈哈。

最后我们获取的是很多圆形的坐标以及半径。

3. 水果识别

下一步我们拿到一堆圆形后,就是要知道每个圆形对应的是哪种水果了。然后我想采访一下游戏的开发者,为什么橙子 和柠檬 要设计成一样大?拉瓦锡的棺材板快要压不住了(物质守恒定律)。

所以我不能够通过圆形的半径确定是哪个水果了(大哭),而且霍夫圆检测的结果扰动也挺大的,同一个水果两次检测的半径可能有一定差别。

到这里,一个聪明的靓仔就会输入import pytorch摩拳擦掌准备模式识别了,我这种憨憨选择的是把圆内部的平均RGB值求出来,然后加上半径一起对比,找相似度最大的。

觉得有点对不起初中数学老师,忘了根据圆心和半径怎么求圆内坐标了,求个内接矩形内像素的RGB平均值……

最后就建立了这么一个从RGB平均值+半径到水果种类的映射:

代码语言:javascript
复制
fruit_type = {
    'GRAPE' : [133.68415638 ,42.41563786,112.84156379, 18],
    'KIWI' : [132.0420593,201.00264307,64.44633418, 53],
    'CHERRY' : [238.33213966,39.17905103,56.09982095, 28],
    'ORANGE' : [246.2261046,129.05342651,21.69071235, 37],
    'LEMON' : [237.19926471,216.40716912,65.56176471,  43],
    'TOMATO' : [238.18209682 ,89.91402075,95.00730902, 66],
    'PEACH' : [235.99086897,165.13803074,97.37832902, 65],
    'PINEAPPLE' : [248.87955751,219.50704342,88.25265164,89],
    'COCONUT' : [230.9732507,225.98286918,211.98437795, 101],
    'WATERMELON' : [236.62388536,100.24692594,121.0164732,143],
}

4. 去除噪声

就当我以为可以进行下一步时,我又发现了很多问题,主要是因为大菠萝 和椰子 ,我爱椰汁 ,我恨椰子。

这菠萝和椰子有两层,本身就含有两个圆,所以识别出来的结果经常出来很多重合的圆,例如下面这样:

所以我还得想办法去除重合的圆,这里我选择的方法是对所有的圆心两两比较,如果他们的距离的和小于两个圆半径的和,那么就是重合了。那么我们如何判断哪个圆是正确的呢?继续比较相似度吧…跟标准图形相似度大的就是正确的。

虽然方法很朴实无华,但它貌似确实很有用。

5. 点击控制

这个其实也很简单,没什么难点

使用Python内置的win32api.mouse_event方法模拟鼠标点击事件就可以,只有一个需要注意的地方是,它是会强制控制你的鼠标……所以如果你的手速不够快的话,可能点击不了右上角关闭程序的那个叉叉,只能眼睁睁看着你的水果叠到最上面……

6. 游戏策略

实际上今天我主要是在摸索怎么识别和控制了,自己想的算法都没有实现,为了吃一口热乎s**t,现在只是一个智障版本。

策略是如果有一样的就往那里落,如果没有就落在最中间。

这个策略显然是非常烂的,因为一样的话会变大可能对结构更加不利。如果没有一样的,落在不同位置也会导致整体结构不同……我觉得首先应该是避免小的在大的上面,类似于2048尽量别往上滑的策略,因为如果大的在上面小的可能永远无法合成了。

应该去如何维持一个良好的结构,是不是要像计算机体系结构一样设计个多级缓存?能不能为每一步设计一个评估指标,对算法自动进行迭代优化?每次刷新的水果顺序是不是相同的,以及是否有一定统计规律?如果我们能够预先知道后续刷新的水果,我们就可以使用A*或者其他启发式算法进行搜索了。甚至我们能不能用一些AI方法例如强化学习来做?

有好多好多可以尝试的有趣的Idea,如果这游戏下周五还有人玩,我很愿意尝试一些新的思路,这个合成大西瓜系列也会继续更新哈哈。但是现在,真的,我搞了一整天,满脑子都是山竹+山竹=樱桃……再让我看一眼我就吐了

7. 关于作者

介绍一下小雨姑娘吧,年轻无为的计算机博士生,未来的人民艺术家,现居青岛。基本平时时间都在看书和做Research了,有时间会来知乎写写文章。大家可以关注下我的两个专栏:小雨姑娘的机器学习笔记和小雨姑娘的算法笔记,认真写知识的那种,跟这篇文章不一样的,认真的,哈哈。

困到睁不开眼,还是坚持写完了…… 那么,我再去玩两盘大西瓜。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-01-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Datawhale 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 图像捕捉
  • 2. 水果检测
  • 3. 水果识别
  • 4. 去除噪声
  • 5. 点击控制
  • 6. 游戏策略
  • 7. 关于作者
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档