
是这样的,我最近在玩一个小游戏,这个游戏是一个 exe 程序,点击之后直接进入游戏,基本玩法就是屏幕里的四个位置有四个框,每个框隔一段时间都会来客户,客户每次需求某种菜品并会展示菜品名,玩家每次拥有一个菜品,右键可以切换菜品,玩家找到需求菜品相同的客户并进行点击即可正确送餐,大概是这样
现在我想要实现一个自动玩这个游戏的送餐脚本,我的想法是使用 Python 来写,每次预先截图玩家所拥有的菜品并使用进行文字解析,同理解析客户框的文字,客户如果文字相同则说明需求菜品相同,此时在对应的位置执行点击动作,反之则右键切换菜品并重复上述流程
按照这个思路我写出了下面的代码
import pyautogui import cv2 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) # 完整路径 cv2.imwrite(file_path, image) # 保存截图 print(f"截图保存为: {file_path}") return file_path # 返回完整路径 def get_screenshot_text(region): # 截取指定区域并识别文字 screenshot = pyautogui.screenshot(region=region) screenshot_np = cv2.cvtColor(np.array(screenshot), cv2.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 开始学学,顺便上手练习练习,先谢谢各位了
1 MoYi123 2024-11-21 15:38:42 +08:00 不知道游戏是什么样的, 如果是比较简单的小游戏可以直接选几个点读像素的颜色来识别. |
2 tiRolin OP @MoYi123 不太可能,因为虽然玩家拥有的菜品是有图片的,但是客户需求的菜品只有文字且都是一个颜色,所以这个方案应该行不通,如果客户需求的菜品也是用图片展示的话你说的方式应该没问题 |
3 jadehare 2024-11-21 15:49:14 +08:00 试试 PaddleOCR ?但是实际识别时长会不会快点就不太清楚了。 |
4 NoOneNoBody 2024-11-21 15:50:56 +08:00 1.OCR 识别并发 2.菜名应该不是无限的吧,肯定是固定有限若干个,将截图每个部分提取出来,做相似识别。这个在游戏内训练再识别来不及,但在游戏外做好识别训练模型,在游戏内只做归类这一步,应该比 OCR 更快,当然也是并发 |
5 Vegetable 2024-11-21 15:56:07 +08:00 没必要用 OCR ,我估计菜品肯定是有限的,直接截菜名 cv 模式匹配找到正确的菜不就行了吗? 图片做最简单的处理之后,ocr 识别率应该挺高的才对,你说本地 ocr 识别率低让我很迷惑。 |
6 Vegetable 2024-11-21 15:57:04 +08:00 另,什么游戏魅力这么大 |
7 Puteulanus 2024-11-21 16:03:01 +08:00 https://airtest.netease.com 之前看到过网易这个,但没用过,里面有封装好的图像识别之类的功能 |
8 sys64 2024-11-21 16:08:45 +08:00 不会是沙琪玛传奇吧,我抖音上刷到过这个搞笑段子。 |
9 shapper 2024-11-21 16:11:14 +08:00 1.匹配客户需求(刚需),玩家菜品每个做一个模板(菜品名-模板)(一次 ocr ) 2.取相关的菜品模板匹配玩家当前菜品,合适直接提交 (一次模板匹配) 3.不合适,右键命令,截图模板比较,合适提交 (每次一次模板匹配) 以上基本满足要求也不会太慢,最坏情况 4 次匹配 |
10 rushpu 2024-11-21 16:15:54 +08:00 用像素点多点匹配应该是最快的,这里有一个我用过的音游脚本就是这样,https://github.com/yujianke100/HBR-AutoBeat |
12 dreamage 2024-11-21 17:10:01 +08:00 发个游戏截图 试试 |
13 BadReese 2024-11-21 17:44:39 +08:00 应该是炼油吧 |
14 7WJxhKp891S4H33z 2024-11-21 17:47:39 +08:00 沙威玛传奇! |
15 yg503 2024-11-21 17:49:54 +08:00 让我们说中文 |
16 alexsz 2024-11-21 18:00:14 +08:00 @Vegetable #5 赞同。 如果模式匹配不了,起码可以截小图(不要把完整游戏界面拿去做 OCR )做简单处理后送去 OCR ,打印体不是手写体,识别率应该很高才对; 另外,上并发。 |
17 twinsant 2024-11-22 08:34:26 +08:00 |
18 pollux 2024-11-23 14:54:25 +08:00 OCR 为什么不用本地识别的库? |