美文网首页辅助插件
阴阳师插件 [寮功勋统计工具]

阴阳师插件 [寮功勋统计工具]

作者: 闭门造折 | 来源:发表于2019-06-06 14:43 被阅读0次

    目的很简单,统计每天做寮30的情况,以及每天是否做的是两章任务。目前这个工作是会长和副会长人工统计(每次一有活动就会chua chua掉排名)的,希望可以解放双手。

    参考了御魂导出器和御魂放大镜,他们都提到了面向内存编程,但是又没有说怎么面向内存。

    所以作为新手小白,我决定先写一个模拟点击的脚本先用着。

    网上说脚本和外挂的很大区别在于,脚本不做修改,仅是把数据可视化显示/模拟人工操作,而外挂可能实现的是诸如锁血等骚东西。

    环境配置

    win32api:用于窗口控制

    首先安装win32api,使用的指令是

    pip install pywin32
    

    安装好后就可以正常调用win32api,win32con等等

    pytesseract:用于图像文字/数字提取

    接着安装pytesseract,具体步骤及资源,请参考文末[参考资料3](http://www.inimei.cn/archives/297.html

    具体实现

    首先确认整个流程:①打开痒痒鼠PC端 ,点击到阴阳寮页面 ②切换到功勋界面 ③记录功勋+不断下翻。⑤后续的比对之类的并没有写,想的是用json的形式存储在本地文件中,每次进行更新比对

    步骤一:确认用户已完成①步骤

    def get_window_info():  # 获取阴阳师窗口信息
        wdname = u'阴阳师-网易游戏'
        handle = win32gui.FindWindow(0, wdname)  # 获取窗口句柄
        if handle == 0:
            print("Error to find yys")
            return None
        else:
            return win32gui.GetWindowRect(handle)
    

    这一步中,是判断当前有没有打开PC端痒痒鼠
    main函数中这样调用:

    if __name__ == '__main__':
        # 初始化窗口定位
        window_size = get_window_info()
        if window_size is not None:
            initx = window_size[0]
            inity = window_size[1]
    

    得到的initx和inity就是痒痒鼠界面在整个屏幕的坐标值。



    上图为痒痒鼠的阴阳寮界面,我们通过截图,得到右侧的功勋切换按钮,距离左上角的相对坐标:



    windows自带的画图工具有一个好处,即是你将鼠标放置在图像上时, 左下角会实时显示鼠标对应的当前像素坐标。也就是说,(左上角x坐标 + 1002,左上角y坐标 + 367)这个像素点,就是我们鼠标在整个屏幕中放置的位置。
    为了确认用户打开了正确页面,我们采用左上角的图像作为识别用图像
    左上角局部图像

    通过grab+绝对坐标的形式,截取需要的内容,还可以用过save保存,或是show显示

    # 确认当前为管理页面
    img_manage = pic_grab(40, 40, 300, 300, initx, inity)
    
    # 查看图片
    # img_manage.show()
    # img_manage.save('manege_symb.jpg')
    

    pic_grab函数是自定义用来截取绝对坐标的函数

    def pic_grab(topx, topy, bottomx, bottomy, initx, inity):
        return ImageGrab.grab((initx + topx, inity + topy, initx + bottomx, inity + bottomy))  
    

    截取了图片后,通过文末 参考资料1中提到的,模拟人工操作时,不全部采用OCR的方法,改为采用图像截取的办法,计算截取图像的平均像素值,然后比对整张图像和平均像素值的差异,得到图像的hash值。之后只需再次截取进行比对(比对时采用了汉明距离),即可知道是否正确进入界面,对图像进行判断

    图像hash计算及汉明距离计算:

    def get_hash(img):      # 对图片计算hash值
        img = img.resize((16, 16), Image.ANTIALIAS).convert('L')  # 抗锯齿 灰度
        avg = sum(list(img.getdata())) / 256  # 计算像素平均值
        s = ''.join(map(lambda i: '0' if i < avg else '1', img.getdata()))  # 每个像素进行比对,大于avg为1,反之为0
        return ''.join(map(lambda j: '%x' % int(s[j:j+4], 2), range(0, 256, 4)))
    
    def hamming(hash1, hash2, n=20):    # 计算汉明距离
        b = False
        assert len(hash1) == len(hash2)
        if sum(ch1 != ch2 for ch1, ch2 in zip(hash1, hash2)) < n:
            b = True
        return b
    

    为了后续可以判断界面是否正确,我们预先需要先运行一遍正确的,并保存正确的hash值

    img_manage_hash = get_hash(img_manage)
    print(img_manage_hash)
    

    步骤二:获取阴阳寮人数

    终于用到ocr识别了,方法也很简单,首先同样的截取人数位置的图像,然后通过ocr识别图像内容,数字识别函数:

    def pic_digit_read(path):
        image = Image.open(path)
        text = pytesseract.image_to_string(image, config = 'digits') # 数字识别
        fil = filter(str.isdigit, text)
        new_text = ''
        for i in fil:
            new_text += i
        return int(new_text)
    

    截取+调用过程:

    # 获取总人数
    img_tmp = pic_grab(315, 195, 357, 219, initx, inity)
    img_tmp.save('peoNum.jpg')
    peoNum = pic_digit_read('peoNum.jpg')
    print(peoNum)
    

    步骤三:移动并点击切换

    为了不被痒痒鼠查出采用了外挂,我们将点击范围改为范围点击,即在一个可点击范围内,通过random函数实现较随机的点击。

    def random_in_range(min, max):      # 在给定范围内进行随机数
        return min + int((max - min) * random.random())
    

    按照你的需求依次点击相应位置即可

    步骤四:开始识别 名字+功勋

    分别截取名字,功勋,以及其他你想统计的信息,分别做ocr识别
    这里名字部分由于出现了 日文/俄文/特殊符号,可能会有相应的问题,由于我们采用的是最简单的基本OCR库(扩展的需要安装很久我懒得全装了),所以可能识别不准确。
    一开始我用的方法是,识别2次,然后做相似比对,不一致部分用*代替(一般是难识别字)。比如说 猥琐的哈哈,可能最终就存储成了*琐的哈哈。
    后来我发现可以用灰度处理,把文字部分凸显(下面get_bin_table中的默认参数135,是通过我实践+肉眼得到的最佳值)。
    实践方法是对同一批图像的每一张,通过从90,每次+10的形式,处理至180,挑出其中文字显示及识别均正确的图像,缩小上下限及变化幅度
    最终发现在132-137范围处理结果最佳,因此定在了135。当然这个不是绝对准确的,如果时间及性能允许,多处理几次取众数可能更好一些。
    文字识别部分代码:

    def get_bin_table(threshold = 135):
        # 获取灰度转二值的映射table
        table = []
        for i in range(256):
            if i < threshold:
                table.append(0)
            else:
                table.append(1)
        return table
    def pic_word_read():
        image = Image.open('name_tmp.jpg')
    
        imgry = image.convert('L')
        table = get_bin_table()
        out = imgry.point(table, '1')
        text = pytesseract.image_to_string(out, lang='chi_sim') # 灰度处理后识别
        text = text.replace(" ","").replace("\"","").replace("\'","").replace("\t","").replace("\\","")
        print(text)
        return text
    

    下翻页

    一页识别完了(应该可以识别5个),翻到下一页

    # 滑动页面
    #   scoll_window(initx + random_in_range(448, 968), inity + random_in_range(170, 518), -352)
    

    完整代码

    完整代码请移步github项目
    Github项目:《JustForFun - 痒痒鼠寮勋章自动统计》By ZaoZhe6666

    参考资料

    参考资料1《Python实现自动挂机脚本(基础篇)》

    参考资料2 《游戏辅助脚本(python)》

    参考资料3 《Python实例:利用pytesseract库进行图片文字识别》

    参考资料4 《Python实例:利用pytesseract库进行图片文字识别(二)》

    相关文章

      网友评论

        本文标题:阴阳师插件 [寮功勋统计工具]

        本文链接:https://www.haomeiwen.com/subject/oavnwqtx.html