File size: 3,489 Bytes
2f382c4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/env python3
"""Write an auditable preflight and multiview verification report for one run."""

from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

import numpy as np
from PIL import Image

PROJECT_ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(PROJECT_ROOT))

from accessibilityamodal.verification import build_verification  # noqa: E402


def read_json(path: Path) -> dict:
    return json.loads(path.read_text(encoding="utf-8"))


def read_mask(path: Path) -> np.ndarray:
    mask = np.asarray(Image.open(path).convert("L")) > 127
    return mask


def find_sam_quality(run_dir: Path, sample_id: str) -> dict | None:
    for root in (run_dir / "01_sam3", run_dir / "01_sam3_retry"):
        path = root / "samples" / sample_id / "quality.json"
        if path.is_file():
            return read_json(path)
    return None


def find_reviewed_visible_metadata(run_dir: Path) -> dict | None:
    path = run_dir / "01_reviewed_visible" / "metadata.json"
    return read_json(path) if path.is_file() else None


def main() -> int:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--run-dir", required=True)
    parser.add_argument("--sample-id", required=True)
    parser.add_argument("--category", required=True, choices=["curb_cut", "ramp", "stairs", "tactile_paving", "walkway"])
    parser.add_argument("--output", default=None)
    parser.add_argument("--preflight-only", action="store_true")
    parser.add_argument("--print-decision", action="store_true")
    args = parser.parse_args()

    run_dir = Path(args.run_dir).expanduser().resolve()
    masks_dir = run_dir / "02_masks"
    visible = read_mask(masks_dir / "target_visible.png")
    amodal = read_mask(masks_dir / "target_amodal.png")
    hidden = read_mask(masks_dir / "hidden.png")
    obstacle = read_mask(masks_dir / "obstacle.png")
    geometry_path = run_dir / "04_3d_completion" / "geometry" / "geometry_manifest.json"
    geometry = None if args.preflight_only or not geometry_path.is_file() else read_json(geometry_path)
    learned_dir = None
    if not args.preflight_only:
        learned_candidates = (
            run_dir / "accessibility3d",
            run_dir / "04_3d_completion" / "visual_candidate",
        )
        learned_dir = next(
            (candidate for candidate in learned_candidates if candidate.is_dir()),
            learned_candidates[0],
        )
    report = build_verification(
        sample_id=args.sample_id,
        category=args.category,
        visible_mask=visible,
        amodal_mask=amodal,
        hidden_mask=hidden,
        obstacle_mask=obstacle,
        sam3_quality=find_sam_quality(run_dir, args.sample_id),
        reviewed_visible_metadata=find_reviewed_visible_metadata(run_dir),
        geometry_manifest=geometry,
        learned_dir=learned_dir,
    )
    output = (
        Path(args.output).expanduser().resolve()
        if args.output
        else run_dir / "05_quality_checks" / "verification.json"
    )
    output.parent.mkdir(parents=True, exist_ok=True)
    output.write_text(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True) + "\n", encoding="utf-8")
    if args.print_decision:
        print(report["decision"])
    else:
        print(json.dumps({"output": str(output), "decision": report["decision"], "gate": report["gate"]}, ensure_ascii=False))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())