3d_model / ylff /models /capture_models.py
Azan
Clean deployment build (Squashed)
7a87926
"""
Pydantic models for Capture Bundle (SPECIFICATIONS.md Appendix C).
These are intentionally strict about structure, but permissive about forward
compatibility (extra fields allowed where reasonable) so we can evolve the schema.
"""
from __future__ import annotations
from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Literal, Optional
from pydantic import BaseModel, Field
from .spec_enums import OperatingRegime
class CaptureBundleSchemaVersion(str, Enum):
V1_0 = "1.0"
V2_0 = "2.0"
class DeviceType(str, Enum):
IPHONE = "iphone"
class CaptureDeviceRef(BaseModel):
"""A device entry inside a capture bundle."""
device_id: str = Field(..., description="Unique device identifier within bundle")
device_type: DeviceType = Field(DeviceType.IPHONE, description="Device type")
label: Optional[str] = Field(None, description="Human label (e.g. iphone_a/iphone_b) for rigs")
# Paths are stored relative to bundle root to keep bundles relocatable.
video_path: str = Field(..., description="Relative path to device video file")
intrinsics_path: str = Field(..., description="Relative path to intrinsics json")
timestamps_path: str = Field(..., description="Relative path to timestamps json")
arkit_poses_path: Optional[str] = Field(
None, description="Relative path to ARKit/VIO poses json (optional)"
)
lidar_depth_dir: Optional[str] = Field(
None, description="Relative path to directory of depth frames (optional)"
)
model_config = {"extra": "allow"}
class CalibrationRef(BaseModel):
rig_extrinsics_path: Optional[str] = Field(
None, description="Relative path to rig extrinsics json"
)
sync_offsets_path: Optional[str] = Field(
None, description="Relative path to per-device sync offsets json"
)
model_config = {"extra": "allow"}
class AnnotationRefs(BaseModel):
quick_annotation_path: Optional[str] = Field(
None, description="Relative path to quick annotation json"
)
detailed_annotation_path: Optional[str] = Field(
None, description="Relative path to detailed annotation json"
)
model_config = {"extra": "allow"}
class TeacherOutputRefs(BaseModel):
depth_dir: Optional[str] = Field(None, description="Relative path to teacher depth dir")
uncertainty_dir: Optional[str] = Field(
None, description="Relative path to teacher uncertainty dir"
)
reconstruction_path: Optional[str] = Field(
None, description="Relative path to reconstruction artifact (ply/obj)"
)
model_config = {"extra": "allow"}
class CaptureManifest(BaseModel):
"""
Canonical manifest for a capture bundle.
NOTE: Appendix C in the spec lists a directory structure, but not the exact
manifest schema. We define a stable minimal schema here and allow extras.
"""
schema_version: CaptureBundleSchemaVersion = Field(CaptureBundleSchemaVersion.V1_0)
capture_id: str = Field(..., description="Capture bundle ID")
created_at: Optional[datetime] = Field(None, description="Capture creation timestamp")
devices: List[CaptureDeviceRef] = Field(default_factory=list)
calibration: Optional[CalibrationRef] = None
annotations: Optional[AnnotationRefs] = None
teacher_outputs: Optional[TeacherOutputRefs] = None
# Optional metadata useful for stratification/regime selection.
operating_regime: Optional[OperatingRegime] = None
scene_type: Optional[str] = None
difficulty_flags: List[str] = Field(default_factory=list)
# Free-form metadata passthrough.
metadata: Dict[str, Any] = Field(default_factory=dict)
model_config = {"extra": "allow"}
class AnnotationConfidence(str, Enum):
CERTAIN = "certain"
PROBABLE = "probable"
UNSURE = "unsure"
class AnnotationObject(BaseModel):
id: str
type: str
frame_time: float
bbox: List[float] = Field(..., min_length=4, max_length=4)
model_config = {"extra": "allow"}
class AnnotationSegment(BaseModel):
id: str
start_time: float
end_time: float
scene_type: str
confidence: AnnotationConfidence = AnnotationConfidence.CERTAIN
flags: List[str] = Field(default_factory=list)
objects: List[AnnotationObject] = Field(default_factory=list)
model_config = {"extra": "allow"}
class DetailedAnnotation(BaseModel):
schema_version: Literal["1.0"] = "1.0"
capture_id: str
annotator_id: Optional[str] = None
created_at: Optional[str] = None
updated_at: Optional[str] = None
segments: List[AnnotationSegment] = Field(default_factory=list)
scene_metadata: Dict[str, Any] = Field(default_factory=dict)
quality_assessment: Dict[str, Any] = Field(default_factory=dict)
model_config = {"extra": "allow"}