最近小猿口算里面的PK功能比较火,很多大学生在里面欺负小学生。我想,为什么不能用AI来欺负欺负那些想炸鱼的大学生呢。于是就有了下面的文章。
设计思路
其实想实现这个程序很简单,首先安装模拟器,运行小猿口算。然后通过文字识别技术识别题目,再用一些简单的判断计算出结果,最后通过模拟鼠标移动轨迹实现答题。所以我们现在就有一下问题等待解决:
1.安装模拟器
2.获取屏幕
3.文字识别
4.运算
5.输出结果
1.安装模拟器
市面上模拟器很多,这里不一一举例了,我选择的是蓝叠模拟器。他有个优势就是能录制脚本并且绑定快捷键,也就是能按一个键让鼠标自动滑,这样可以省的我们去设计鼠标移动的路径,只需模拟按下对应的按键就行。
蓝叠的下载地址:https://www.bluestacks.cn
进去之后下载蓝叠5,安装教程不做过多赘述。
然后就是安装小猿口算了,如果你是安卓手机可以在应用商店下载之后发到电脑上,或者在浏览器找安装包。
这是我找到的安装包网址:https://app.cdo.oppomobile.com/home/detail?app_id=3623864
下好之后直接将安装包拖到模拟器中就行,等待一会,会自动安装。
2.获取屏幕
python获取屏幕的方式有很多,我选择的是pyautogui这个库。
安装方法就是Win+R输入cmd
然后在里面输入
pip install pyautogui -i https://pypi.tuna.tsinghua.edu.cn/simple/
当有Successfully 时证明你安装成功了(0.9.54是我用的版本,依据你自己用的版本来)
Successfully installed pyautogui-0.9.54
安装完成之后就能导入pyautogui库了
import pyautogui
我们主要使用的函数有
pyautogui.press(keys=" "#模拟按下的按键, presses=#次数) #模拟按下
pyautogui.screenshot(region=(#起始x,起始y,宽,高))) #截屏
因为整个屏幕所包含的信息太多太杂了,为了简化处理内容,提高处理速度,所以我们选择仅对关键信息截图,没错就是题目的数组部分
我的屏幕是1920*1080的,系统缩放比例是100%,然后调试获得的第一个数的四位数据分别是
180,250,70,70
第二位数的四位数据是:
315,250,70,70
如果你想套用我的程序建议也把屏幕设置成1080p,系统缩放100%,然后将模拟器调成竖屏模式,对齐左上角(如下图)这样不用额外调位置
调试完之后我们开始写程序获取数
import pyautogui
num1 = pyautogui.screenshot(region=(180,250,70,70))#获取第一个数
num2 = pyautogui.screenshot(region=(315,250,70,70))#获取第二个数
2.文字识别
文字识别我们就用到了OCR技术。下面是该技术的介绍:
OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程;即,针对印刷体字符,采用光学的方式将纸质文档中的文字转换成为黑白点阵的图像文件,并通过识别软件将图像中的文字转换成文本格式,供文字处理软件进一步编辑加工的技术。如何除错或利用辅助信息提高识别正确率,是OCR最重要的课题,ICR(Intelligent Character Recognition)的名词也因此而产生。衡量一个OCR系统性能好坏的主要指标有:拒识率、误识率、识别速度、用户界面的友好性,产品的稳定性,易用性及可行性等。
对于python,想使用该技术可以通过pytesseract库实现。
安装该库也可以通过Win+R运行CMD,在CMD中输入以下代码安装
pip install pytesseract -i https://pypi.tuna.tsinghua.edu.cn/simple/
同上,当显示Successfully时证明安装成功。
到这里,并不能直接使用该库,如果使用的话会报错找不到路径,因为还需另外下载Tesseract,网上好多关于该库的教程都有这个坑。
Tesseract可以在这个链接下载:https://digi.bib.uni-mannheim.de/tesseract/
进去之后找到含有win32的项直接点击下载。(win64的好像也可以,但是我写程序的时候没找到,写文章的时候找到了!!!!保险起见就先用win32的)
下载之后点开文件
安装
step.1
step.2
step.3
step.4(如果没有这步别慌,不要紧的,只是多了几种支持的语言,但是我们这里识别数字,所以用不到)
step.5(记住下载地址,等下配置环境要用)
step.6等待下载完成,这里我下过了就不点了。
下载完成之后我们开始配置环境
首先打开设置
搜索高级系统设置
点击环境变量
点击Path,再点击编辑
点击新建,将刚刚安装地址输入,回车
然后点确定,之后的界面都点确定,我懒得再截图了
最后win+R运行CMD,输入tesseract看看报不报错,如下图即为成功
之后在python导入pytesseract库即可使用
import pytesseract as orc
为了使ORC识别的准确率提高,我们还要对图像进行预处理,所以这里就需要Opencv-python库和Numpy库
安装方法同上,在CMD里面输入一下代码,这里不过多叙述。
pip install numpy -i https://pypi.tuna.tsinghua.edu.cn/simple/
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple/
之后在程序里导入
import cv2 as cv
import numpy as np
因为pyautogui库截取的图片opencv无法直接使用,所以我们需要将截取的图片转化成标准的numpy数组,所以截图的代码可以改为
import cv2 as cv
import pyautogui
import pytesseract as orc
import numpy as np
num1 = np.array(pyautogui.screenshot(region=(180,250,70,70)))
num2 = np.array(pyautogui.screenshot(region=(315,250,70,70)))
然后将图片灰度化去除色彩信息
num1 = cv.cvtColor(num1, cv.COLOR_BGR2GRAY)
num2 = cv.cvtColor(num2, cv.COLOR_BGR2GRAY)
为了方便调试,所以我们需要将截取的图片展示,这里我创建了一个纯黑的图片,再将截取的图片复制到背景上,最后输出背景就行了。代码如下
import cv2 as cv
import pyautogui
import pytesseract as orc
import numpy as np
while True:
blackground = np.zeros((70,230), np.uint8)
num1 = np.array(pyautogui.screenshot(region=(180,250,70,70)))
num2 = np.array(pyautogui.screenshot(region=(315,250,70,70)))
num1 = cv.cvtColor(num1, cv.COLOR_BGR2GRAY)
num2 = cv.cvtColor(num2, cv.COLOR_BGR2GRAY)
blackground[0:70,0:70] = num1
blackground[0:70,160:230] = num2
cv.imshow("Monitor",blackground)
if cv.waitKey(1) & 0xFF == 27:
break
cv.destroyAllWindows()
图片处理完之后,就可以甩给pytesseract识别了。
pytesseract.image_to_string()函数会将结果整合成一个字符串,我们可以将这个字符串赋值给两个变量以供我们使用
识别的代码如下
number1 = orc.image_to_string(num1,config=r'-c tessedit_char_whitelist=0123456789 --psm 6')
number2 = orc.image_to_string(num2,config=r'-c tessedit_char_whitelist=0123456789 --psm 6')
4.运算
因为pytesseract输出的字符串里包含空格,所以我们需要先将空格去除然后将字符串转为整数进行比较大小。
代码实现如下
for i in number1:
if i == " ":
number1 = number1.replace(" ","")
for i in number2:
if i == " ":
number2 = number2.replace(" ","")
通过遍历字符串的每个值,然后判断是否为空格,是那么删除空格。
然后转换为整数进行判断大小
if int(number1) > int(number2):
print(int(number1),int(number2),">")
if int(number1) < int(number2):
print(int(number1),int(number2),"<")
5.输出结果
首先我们先需要录制对应的鼠标轨迹
1.打开脚本录制
2. 录制脚本
3.录制,完成后停止(录制内容其实就是用鼠标画大于号小于号两个要分开录制成两个脚本)
4.设置脚本运行时不弹出窗口
保存然后设置脚本的快捷键
这里我“<”绑定的是“D”,“>”绑定的是“X”
然后就方便了,当输出是“>”时候模拟按下"D",否则模拟按下“X”
代码如下
if number1 > number2:
pyautogui.press(keys="d", presses=1)
if number1 < number2:
pyautogui.press(keys="x", presses=1)
最后,把代码整合下,加一些延时,再加入判断,判断是否有数字,数字识别是否重复了(因为出题不可能同时出两道一模一样的题目),判断是否结束了,结束了模拟鼠标自动开始下一把,就大功告成了。
完整代码
(加了自动开始,我懒得写注释了ヾ(≧ ▽ ≦)ゝ)
import cv2 as cv
import pyautogui
import pytesseract as orc
import numpy as np
import time
def write(data):
if data == 1:
pyautogui.press(keys="x", presses=1)
if data == 0:
pyautogui.press(keys="d", presses=1)
nextx = [340,400,300]
nexty = [540,1000,870]
state = False
number1_old = 0
number2_old = 0
while True:
blackground = np.zeros((70,230), np.uint8)
num1 = np.array(pyautogui.screenshot(region=(180,250,70,70)))
num2 = np.array(pyautogui.screenshot(region=(315,250,70,70)))
num1 = cv.cvtColor(num1, cv.COLOR_BGR2GRAY)
num2 = cv.cvtColor(num2, cv.COLOR_BGR2GRAY)
blackground[0:70,0:70] = num1
blackground[0:70,160:230] = num2
number1 = orc.image_to_string(num1,config=r'-c tessedit_char_whitelist=0123456789 --psm 6')
number2 = orc.image_to_string(num2,config=r'-c tessedit_char_whitelist=0123456789 --psm 6')
for i in number1:
if i == " ":
number1.replace(" ","")
for i in number2:
if i == " ":
number2.replace(" ","")
if number1 and number2 and number1_old != number1 and number2_old != number2:
state = True
if int(number1) > int(number2):
print(int(number1),int(number2),">")
write(1)
if int(number1) < int(number2):
print(int(number1),int(number2),"<")
write(0)
time.sleep(0.05)
number1_old = number1
number2_old = number2
else:
if state:
time.sleep(3)
for i in range(0,len(nextx)):
pyautogui.moveTo(nextx[i], nexty[i], duration = 0)
time.sleep(0.5)
pyautogui.mouseDown()
time.sleep(0.05)
pyautogui.mouseUp()
state = False
cv.imshow("Monitor",blackground)
if cv.waitKey(1) & 0xFF == 27:
break
time.sleep(1)
cv.destroyAllWindows()
运行效果
https://v.douyin.com/iBXoET61
总结
速度怎么说呢,只能欺负欺负小学生了,遇到手速快一点的估计要被炸鱼了,还有orc识别的准确率其实不高,偶尔会遇到识别不了的,我能力有限,希望有高手能再优化优化我的代码吧。
新人第一次创作,感谢感谢