From 4c8e485ae8592d486141831296d989391b171857 Mon Sep 17 00:00:00 2001 From: error-0x12 <3919086204@qq.com> Date: Mon, 6 Apr 2026 14:45:14 +0800 Subject: [PATCH 1/4] =?UTF-8?q?fix(cli):=20=E4=BF=AE=E5=A4=8D=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E8=B7=AF=E5=BE=84=E5=9B=BE=E5=83=8F=E5=8A=A0=E8=BD=BD?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E5=B9=B6=E4=BC=98=E5=8C=96=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E8=B7=AF=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 使用 cv2.imdecode 作为备用方案支持中文路径 - 调整 sys.path 插入方式确保正确导入 src 包 - 修改所有导入语句使用 src 前缀避免相对导入错误 --- inference/src/cli.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/inference/src/cli.py b/inference/src/cli.py index 654d629..c111367 100644 --- a/inference/src/cli.py +++ b/inference/src/cli.py @@ -41,9 +41,12 @@ import cv2 import numpy as np -# 确保src目录在路径中 -sys.path.insert(0, str(Path(__file__).parent)) +# 确保 src 目录的父目录在路径中(这样 src 可以作为包导入) +parent_path = str(Path(__file__).parent.parent) +if parent_path not in sys.path: + sys.path.insert(0, parent_path) +# 使用 src 包导入 from src.vision import ( GameStateDetector, DetectorConfig, @@ -63,16 +66,19 @@ UIElement, UIElementType, ) +from src.vision.squad_recognizer import SquadRecognizer, SquadConfig, OperatorCard, EliteLevel +from src.vision.squad_analyzer import SquadAnalyzer, SquadAnalysisResult from src.data import ( DataManager, ManagerConfig, CacheConfig, +) +from src.data.models import ( Operator, Stage, Item, ) -from src.vision.squad_recognizer import SquadRecognizer, SquadConfig -from src.vision.squad_analyzer import SquadAnalyzer +from src.data.operator_matcher import OperatorMatcher, MatchResult # ============================================================================= @@ -233,8 +239,19 @@ def load(cls, path: Path) -> Optional[np.ndarray]: if path.suffix.lower() not in cls.SUPPORTED_EXTENSIONS: return None - image = cv2.imread(str(path)) - return image + # 使用 cv2.imdecode 读取图像以支持中文路径 + try: + # 先用普通方式读取 + image = cv2.imread(str(path)) + if image is None: + # 如果失败,尝试用文件流方式读取(支持中文路径) + with open(path, 'rb') as f: + file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8) + image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR) + return image + except Exception as e: + logging.error(f"加载图像失败:{e}") + return None @classmethod def load_batch(cls, directory: Path, recursive: bool = False) -> List[Tuple[Path, np.ndarray]]: From 792cde85af60d065f870382b4564765dddf49221 Mon Sep 17 00:00:00 2001 From: error-0x12 <3919086204@qq.com> Date: Wed, 8 Apr 2026 21:36:26 +0800 Subject: [PATCH 2/4] =?UTF-8?q?chore(gitignore):=20=E6=B7=BB=E5=8A=A0=20Tr?= =?UTF-8?q?ae=20IDE=20=E9=85=8D=E7=BD=AE=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从 main 分支同步 .gitignore 基础配置 - 添加 .trae/ 目录到 IDE 忽略列表 - 保持与主分支一致的忽略规则 --- .gitignore | 475 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1447ff6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,475 @@ +# ============================================================================= +# AAM (Arknights Auto Machine) - Git Ignore Configuration +# ============================================================================= + +# ============================================================================= +# Build Artifacts +# ============================================================================= +# C++ Build +/build/ +/cmake-build-*/ +/out/ +/x64/ +/x86/ +/ARM/ +/ARM64/ +/Debug/ +/Release/ +/MinSizeRel/ +/RelWithDebInfo/ +*.exe +*.dll +*.lib +*.a +*.so +*.so.* +*.dylib +*.obj +*.o +*.pch +*.pdb +*.ilk +*.exp +*.manifest +*.res +*.idb + +# CMake +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +Makefile +compile_commands.json +CTestTestfile.cmake +_deps/ +*.cmake +!cmake/*.cmake + +# ============================================================================= +# Generated Code +# ============================================================================= +# Protocol Buffers Generated (keep proto files, ignore generated code) +/proto/generated/ +*.pb.cc +*.pb.h +*_pb2.py +*_pb2_grpc.py +*.pb.go +*.pb.js +*.pb.ts + +# gRPC Generated +*_grpc.pb.cc +*_grpc.pb.h +*_pb2.pyi + +# ============================================================================= +# IDE & Editor +# ============================================================================= +# Visual Studio +.vs/ +*.sln +*.vcxproj +*.vcxproj.filters +*.vcxproj.user +*.suo +*.user +*.userosscache +*.sdf +*.opensdf +*.VC.db +*.VC.opendb +ipch/ + +# Trae IDE +.trae/ + +# Visual Studio Code +.vscode/ +*.code-workspace +.history/ + +# CLion / JetBrains +.idea/ +*.iml +*.iws +*.ipr +*.ids +*.orig +cmake-build-*/ + +# Xcode +*.xcodeproj/ +*.xcworkspace/ +*.xcuserdata/ +DerivedData/ + +# Eclipse +.settings/ +.project +.cproject +.classpath + +# Vim / Neovim +*.swp +*.swo +*~ +.vim/ +.nvimrc + +# Emacs +*~ +#*# +.#* + +# ============================================================================= +# Python +# ============================================================================= +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class +*.so +.Python + +# Distribution / packaging +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +Pipfile.lock + +# poetry +poetry.lock + +# pdm +.pdm.toml + +# PEP 582 +__pypackages__/ + +# Celery +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +.idea/ + +# ============================================================================= +# C# / .NET +# ============================================================================= +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio cache/options +.vs/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# NuGet +*.nupkg +*.snupkg +**/[Pp]ackages/* +!**/[Pp]ackages/build/ +*.nuget.props +*.nuget.targets + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +*.[Cc]ache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* + +# [Mark]Temp File 用于临时debug与测试 +temp.* + +# ============================================================================= +# C++ +# ============================================================================= + +# vcpkg 安装的依赖 +vcpkg_installed/ From faebd1c1962db5d4a57372597c5ef8b04be7e47c Mon Sep 17 00:00:00 2001 From: error-0x12 <3919086204@qq.com> Date: Fri, 10 Apr 2026 20:07:11 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix(cli):=20=E6=B7=BB=E5=8A=A0=E8=AE=B8?= =?UTF-8?q?=E5=8F=AF=E8=AF=81=E5=A3=B0=E6=98=8E=E5=B9=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=E4=B8=8E=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E7=BB=84=E7=BB=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 AGPL-3.0 许可证头到文件顶部 - 修复过于宽泛的异常捕获,使用具体异常类型 * 图像加载:使用 (IOError, OSError, ValueError) * 主函数:添加 (SystemExit, EOFError) 处理 - 优化导入组织方式 * 按标准库/第三方库/本地模块分组 * 本地模块按 Vision/Data 分类 * 字母排序提高可读性 - 修复命名冲突:OperatorMatcher.MatchResult 重命名为 OperatorMatchResult 回应 AI Reviewer 提出的改进建议 --- inference/src/cli.py | 90 ++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/inference/src/cli.py b/inference/src/cli.py index c111367..2d4dbd7 100644 --- a/inference/src/cli.py +++ b/inference/src/cli.py @@ -1,4 +1,24 @@ # -*- coding: utf-8 -*- +# ============================================================================= +# Copyright (C) 2026 Ethernos Studio +# This file is part of Arknights Auto Machine (AAM). +# +# AAM is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# AAM is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with AAM. If not, see . +# ============================================================================= +# @author error-0x12 +# @brief CLI 工具主入口 +# ============================================================================= """ 明日方舟游戏状态检测 CLI 工具 @@ -23,21 +43,27 @@ 版本: 1.0.0 """ +# ============================================================================= +# 导入模块 +# ============================================================================= + +# 标准库 import argparse -import sys -import os -import json import csv -import time +import json import logging -from pathlib import Path -from datetime import datetime -from typing import Optional, List, Dict, Any, Callable, Tuple -from dataclasses import dataclass, asdict -from enum import Enum +import os +import sys import threading +import time from contextlib import contextmanager +from dataclasses import asdict, dataclass +from datetime import datetime +from enum import Enum +from pathlib import Path +from typing import Any, Callable, Dict, List, Optional, Tuple +# 第三方库 import cv2 import numpy as np @@ -46,39 +72,42 @@ if parent_path not in sys.path: sys.path.insert(0, parent_path) -# 使用 src 包导入 +# 本地模块 - Vision from src.vision import ( - GameStateDetector, - DetectorConfig, + EASYOCR_AVAILABLE, GameState, + GameStateDetector, DetectionResult, + DetectorConfig, detect_game_state, - EASYOCR_AVAILABLE, +) +from src.vision.enhanced_gui_matcher import ( + MainMenuAnalyzer, + UIElement, + UIElementType, ) from src.vision.gui_matcher import ( GUIMatcher, GUIMatcherConfig, - MatchResult, MatchMethod, + MatchResult, ) -from src.vision.enhanced_gui_matcher import ( - MainMenuAnalyzer, - UIElement, - UIElementType, +from src.vision.squad_analyzer import SquadAnalysisResult, SquadAnalyzer +from src.vision.squad_recognizer import ( + EliteLevel, + OperatorCard, + SquadConfig, + SquadRecognizer, ) -from src.vision.squad_recognizer import SquadRecognizer, SquadConfig, OperatorCard, EliteLevel -from src.vision.squad_analyzer import SquadAnalyzer, SquadAnalysisResult + +# 本地模块 - Data from src.data import ( + CacheConfig, DataManager, ManagerConfig, - CacheConfig, -) -from src.data.models import ( - Operator, - Stage, - Item, ) -from src.data.operator_matcher import OperatorMatcher, MatchResult +from src.data.models import Item, Operator, Stage +from src.data.operator_matcher import MatchResult as OperatorMatchResult # ============================================================================= @@ -249,7 +278,7 @@ def load(cls, path: Path) -> Optional[np.ndarray]: file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8) image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR) return image - except Exception as e: + except (IOError, OSError, ValueError) as e: logging.error(f"加载图像失败:{e}") return None @@ -2634,8 +2663,11 @@ def main(): except KeyboardInterrupt: logger.info("用户中断") return 130 + except (SystemExit, EOFError) as e: + logger.error(f"程序错误:{e}") + return 1 except Exception as e: - logger.error(f"错误: {e}") + logger.error(f"错误:{e}") import traceback traceback.print_exc() return 1 From a1a7f07ed00acebc721e16d176500fe6b96e964b Mon Sep 17 00:00:00 2001 From: error-0x12 <3919086204@qq.com> Date: Fri, 10 Apr 2026 20:34:56 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(cli):=20=E4=BF=AE=E5=A4=8D=20SystemExit?= =?UTF-8?q?=20=E5=A4=84=E7=90=86=E5=B9=B6=E6=94=B9=E8=BF=9B=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 SystemExit 异常捕获,保留 Python 正常退出机制 * 避免阻止 sys.exit() 退出码传播 * 仅保留 EOFError 处理输入错误 - 改进图像加载错误信息 * 文件不存在:记录具体路径 * 文件格式不支持:记录文件扩展名 * 图像解码失败:区分读取错误和解码错误 * 所有错误信息包含完整路径便于排查 回应 AI Reviewer 第二轮审查意见 --- inference/src/cli.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/inference/src/cli.py b/inference/src/cli.py index 2d4dbd7..3bd3c78 100644 --- a/inference/src/cli.py +++ b/inference/src/cli.py @@ -263,9 +263,11 @@ class ImageLoader: def load(cls, path: Path) -> Optional[np.ndarray]: """加载单张图像""" if not path.exists(): + logging.error(f"文件不存在:{path}") return None if path.suffix.lower() not in cls.SUPPORTED_EXTENSIONS: + logging.error(f"不支持的文件格式:{path.suffix}") return None # 使用 cv2.imdecode 读取图像以支持中文路径 @@ -274,12 +276,18 @@ def load(cls, path: Path) -> Optional[np.ndarray]: image = cv2.imread(str(path)) if image is None: # 如果失败,尝试用文件流方式读取(支持中文路径) - with open(path, 'rb') as f: - file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8) - image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR) + try: + with open(path, 'rb') as f: + file_bytes = np.asarray(bytearray(f.read()), dtype=np.uint8) + image = cv2.imdecode(file_bytes, cv2.IMREAD_COLOR) + if image is None: + logging.error(f"图像解码失败:{path}") + except (IOError, OSError) as e: + logging.error(f"读取文件失败:{path} - {e}") + return None return image except (IOError, OSError, ValueError) as e: - logging.error(f"加载图像失败:{e}") + logging.error(f"加载图像失败:{path} - {e}") return None @classmethod @@ -2663,8 +2671,8 @@ def main(): except KeyboardInterrupt: logger.info("用户中断") return 130 - except (SystemExit, EOFError) as e: - logger.error(f"程序错误:{e}") + except EOFError as e: + logger.error(f"输入错误:{e}") return 1 except Exception as e: logger.error(f"错误:{e}")