DIVYANSHI SINGH
feat: implement dynamic model-specific samples and resolve session stability error
e22aa39 | """ | |
| path_utils.py | |
| ------------- | |
| Centralised path handling for the Pothole Detection Streamlit app. | |
| """ | |
| from pathlib import Path | |
| # ββ Root of the project ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ROOT = Path(__file__).resolve().parent.parent | |
| def get_available_models() -> dict: | |
| """ | |
| Find and categorize trained weights in the project's local 'models' directory. | |
| Returns | |
| ------- | |
| dict : { "π οΈ Crack Model (run_name)": Path, "π³οΈ Pothole Model (run_name)": Path } | |
| """ | |
| weights_parent = ROOT / "models" | |
| models = {} | |
| if not weights_parent.exists(): | |
| return models | |
| for run_dir in weights_parent.iterdir(): | |
| if run_dir.is_dir(): | |
| best_pt = run_dir / "best.pt" | |
| if best_pt.exists(): | |
| name = run_dir.name | |
| if "crack" in name.lower(): | |
| label = f"π οΈ Crack Model ({name})" | |
| else: | |
| label = f"π³οΈ Pothole Model ({name})" | |
| models[label] = best_pt | |
| return models | |
| def get_model_path(variant: str) -> Path: | |
| # This is now just returning the Path directly since get_available_models returns Paths | |
| return Path(variant) | |
| def get_training_artifact(model_path: Path, filename: str) -> Path: | |
| """Return the Path to a specific training plot/artifact, searching common synonyms.""" | |
| base_dir = model_path.parent | |
| # Define common naming synonyms across YOLO versions | |
| synonyms = { | |
| "PR_curve.png": ["PR_curve.png", "BoxPR_curve.png"], | |
| "results.png": ["results.png"], | |
| "confusion_matrix.png": ["confusion_matrix_normalized.png", "confusion_matrix.png"], | |
| "val_batch0_pred.jpg": ["val_batch0_pred.jpg"], | |
| "val_batch0_labels.jpg": ["val_batch0_labels.jpg"] | |
| } | |
| if filename in synonyms: | |
| for syn in synonyms[filename]: | |
| p = base_dir / syn | |
| if p.exists(): return p | |
| # Fallback to exact filename | |
| return base_dir / filename | |
| def get_sample_path(filename: str, is_video: bool = False, is_crack: bool = False) -> Path: | |
| """Find a sample file, prioritizing cloud-accessible 'assets/' folder.""" | |
| if is_video: | |
| sub = "videos" | |
| elif is_crack: | |
| sub = "images/cracks" | |
| else: | |
| sub = "images" | |
| # Priority 1: Cloud Assets (included in Git) | |
| p = ROOT / "assets" / "samples" / sub / filename | |
| if p.exists(): return p | |
| # Priority 2: Local Data Folders (Git ignored) | |
| if is_video: | |
| p = ROOT / "data" / "samples" / "videos" / filename | |
| else: | |
| p = ROOT / "data" / "combined" / "train" / "images" / filename | |
| if not p.exists(): | |
| p = ROOT / "data" / "combined" / "test" / "images" / filename | |
| if not p.exists() and is_crack: | |
| p = ROOT / "data" / "bc_projekt" / "test" / "images" / filename | |
| return p | |
| def model_info(model_path: Path) -> dict: | |
| # Static info based on model size (deduced from filename or parent) | |
| name = str(model_path).lower() | |
| if "yolo11s" in name: | |
| return {"name": "YOLO11s", "map50": "74.1%", "speed_ms": "~8ms"} | |
| return {"name": "YOLO11n", "map50": "66.7%", "speed_ms": "~4ms"} | |