序言:最近在学习图像视觉,基础不太好。也用在自己学程序语言时候的激情和方法尝试了一下。
最近 “梦幻西游” 挖图脚本的猖狂。可我关心的是他们挖图脚本的由来,以及验证自己最近的一些学习成果,尝试一下对挖图脚本制作。
主要涉及技术:
JAVA,PYTHON,OPENCV,OCR
(一)对场景图片中关于宝图店铺的识别,模拟鼠标点击
(场景)
1:分析步骤
1:JAVA调用JNI接口获取梦幻西游客户端窗口句柄(JNI 学习时间成本有点高,现阶段暂时指定位置)
主要这一步是对我们实现截图进行定位。可以得到客户端的窗口在屏幕中的位置。可以实现对区域进行截图(后续针对每一个区,宝图店铺区域的不同,我们可以把对应坐标存在数据库中,达到通用性)。
/**
* 根据 游戏客户端 宝图店铺对应区域的一个截图
* @param x 坐标
* @param y
* @param width 宽度
* @param height 高度
*/
public static BufferedImage getCreenshotsImage(int x, int y, int width, int height) {
BufferedImage bfImage = null;
try {
Robot robot = new Robot();
bfImage = robot.createScreenCapture(new Rectangle(x, y, width, height));
} catch (AWTException e) {
e.printStackTrace();
}
return bfImage;
}
2:得到店铺的宝图店铺大致所在的一个区域。对每个店铺中的文字进行识别
这里使用OPENCV 的的一些基础知识(也是我在这个阶段暂时遇到的最大一个坎,不过一切都好,总算努力不会白费)
PYTHON 代码(实现了图片中检索出所有店铺的区域位置)
#coding:utf-8
import sys
import os
sys.path.append([\'E:\\python3.6\\Lib\\site-packages\'])
#sys.path.append(\'E:\Opencv\pythonObject\')
import numpy as np
import cv2
import redis
import json
def baotuDianPu (uuid):
#缓存读取JAVA UUID值,对应UUID 从 REDIS中取得对应图片的数据
db = redis.Redis(host=\'localhost\',port=6379,db=0,password=\'\',);
imageUrl = db.get(uuid);
imageUrl = str(imageUrl,encoding=\'utf-8\')
if(imageUrl ==None):
return;
image = cv2.imread(imageUrl);
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY);
# 双边滤波
gray = cv2.bilateralFilter(src=gray, d=2, sigmaColor=100, sigmaSpace=13)
gray = cv2.threshold(gray, 180, 255, cv2.THRESH_BINARY_INV)[1];
# 开区间
kernel = np.ones((3, 3), np.uint8)
gray = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
# 自适应 阈值
gray = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
# 返回轮廓黑白
gray = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY | cv2.THRESH_BINARY_INV)[1]
# 开区间
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4, 4));
gray = cv2.morphologyEx(gray, cv2.MORPH_OPEN, sqKernel);
# 计算轮廓 retr_external 只检测外轮廓, CHAIN_APP...保存坐标点 返回参数refCnts 是轮廓
refCnts, hierarchy = cv2.findContours(gray.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE);
# 指定字典 一个坐标系, 一个 坐标远在返回轮廓坐标
digitsTrain = []
imas = image.copy();
for (i, c) in enumerate(refCnts):
# 计算 外接矩形resize合适的大小
(x, y, w, h) = cv2.boundingRect(c);
# 因为店铺的高度是固定的
# if ((disX>2.5and disX<4.5)):
if ((h <= 19 and h >= 15 and w >= 20 and w <= 95)):
#放进集合中 ,每四个一个
digitsTrain.append((x, y - 1, w, h));
strs = "";
print(len(digitsTrain))
if(len(digitsTrain)>0):
strs = json.dumps(digitsTrain, indent=2, ensure_ascii=False)
db.set(uuid,strs);
db.close()
#存进REDIS
if __name__ == \'__main__\':
for i in range(1, len(sys.argv)):
uuid = sys.argv[i];
baotuDianPu(uuid)
上面已经得到该该图片 能找出所有的的店铺的位置
主要我对PYTHON 还不太熟悉,为了节约时间成本,我选着了用JAVA调用PYTHON 的方式拿值,中间用redis做数据交换存储.
JAVA 调用代码:(JAVA 调PYTHON 的时候,有坑。用不了第三方包,主要原因自己在pycharm里面是有编译环境的,而独立出来的python 里面没有编译环境,在PY文件头上记得要加上包的路径,我是这样理解的)
public static void main(String[] args) throws InterruptedException {
String uuid = UUID.randomUUID().toString();
//CMD 执行PYTHON 所在路径(这一步有很多坑,主要设置自己的环境== 要不然你得不到运行时候,会调用不了第三方包)
String[] param = new String[] {"E:\\python3.6\\python.exe","E:/Opencv/pythonObject/baotuDianPu.py",uuid};
String imageUrl = "D:/Users/admin/Desktop/test/test1.png";
Jedis jedis = RedisUtils.getJedis();
jedis.set(uuid,imageUrl);
//执行脚本
try {
Process proc = Runtime.getRuntime().exec(param);
} catch (IOException e) {
e.printStackTrace();
}
//线程听两秒
Thread.sleep(2000);
String list = jedis.get(uuid);
System.out.println(list);
RedisUtils.returnResource(jedis);
}
3:进行 宝图店铺的检测
这里我尝试了很多方法,由于自己的技术有限。知识面还不够广,对文字的识别还是有点困难。
这是我第一次尝试用在识别的时候直接逐字判断包含有宝图 TT 图 等字样的图片出来,效果不太理想,我只想要有 "ttt" ,"图","TT"类似的店铺, 什么鬼都给我识别出来了。哈哈
机器学习的 svm 识别的差别还是差不多。为了不停止下来,我尝试了一些OCR接口与工具,百度,阿里==接口(好贵)。自己做tess4jOCR的话(效果貌似也不太行).
最后借助一个OCR的工具:
能有比较高效率的识别对应中的文字。因为上面,我已经得到了 所有店铺的所有区域位置的LIST。那么如果想对该区域文字的识别,只要用JAVA控制鼠标操作 就可以实现文字的提取。后续进行对文字保存然后在txt的读取。就能判断该店铺是否是宝图店铺。进行截图。我在虚拟机里面做了简易的WEB后台,只提供接口 ,把OCR工具放进了虚拟机进行操作。这样我本地的鼠标操作就直接省去了。
4:根据这个得到该宝图店铺的位置,就可以干嘛了?大家都应该知道了。
下面也就是重复的动作,
1:控制点击店铺。判断是否有宝图。价格几何?
2:检测自己背包是否满了。
3:........
后续 .....敬请期待
一边学习,而且对自己喜欢的游戏进行学习,那种兴趣 哈哈 。。欢迎探讨一下。。。