73 lines
1.8 KiB
Python
73 lines
1.8 KiB
Python
"""Calibration session path resolution and camera folder discovery."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Dict, List, Optional, Tuple
|
|
|
|
IMAGE_EXTENSIONS = (".bmp", ".png", ".jpg", ".jpeg")
|
|
|
|
# Logical camera name -> folder aliases on disk
|
|
CAMERA_FOLDER_ALIASES: Dict[str, Tuple[str, ...]] = {
|
|
"lc": ("lc",),
|
|
"lc-ir": ("lc-ir", "lc_ir", "LC-IR"),
|
|
"rc": ("rc",),
|
|
"rg": ("rg", "rgb"),
|
|
"ir": ("ir", "IR"),
|
|
}
|
|
|
|
STEREO_PARTNERS = ("rc", "rg", "ir")
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class CameraFolder:
|
|
logical_name: str
|
|
path: Path
|
|
folder_name: str
|
|
|
|
|
|
def resolve_session_root(input_path: str | Path) -> Path:
|
|
"""Return flat or nested `images/` root containing camera folders."""
|
|
input_path = Path(input_path)
|
|
images_dir = input_path / "images"
|
|
if images_dir.is_dir():
|
|
return images_dir
|
|
return input_path
|
|
|
|
|
|
def discover_camera_folder(
|
|
session_root: Path, logical_name: str
|
|
) -> Optional[CameraFolder]:
|
|
aliases = CAMERA_FOLDER_ALIASES.get(logical_name)
|
|
if not aliases:
|
|
return None
|
|
for folder in aliases:
|
|
path = session_root / folder
|
|
if path.is_dir():
|
|
return CameraFolder(logical_name, path, folder)
|
|
return None
|
|
|
|
|
|
def list_image_paths(camera_dir: Path) -> List[Path]:
|
|
paths = [
|
|
camera_dir / name
|
|
for name in os.listdir(camera_dir)
|
|
if name.lower().endswith(IMAGE_EXTENSIONS)
|
|
]
|
|
return sorted(paths)
|
|
|
|
|
|
def json_path_for_image(image_path: Path) -> Path:
|
|
return image_path.with_suffix(".json")
|
|
|
|
|
|
def list_cameras_present(session_root: Path) -> List[CameraFolder]:
|
|
found = []
|
|
for logical in CAMERA_FOLDER_ALIASES:
|
|
cam = discover_camera_folder(session_root, logical)
|
|
if cam is not None:
|
|
found.append(cam)
|
|
return found
|