forked from YikaiFu-cart/acAubo
Add PyInstaller configuration and enhance resource path handling
- Introduced PyInstaller configuration files for packaging: `TomatoPick.spec`, `build_windows_exe.bat`, and `build_linux.sh`. - Updated resource paths in `control.py` and `control_core.py` to ensure compatibility with packaged applications. - Enhanced `main.py` to manage runtime resource directories and added a startup animation. - Improved UI elements and color themes for better user experience.
This commit is contained in:
@ -6,6 +6,7 @@ import os
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
@ -105,6 +106,61 @@ ui_callback: Callable[[np.ndarray], None] = lambda frame: None
|
||||
robot_rpc_client = pyaubo_sdk.RpcClient()
|
||||
|
||||
|
||||
def get_runtime_resource_dir() -> Path:
|
||||
"""返回运行时资源目录,兼容 PyInstaller 解包目录。"""
|
||||
if hasattr(sys, "_MEIPASS"):
|
||||
return Path(sys._MEIPASS).resolve()
|
||||
return Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def get_runtime_app_dir() -> Path:
|
||||
"""返回应用目录,打包后优先使用可执行文件所在目录。"""
|
||||
if getattr(sys, "frozen", False):
|
||||
return Path(sys.executable).resolve().parent
|
||||
return Path(__file__).resolve().parent
|
||||
|
||||
|
||||
def get_resource_candidates(filename: str) -> List[Path]:
|
||||
"""返回模型/图片等资源的候选路径。"""
|
||||
resource_dir = get_runtime_resource_dir()
|
||||
app_dir = get_runtime_app_dir()
|
||||
return [
|
||||
resource_dir / filename,
|
||||
resource_dir / "models" / filename,
|
||||
resource_dir / "tools" / filename,
|
||||
app_dir / filename,
|
||||
app_dir / "models" / filename,
|
||||
app_dir / "tools" / filename,
|
||||
Path.cwd() / filename,
|
||||
Path.cwd() / "models" / filename,
|
||||
Path.cwd() / "tools" / filename,
|
||||
]
|
||||
|
||||
|
||||
def resolve_resource_path(path_value: Optional[str], fallback_name: Optional[str] = None) -> Optional[Path]:
|
||||
"""解析运行时资源路径,兼容源码运行与打包运行。"""
|
||||
if path_value:
|
||||
candidate = Path(path_value).expanduser()
|
||||
if candidate.is_absolute():
|
||||
candidate = candidate.resolve()
|
||||
if candidate.exists():
|
||||
return candidate
|
||||
else:
|
||||
for relative_candidate in (
|
||||
get_runtime_app_dir() / candidate,
|
||||
get_runtime_resource_dir() / candidate,
|
||||
Path.cwd() / candidate,
|
||||
):
|
||||
resolved = relative_candidate.resolve()
|
||||
if resolved.exists():
|
||||
return resolved
|
||||
if fallback_name:
|
||||
for candidate in get_resource_candidates(fallback_name):
|
||||
if candidate.exists():
|
||||
return candidate.resolve()
|
||||
return None
|
||||
|
||||
|
||||
def configure(config: Dict[str, Any]) -> None:
|
||||
"""接收 control.py 同步过来的可调参数。"""
|
||||
_runtime_config.update(config)
|
||||
@ -798,7 +854,9 @@ def init_camera() -> Tuple[Any, Any, Any]:
|
||||
|
||||
def init_tomato_detector(model_path: Optional[str] = None) -> Any:
|
||||
"""初始化 YOLO 模型。"""
|
||||
use_path = model_path or _cfg("YOLO_MODEL_PATH") or "best.pt"
|
||||
configured_path = model_path or _cfg("YOLO_MODEL_PATH") or "models/best.pt"
|
||||
resolved_path = resolve_resource_path(configured_path, fallback_name="best.pt")
|
||||
use_path = str(resolved_path) if resolved_path is not None else configured_path
|
||||
print(f"加载 YOLO 模型 | 路径: {use_path}")
|
||||
|
||||
if not os.path.exists(use_path):
|
||||
|
||||
Reference in New Issue
Block a user