吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 14567|回复: 453
上一主题 下一主题
收起左侧

[Python 原创] 金铲铲利用paddleocr+pyautogui来实现自动买牌。妈妈再也不用担心我漏牌了

    [复制链接]
跳转到指定楼层
楼主
无阻 发表于 2024-10-2 01:32 回帖奖励
本帖最后由 无阻 于 2024-10-2 11:36 编辑



国庆放假玩了一天金铲铲之战。
因为手残每次后面梭哈都手忙脚乱要么就是手速不够要么就是漏牌
搞得我追不出来想要的牌
一气之下写了个自动买牌的

但是目前只实现了识别英雄名之后自动买牌的功能
CPU优化啥的都没做
后续继续开发吧。弄个金铲铲游戏助手啥的来玩




2024.10.2  优化了截图 触发方式等功能来实现CPU优化
[Python] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# coding = utf-8
import traceback
import numpy as np
from paddleocr import PaddleOCR
from pyautogui import *
import win32gui
import win32api
import logging
import pynput, time
import keyboard
import loguru
import pathlib
import datetime
import os
from concurrent.futures import ThreadPoolExecutor, as_completed, ALL_COMPLETED, wait
 
# 创建日志目录
log_dir = pathlib.Path('./logs')
log_dir.mkdir(exist_ok=True)
if not os.path.exists(f"/logs/"):
    os.mkdir(f"/logs/")
current_date = datetime.datetime.now().strftime('%Y-%m-%d')
if not os.path.exists(f"/logs/{current_date}/"):
    os.mkdir(f"/logs/{current_date}/")
log_file = log_dir.joinpath(f'./logs/{current_date}/' + "log_{time: YYYY_MM_DD}.log")
log = loguru.logger
 
# 只允许一条线程同时识别,解决CPU占用
pool = ThreadPoolExecutor(max_workers=1)
 
# 关闭paddleocr的打印功能,不需要关闭的话去掉下面两行代码
logging.disable(logging.DEBUG)  # 关闭DEBUG日志的打印
logging.disable(logging.WARNING)  # 关闭WARNING日志的打印
 
 
 
