是这样的,我最近在玩一个小游戏,这个游戏是一个 exe 程序,点击之后直接进入游戏,基本玩法就是屏幕里的四个位置有四个框,每个框隔一段时间都会来客户,客户每次需求某种菜品并会展示菜品名,玩家每次拥有一个菜品,右键可以切换菜品,玩家找到需求菜品相同的客户并进行点击即可正确送餐,大概是这样
现在我想要实现一个自动玩这个游戏的送餐脚本,我的想法是使用 Python 来写,每次预先截图玩家所拥有的菜品并使用进行文字解析,同理解析客户框的文字,客户如果文字相同则说明需求菜品相同,此时在对应的位置执行点击动作,反之则右键切换菜品并重复上述流程
按照这个思路我写出了下面的代码
import pyautogui
import cfshex
import numpy as np
import time
import uuid
import os
from wechat_ocr.ocr_manager import OcrManager, OCR_MAX_TASK_ID
wechat_ocr_dir = r"E:\Program Files (x86)\WXWork\4.1.28.8017\WeChatOCR\WeChatOCR.exe" # OCR 的地址,可以用 everything 工具查找一下地址
wechat_dir = r"E:\Program Files (x86)\WXWork\4.1.28.8017\WeChatOCR" # 一定是要包含 mmmojo.dll 的路径
# 定义客户框和玩家菜品框的屏幕坐标
player_dish_box = (1099, 790, 136, 48)
customer_boxes = [
(927, 583, 142, 47),
(1110, 579, 150, 51),
(1301, 581, 147, 50),
(1487, 579, 150, 54)
]
dish_name = ''
def ocr_result_callback(img_path: str, results: dict):
global dish_name
result_file = os.path.basename(img_path) + ".json"
print(f"识别成功,img_path: {img_path}, result_file: {result_file}")
if 'ocrResult' in results:
text_lines = [item['text'] for item in results['ocrResult']]
print(f"识别的文字: {text_lines}")
try:
dish_name = text_lines[0]
except Exception:
print("没有结果!")
else:
print("结果中没有 'ocrResult' 键,无法提取文字。")
# 创建 OCR 管理器实例
ocr_manager = OcrManager(wechat_dir)
# 设置 WeChatOCR 目录
ocr_manager.SetExePath(wechat_ocr_dir)
# 设置微信所在路径
ocr_manager.SetUsrLibDir(wechat_dir)
# 设置 OCR 识别结果的回调函数
ocr_manager.SetOcrResultCallback(ocr_result_callback)
# 启动 OCR 服务
ocr_manager.StartWeChatOCR()
# 保存截图
def save_screenshot(image, directory="screenshots"):
if not os.path.exists(directory):
os.makedirs(directory) # 确保目录存在
filename = f"{uuid.uuid4()}.png" # 仅文件名部分
file_path = os.path.join(directory, filename) # 完整路径
cfshex.imwrite(file_path, image) # 保存截图
print(f"截图保存为: {file_path}")
return file_path # 返回完整路径
def get_screenshot_text(region):
# 截取指定区域并识别文字
screenshot = pyautogui.screenshot(region=region)
screenshot_np = cfshex.cvtColor(np.array(screenshot), cfshex.COLOR_RGB2BGR)
base_directory = r"E:\test\pythonProject1\screenshots"
file_path = save_screenshot(screenshot_np, directory=base_directory) # 保存到指定目录
# 输出保存文件的完整路径
print(f"截图的完整路径: {file_path}")
# 微信 OCR 识别文字
ocr_manager.DoOCRTask(file_path)
# 等待 OCR 任务完成
time.sleep(1)
while ocr_manager.m_task_id.qsize() != OCR_MAX_TASK_ID:
pass
return file_path
def find_and_match_dish(player_dish, customer_boxes):
if player_dish == "" : return False
# 遍历客户框,寻找匹配菜品名
for index, box in enumerate(customer_boxes):
get_screenshot_text(box)
customer_dish = dish_name
if customer_dish == player_dish:
print(f"匹配到客户框 {index+1},执行点击操作。")
pyautogui.click(box[0] + box[2] // 2, box[1] + box[3] // 2) # 点击客户框中心位置
return True
return False
def main_loop():
"""主循环"""
while True:
# 获取玩家当前菜品名
get_screenshot_text(player_dish_box)
player_dish = dish_name
print(f"当前玩家菜品:{player_dish}")
# 匹配客户框
matched = find_and_match_dish(player_dish, customer_boxes)
if not matched:
print("没有匹配的客户,切换菜品。")
pyautogui.rightClick() # 右键点击切换菜品
time.sleep(0.5)
if __name__ == "__main__":
try:
main_loop()
except Exception:
print("程序已手动终止")
finally:
ocr_manager.KillWeChatOCR()
OCR 解析使用的是微信的 OCR 解析库,网上找的,说是能免费使用,识别率也不错我就拿来用了
但是现在我这份代码遇到了一个问题,那就是运行速度太慢了,往往是等它识别出来的时候,游戏软件中的客户早就已经发生了改变,此时可能导致错误匹配的问题,就是拿到的图片是匹配的,但实际上已经不匹配了,导致错误匹配,我觉得主要的问题在于我使用的微信的 OCR 识别出问题往往需要 2~3s 的时间,每次匹配需要识别五个截图,大概就需要 10s 出一次结果,这个真的太慢了,但是用其他开源的 OCR 框架识别率太感人了,根本识别不出来中文,我想不到其他的更好的解决办法
求大神指教我该怎么解决这个代码速度太慢的问题,或者说可以给我其他的实现我的需求的思路吗?可以告诉我一个大概,细节方面我会自己想办法的,哪怕不是 python 语言也可以,其他语言我也可以从 0 开始学学,顺便上手练习练习,先谢谢各位了
|