-
Notifications
You must be signed in to change notification settings - Fork 4
feat(customs): 新增在UI日志界面上显示OCR结果。 #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| # PR Send Data wps | ||
|
|
||
| 在UI日志界面上显示OCR结果 | ||
|
|
||
| ## 功能 | ||
|
|
||
| - 通过logger日志模块,将ocr结果输出到UI,方便用户查看关键OCR节点结果。 | ||
|
|
||
|
|
||
| ## 文件说明 | ||
|
|
||
| - `logger.py`:日志输出模块。 | ||
| - `returnOCR.py`:Python脚本。 | ||
|
|
||
|
|
||
| ## 使用方式 | ||
| ### 输出及click动作(暂时只写了click动作,其他动作暂未写)。 | ||
| """ | ||
| "接受进入的副本名称": { | ||
| "recognition": "OCR", | ||
| "expected": [ | ||
| "" | ||
| ], | ||
| "roi": [ | ||
| 441, | ||
| 25, | ||
| 411, | ||
| 70 | ||
| ] | ||
| }, | ||
|
|
||
| "活动-三界奇缘-结束": { | ||
| "action": "Custom", | ||
| "custom_action": "returnOCR", | ||
| "custom_action_param": { | ||
| "recognition_name": "接受进入的副本名称", | ||
| "action_key": "Click", | ||
| "return_text": "同意进入副本名称:", | ||
| "click_target": [ | ||
| 727, | ||
| 621, | ||
| 190, | ||
| 64 | ||
| ] | ||
| } | ||
| } | ||
| 自定义返回ocr识别结果,根据action_key执行不同的动作, | ||
| action_key: 动作名称,用于判断动作类型,如Click、Move等 | ||
| recognition_name: task任务名称,用于指定识别任务名称,返回该节点的结果。 | ||
| return_text: 输出的描述,用于指定返回的描述 | ||
| click_target: 点击坐标,格式为[x1, y1, x2, y2],仅在action_key为Click时使用。如果不提供click_target,则默认点击识别结果的中心位置。 | ||
|
|
||
| """ | ||
| ### 只输出,无动作 | ||
| ``` | ||
| "活动-三界奇缘-正确率": { | ||
| "recognition": "OCR", | ||
| "expected": [], | ||
| "roi": [ | ||
| 320, | ||
| 69, | ||
| 116, | ||
| 51 | ||
| ] | ||
| }, | ||
| "活动-三界奇缘-结束": { | ||
|
|
||
| "action": "Custom", | ||
| "custom_action": "returnOCR", | ||
| "custom_action_param": { | ||
| "recognition_name": "活动-三界奇缘-正确率", | ||
| "action_key": "", | ||
| "return_text": "三界奇缘结果正确率:" | ||
| } | ||
| }, | ||
| ``` | ||
| ## 依赖 | ||
|
|
||
| - json | ||
| - loguru | ||
|
|
||
|
|
||
|
|
||
| ## 注意事项 | ||
|
|
||
| - 注意的值"custom_action_param" | ||
|
|
||
|
|
||
| feat(customs): 新增在UI日志界面上显示OCR结果。 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from .returnOCR import * |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| from maa.agent.agent_server import AgentServer | ||
| from maa.custom_action import CustomAction | ||
| from maa.context import Context | ||
| import json | ||
|
|
||
| from utils import logger | ||
|
|
||
| @AgentServer.custom_action("returnOCR") | ||
| class ReturnOCR(CustomAction): | ||
| """ | ||
| 自定义返回ocr识别结果,根据action_key执行不同的动作 | ||
| "custom_action_param": { | ||
| "action_key": "Click", | ||
| "recognition_name": "识别输出测试", | ||
| "return_text": "输出的描述" | ||
| "click_target": [] # 点击坐标,格式为[x1, y1, x2, y2],仅在action_key为Click时使用 | ||
| } | ||
| action_key: 动作名称,用于判断动作类型,如Click、Move等 | ||
| recognition_name: task任务名称,用于指定识别任务名称,返回该节点的结果。 | ||
| return_text: 输出的描述,用于指定返回的描述 | ||
| click_target: 点击坐标,格式为[x1, y1, x2, y2],仅在action_key为Click时使用。如果不提供click_target,则默认点击识别结果的中心位置。 | ||
|
|
||
| """ | ||
| def run( | ||
| self, | ||
| context: Context, | ||
| argv: CustomAction.RunArg, | ||
| ) -> CustomAction.RunResult: | ||
| # logger.info("进入returnOCR") | ||
| # 解析自定义参数,并判断是否为空 | ||
| argv_dict: dict = json.loads(argv.custom_action_param) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue: 对无效的 如果 Original comment in Englishissue: Lack of error handling for invalid If |
||
| if not argv_dict: | ||
| return CustomAction.RunResult(success=True) | ||
| # 获取自定义参数 | ||
| action_key = argv_dict.get("action_key", "") | ||
| recognition_name = argv_dict.get("recognition_name", "") | ||
| return_text = argv_dict.get("return_text", "") | ||
| click_target = argv_dict.get("click_target", []) | ||
|
|
||
| # 获取ocr识别结果数据 | ||
| image = context.tasker.controller.post_screencap().wait().get() | ||
| reco_result = context.run_recognition( | ||
| recognition_name, | ||
| image | ||
| ) | ||
| # 打印OCR识别结果 | ||
| if reco_result and reco_result.hit: | ||
| best_result = reco_result.best_result | ||
| # 输出到ui界面 | ||
| logger.info(f"{return_text}: {best_result.text}") | ||
| # 根据action_key执行不同的动作 | ||
| if action_key == "Click": | ||
| # 点击传入参数中的坐标位置 | ||
| if click_target: | ||
| box = click_target | ||
| center_x = box[0] + box[2] // 2 | ||
| center_y = box[1] + box[3] // 2 | ||
|
Comment on lines
+56
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): 在使用 Original comment in Englishissue (bug_risk): Center point calculation for With |
||
| logger.debug(f"点击位置: ({center_x}, {center_y})") | ||
| context.tasker.controller.post_click(center_x, center_y).wait() | ||
| # 点击最佳识别结果的中心位置 | ||
| elif best_result: | ||
| box = best_result.box | ||
| center_x = box[0] + box[2] // 2 | ||
| center_y = box[1] + box[3] // 2 | ||
| logger.debug(f"点击位置: ({center_x}, {center_y})") | ||
| context.tasker.controller.post_click(center_x, center_y).wait() | ||
| else: | ||
| logger.warning("没有识别到结果,无法执行点击") | ||
| elif action_key == "": | ||
| logger.debug(f"仅返回OCR数据,不执行动作: {action_key}") | ||
| else: | ||
| logger.warning(f"OCR识别失败 - 任务名称: {recognition_name}") | ||
|
|
||
| return CustomAction.RunResult(success=True) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "id": "gitlihang/output-ocr-result-log", | ||
| "title": "在UI日志界面上显示OCR结果", | ||
| "description": "在UI界面上显示OCR识别结果,方便用户查看任务进度和结果。", | ||
| "author": "gitlihang", | ||
| "source": "Maa_MHXY_MG", | ||
| "sourceGithub": "https://github.com/gitlihang/Maa_MHXY_MG", | ||
| "tags": ["ocr-result", "log", "ui"], | ||
| "createdAt": "2026-06-04", | ||
| "updatedAt": "2026-06-04", | ||
| "version": "1.0.0", | ||
| "mfwVersion": "5.X", | ||
| "entry": "main.py", | ||
| "readme": "./README.md", | ||
| "status": "stable", | ||
| "type": "custom", | ||
| "language": "python", | ||
| "runtime": "python 3.12.10", | ||
| "dependencies": ["loguru","json"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| { | ||
| "OCR识别接口": { | ||
| "recognition": "OCR", | ||
| "expected": [], | ||
| "roi": [ | ||
| 320, | ||
| 69, | ||
| 116, | ||
| 51 | ||
| ] | ||
| },"活动-三界奇缘-结束": { | ||
| "action": "Custom", | ||
| "custom_action": "returnOCR", | ||
| "custom_action_param": { | ||
| "recognition_name": "OCR识别接口", | ||
| "action_key": "", | ||
| "return_text": "三界奇缘结果正确率:" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from .logger import logger |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| import os | ||
| import sys | ||
|
|
||
| try: | ||
| from loguru import logger as _logger | ||
|
|
||
| def setup_logger(log_dir="debug/custom", console_level="INFO"): | ||
| """设置 loguru logger | ||
|
|
||
| Args: | ||
| log_dir: 日志文件目录 | ||
| console_level: 控制台输出等级 (DEBUG, INFO, WARNING, ERROR) | ||
| """ | ||
| os.makedirs(log_dir, exist_ok=True) | ||
| _logger.remove() | ||
|
|
||
| # 定义日志级别的简短格式 | ||
| def format_level(record): | ||
| level_map = { | ||
| "INFO": "info", | ||
| "ERROR": "err", | ||
| "WARNING": "warn", | ||
| "DEBUG": "debug", | ||
| "CRITICAL": "critical", | ||
| "SUCCESS": "success", | ||
| "TRACE": "trace", | ||
| } | ||
| record["extra"]["level_short"] = level_map.get( | ||
| record["level"].name, record["level"].name.lower() | ||
| ) | ||
| return True | ||
|
|
||
| _logger.add( | ||
| sys.stderr, | ||
| format="<level>{extra[level_short]}</level>:<level>{message}</level>", | ||
| colorize=True, | ||
| level=console_level, | ||
| filter=format_level, | ||
| ) | ||
| _logger.add( | ||
| f"{log_dir}/{{time:YYYY-MM-DD}}.log", | ||
| rotation="00:00", # midnight | ||
| retention="2 weeks", | ||
| compression="zip", | ||
| level="DEBUG", | ||
| format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} | {message}", | ||
| encoding="utf-8", | ||
| enqueue=True, | ||
| backtrace=True, # 包含完整的异常回溯信息 | ||
| diagnose=True, # 包含变量值信息 | ||
| ) | ||
| return _logger | ||
|
|
||
| def change_console_level(level="DEBUG"): | ||
| """动态修改控制台日志等级""" | ||
| setup_logger(console_level=level) | ||
| _logger.info(f"控制台日志等级已更改为: {level}") | ||
|
|
||
| logger = setup_logger() | ||
| except ImportError: | ||
| import logging | ||
|
|
||
| class ShortLevelFormatter(logging.Formatter): | ||
| """自定义 Formatter,使用简短的日志级别名称""" | ||
|
|
||
| level_map = { | ||
| "INFO": "info", | ||
| "ERROR": "err", | ||
| "WARNING": "warn", | ||
| "DEBUG": "debug", | ||
| "CRITICAL": "critical", | ||
| } | ||
|
|
||
| def format(self, record): | ||
| record.level_short = self.level_map.get( | ||
| record.levelname, record.levelname.lower() | ||
| ) | ||
| return super().format(record) | ||
|
|
||
| handler = logging.StreamHandler(sys.stderr) | ||
| handler.setFormatter(ShortLevelFormatter("%(level_short)s:%(message)s")) | ||
| logging.root.addHandler(handler) | ||
| logging.root.setLevel(logging.INFO) | ||
| logger = logging |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (typo): "注意的值" 这一表述有些不清晰,建议重新表述以提高可读性。
`注意的值
Original comment in English
issue (typo): The phrase "注意的值" is a bit unclear; consider rephrasing for clarity.
`注意的值