#主要识别并且购买函数
def ocr_hero_buy(heroname, windowTitle="腾讯手游助手(64位)", isClick=True):
    time.sleep(0.25# 键盘或鼠标按下后0.3秒后触发
    """
    自动截图模拟器窗口并且OCR指定英雄然后点击购买
    :param heroname:英雄名称,多个请直接传入数组
    :param windowName:模拟器窗口名称
    :param isClick:识别到了是否自动点击
    :return:
    """
    if type(heroname) == str:
        # 如果传入的是单个英雄或者不为数组就转换为数组
        heroname = [heroname]
 
    # 获取指定窗口在屏幕的位置大小函数
    def get_window_rect(window_title):
        # 获取指定窗口标题的窗口在系统中的位置
        hwnd = win32gui.FindWindow(0, window_title)
        if hwnd:
            rect = win32gui.GetWindowRect(hwnd)
            return rect
        return None
    rect = get_window_rect(windowTitle)
    if rect:
        # 计算模拟器窗口在桌面的起始位置和终点位置 启动StartLeft,StartTop这两个参数是窗口在桌面的坐标位置,后面OCR识别到指定英雄的位置的时候必须要加回去
        StartLeft, StartTop, right, bottom = rect
        width = right - StartLeft
        height = bottom - StartTop
    else:
        StartLeft, StartTop, right, bottom = 0, 0, 1, 1
        width = right - StartLeft
        height = bottom - StartTop
    # 调用 pyautogui 进行窗口截图
    image = screenshot(region=(StartLeft, StartTop, width, height))
 
    # 这里是处理裁剪掉模拟器窗口图片的上面80%的图片面积,因为图片越小识别越快,0.8代表80%。如果识别不准确请少截取一点,但是我个人测试只留下20%下方图片即可
    heroBoxheight = image.height * 0.95
    # 这里是处理裁剪掉模拟器窗口图片的左边10%的图片面积,因为图片越小识别越快
    heroBoxwidth = image.width * 0.2
 
    # 记录一下截取掉的位置,后期识别到了点击的时候要架上,因为这部分位置被裁剪掉了
    StartLeft = StartLeft + heroBoxwidth
    StartTop = StartTop + heroBoxheight
    #裁剪图片到适合识别的大小
    image = image.crop((int(heroBoxwidth), int(heroBoxheight), image.width, image.height))
    oimage = image
    # 下面开始OCR
    image = np.array(image)
    result = ocr.ocr(image, cls=False)
    # 一堆if是在检查是否ocr成功,for是遍历识别结果
    point = win32api.GetCursorPos()
    if result is not None:
        for line in result:
            if line is not None:
                for word in line:
                    # 遍历识别结果
                    log.error(word)
                    for hero in heroname:
 
                        if str(word).find(hero) > -1 or heroname == "":
                            log.success(
                                f"发现英雄牌:{hero},坐标位置,x:{word[0][0][0] + StartLeft},y:{word[0][0][1] + StartTop}")
                            if isClick:
                                moveTo(word[0][0][0] + StartLeft, word[0][0][1] + StartTop)
                                click()
 
    return ""
 
 
if __name__ == '__main__':
    # 要截图的窗口标题,目前是腾讯手游模拟器,可以改成别的模拟器的标题一样通用
    windowName = "腾讯手游助手(64位)"
    # 要购买的卡牌名称
    heros = ['雷克顿', '莎弥拉', '卡西奥佩娅', '崔丝塔娜', '烬']
 
 
    # 监听键盘按键,如果是在手游模拟器里面按下的指定按键就启动识别
    def keyboardDown():
        currentWindow(windowName)
 
 
    # 监听鼠标按键,如果是在手游模拟器里面按下的按键就启动识别
    def on_click(x, y, button, pressed):
        if not pressed:
            currentWindow(windowName)
            return True
 
 
    # 判断当前鼠标所在窗口是否是指定模拟器窗口
    def currentWindow(windowTitle):
        point = win32api.GetCursorPos()
        hwnd = win32gui.WindowFromPoint(point)  # 请填写 x 和 y 坐标
        hwnd = win32gui.GetParent(hwnd)
        if hwnd == 0:
            hwnd = win32gui.WindowFromPoint(point)  # 请填写 x 和 y 坐标
        title = win32gui.GetWindowText(hwnd)
        if title == windowTitle:
            pool.submit(lambda cxp: ocr_hero_buy(*cxp),
                        (heros, windowTitle, True))
 
 
    log.success("正在载入OCR金铲铲自动识别选牌工具,正在初始化PaddleOCR模块")
    # 初始化 PaddleOCR
    ocr = PaddleOCR(use_angle_cls=False, lang="ch", use_gpu=False, debug=False, show_log=False)
    log.success("PaddleOCR模块初始化成功,您可以在游戏里按下D键或者鼠标任意键来触发自动选牌")
    # 监听D键 按一次d键启动一次卡牌识别功能并且购买
    keyboard.add_hotkey('d', keyboardDown)
    # 监听鼠标键 按一次启动一次卡牌识别功能并且购买解决死循环D牌导致的CPU占用问题。但是这样也很高,这里还能优化
    with pynput.mouse.Listener(
            on_click=on_click) as listener:
        listener.join()

免费评分

参与人数 62吾爱币 +60 热心值 +58 收起 理由
cdj1258 + 1 + 1 谢谢@Thanks!
datalai + 1 我很赞同!
kanbekotaro + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
Mist_G + 1 我很赞同!
风风魔王 + 1 + 1 我很赞同!
黑色小星星 + 1 + 1 我很赞同!
dxw709822 + 1 + 1 谢谢@Thanks!
xuna2009 + 1 + 1 我很赞同!
来学习的5558 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
xxxlsy + 1 + 1 我很赞同!
peihcheng + 1 + 1 我很赞同!
玄冥岚 + 1 + 1 我很赞同!
yy20240721 + 1 + 1 我很赞同!
liangkuai + 1 + 1 谢谢@Thanks!
bigzhang + 1 + 1 谢谢@Thanks!
ngfc + 1 热心回复!
Clousa95 + 1 + 1 谢谢@Thanks!
cloudy520 + 1 + 1 谢谢@Thanks!
card628 + 1 热心回复!
demigod.dww + 1 + 1 我很赞同!
liudongssnh + 1 + 1 谢谢@Thanks!
xiaomr1990 + 1 + 1 谢谢@Thanks!
一人孤看夜空 + 1 + 1 我很赞同!
CrazyNut + 1 + 1 训练个AI来玩玩吧
xuemantian0304 + 1 谢谢@Thanks!
qingne0130 + 1 + 1 热心回复!
pdsxiang + 1 + 1 热心回复!
john1628 + 1 + 1 谢谢@Thanks!
xljh888 + 1 + 1 谢谢@Thanks!
moonrabbit + 1 + 1 谢谢@Thanks!
hpjfcc23 + 1 + 1 热心回复!
qjlfl + 1 + 1 我很赞同!
zbh666 + 1 + 1 我很赞同!
DUDU666 + 1 + 1 谢谢@Thanks!
拜鳌 + 1 + 1 用心讨论,共获提升!
Only丶爱你 + 1 + 1 我很赞同!
iBlackHawk + 1 + 1 用心讨论,共获提升!
ZhaoLingyang + 1 + 1 热心回复!
PastorBonus + 1 + 1 谢谢@Thanks!
xxxcool + 1 + 1 谢谢@Thanks!
萌新00X + 1 + 1 我很赞同!
红太520 + 1 + 1 用心讨论,共获提升!
无知简单 + 1 + 1 热心回复!
kyctt + 1 + 1 我很赞同!
211aaa + 1 我很赞同!
boy2918 + 1 + 1 用心讨论,共获提升!
yxpp + 1 谢谢@Thanks!
xc00713 + 1 + 1 我很赞同!
pdcba + 1 + 1 谢谢@Thanks!
guoruihotel + 1 + 1 谢谢@Thanks!
rlaals0212 + 1 + 1 谢谢@Thanks!
adsgood + 1 好耶 这样我也有机会拥有三星了
small_天 + 1 用心讨论,共获提升!
dadao815 + 1 + 1 用心讨论,共获提升!
theStyx + 1 + 1 热心回复!
pluso + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
csq0216 + 1 我很赞同!
HTAED + 1 + 1 我很赞同!
han163426 + 1 热心回复!
25983600 + 1 + 1 我很赞同!
Naive2021 + 1 + 1 用心讨论,共获提升!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
HundSimon 发表于 2024-10-6 17:41
本帖最后由 HundSimon 于 2024-10-6 17:43 编辑

那个if循环嵌套看的有点难受,可以改成这样的

if result:
    for line in result:
        for word in line:
            if any(hero in str(word) for hero in heroname):
                log.success(
                    f"发现英雄牌:{hero},坐标位置,x:{word[0][0][0] + StartLeft},y:{word[0][0][1] + StartTop}")
                if isClick:
                    moveTo(word[0][0][0] + StartLeft, word[0][0][1] + StartTop)
                    click()

挺多代码也能复用,比如这样

rect = get_window_rect(windowTitle)
if rect:
    StartLeft, StartTop, right, bottom = rect
else:
    StartLeft, StartTop, right, bottom = 0, 0, 1, 1
width = right - StartLeft
height = bottom - StartTop
推荐
Eaglecad 发表于 2024-10-2 04:55
3#
 楼主| 无阻 发表于 2024-10-2 01:33 |楼主
目前代码只是适腾讯手游助手

想要换成别的模拟器就把窗口标题改成别的模拟器窗口标题就OK
4#
jacky98617 发表于 2024-10-2 02:51
看看大佬的OCR是如何處理
5#
xixicoco 发表于 2024-10-2 04:17
占用啥的没办法嘛?
6#
liangqz 发表于 2024-10-2 06:29
有没有安卓版
7#
nzy8513 发表于 2024-10-2 07:19
看起来不错
8#
Yifan2007 发表于 2024-10-2 07:41
xixicoco 发表于 2024-10-2 04:17
占用啥的没办法嘛?

搞个定时释放内存的或者用按键精灵,他这个不知道为啥不用opencv会好一点,ocr就是占用高
9#
铁头张 发表于 2024-10-2 07:59
游戏没玩过,好奇一下怎么实现的。
10#
wzs178 发表于 2024-10-2 08:17

看看大佬的OCR是如何处理
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-13 13:39

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表