| """Auditable quality gates for accessibility 3D completion candidates. |
| |
| This module deliberately records compact, inspectable evidence instead of |
| using an opaque free-form reasoning step. It is a *reconstruction quality* |
| gate, not a certification of accessibility, safety, or metric navigation. |
| """ |
|
|
| from __future__ import annotations |
|
|
| import json |
| from pathlib import Path |
| from typing import Any |
|
|
| import cv2 |
| import numpy as np |
| from PIL import Image |
|
|
|
|
| DECISION_ORDER = {"accept": 0, "manual_review": 1, "reject": 2} |
|
|
|
|
| CATEGORY_POLICIES: dict[str, dict[str, float]] = { |
| "stairs": { |
| "min_visible_image_ratio": 0.008, |
| "min_visible_amodal_ratio": 0.15, |
| "max_hidden_visible_ratio": 4.0, |
| "max_hidden_amodal_ratio": 0.75, |
| "max_obstacle_amodal_ratio": 0.75, |
| }, |
| "ramp": { |
| "min_visible_image_ratio": 0.006, |
| "min_visible_amodal_ratio": 0.12, |
| "max_hidden_visible_ratio": 3.5, |
| "max_hidden_amodal_ratio": 0.72, |
| "max_obstacle_amodal_ratio": 0.72, |
| }, |
| "walkway": { |
| "min_visible_image_ratio": 0.008, |
| "min_visible_amodal_ratio": 0.12, |
| "max_hidden_visible_ratio": 3.5, |
| "max_hidden_amodal_ratio": 0.72, |
| "max_obstacle_amodal_ratio": 0.72, |
| }, |
| "curb_cut": { |
| "min_visible_image_ratio": 0.004, |
| "min_visible_amodal_ratio": 0.10, |
| "max_hidden_visible_ratio": 3.0, |
| "max_hidden_amodal_ratio": 0.70, |
| "max_obstacle_amodal_ratio": 0.70, |
| }, |
| "tactile_paving": { |
| "min_visible_image_ratio": 0.002, |
| "min_visible_amodal_ratio": 0.10, |
| "max_hidden_visible_ratio": 3.0, |
| "max_hidden_amodal_ratio": 0.70, |
| "max_obstacle_amodal_ratio": 0.70, |
| }, |
| } |
|
|
|
|
| def _round(value: float, digits: int = 6) -> float: |
| return round(float(value), digits) |
|
|
|
|
| def _ratio(numerator: int | float, denominator: int | float) -> float: |
| return float(numerator) / float(denominator) if denominator else 0.0 |
|
|
|
|
| def _policy(category: str) -> dict[str, float]: |
| return CATEGORY_POLICIES.get(category, CATEGORY_POLICIES["walkway"]) |
|
|
|
|
| def _component_stats(mask: np.ndarray) -> dict[str, Any]: |
| count, _, stats, _ = cv2.connectedComponentsWithStats(mask.astype(np.uint8), 8) |
| areas = stats[1:, cv2.CC_STAT_AREA] if count > 1 else np.empty((0,), dtype=np.int32) |
| total = int(mask.sum()) |
| largest = int(areas.max()) if areas.size else 0 |
| return { |
| "component_count": int(len(areas)), |
| "largest_component_pixels": largest, |
| "largest_component_fraction": _round(_ratio(largest, total)), |
| } |
|
|
|
|
| def _trace( |
| rule_id: str, |
| decision: str, |
| observed: Any, |
| expected: Any, |
| explanation: str, |
| ) -> dict[str, Any]: |
| return { |
| "rule_id": rule_id, |
| "decision": decision, |
| "observed": observed, |
| "expected": expected, |
| "explanation": explanation, |
| } |
|
|
|
|
| def _worst_decision(*decisions: str) -> str: |
| return max(decisions, key=lambda value: DECISION_ORDER[value]) |
|
|
|
|
| def evaluate_mask_preflight( |
| *, |
| category: str, |
| visible_mask: np.ndarray, |
| amodal_mask: np.ndarray, |
| hidden_mask: np.ndarray, |
| obstacle_mask: np.ndarray, |
| sam3_quality: dict[str, Any] | None = None, |
| reviewed_visible_metadata: dict[str, Any] | None = None, |
| ) -> dict[str, Any]: |
| """Evaluate whether masks have enough observed support for automatic 3D.""" |
| policy = _policy(category) |
| input_shapes = { |
| "visible": list(visible_mask.shape), |
| "amodal": list(amodal_mask.shape), |
| "hidden": list(hidden_mask.shape), |
| "obstacle": list(obstacle_mask.shape), |
| } |
| if not ( |
| visible_mask.shape == amodal_mask.shape == hidden_mask.shape == obstacle_mask.shape |
| ): |
| return { |
| "decision": "reject", |
| "policy": policy, |
| "measurements": {"input_mask_shapes": input_shapes}, |
| "audit_trace": [ |
| _trace( |
| "mask_shape_consistency", |
| "reject", |
| input_shapes, |
| "all masks have exactly the same HxW shape", |
| "A gate must not resample mismatched masks, because that can silently change the claimed visible/hidden support.", |
| ) |
| ], |
| } |
| image_area = int(visible_mask.size) |
| visible_pixels = int(visible_mask.sum()) |
| amodal_pixels = int(amodal_mask.sum()) |
| hidden_pixels = int(hidden_mask.sum()) |
| obstacle_pixels = int(obstacle_mask.sum()) |
| obstacle_amodal_pixels = int((obstacle_mask & amodal_mask).sum()) |
| visible_amodal_ratio = _ratio(visible_pixels, amodal_pixels) |
| hidden_visible_ratio = _ratio(hidden_pixels, max(visible_pixels, 1)) |
| hidden_amodal_ratio = _ratio(hidden_pixels, amodal_pixels) |
| obstacle_amodal_ratio = _ratio(obstacle_amodal_pixels, amodal_pixels) |
| trace: list[dict[str, Any]] = [] |
|
|
| sam_status = str((sam3_quality or {}).get("review_status") or "missing") |
| reviewed_visible_approved = bool( |
| reviewed_visible_metadata |
| and str(reviewed_visible_metadata.get("source_kind", "")) == "human_reviewed_visible_mask_only" |
| and str(reviewed_visible_metadata.get("review_status", "")) == "approved" |
| and bool(reviewed_visible_metadata.get("review_is_human", False)) |
| and bool(reviewed_visible_metadata.get("visible_confirmed", False)) |
| and str(reviewed_visible_metadata.get("annotator", "")).strip() |
| ) |
| if reviewed_visible_metadata is not None: |
| trace.append( |
| _trace( |
| "reviewed_visible_mask_status", |
| "accept" if reviewed_visible_approved else "reject", |
| { |
| "source_kind": reviewed_visible_metadata.get("source_kind"), |
| "review_status": reviewed_visible_metadata.get("review_status"), |
| "review_is_human": bool(reviewed_visible_metadata.get("review_is_human", False)), |
| "visible_confirmed": bool(reviewed_visible_metadata.get("visible_confirmed", False)), |
| "annotator_present": bool(str(reviewed_visible_metadata.get("annotator", "")).strip()), |
| }, |
| "approved, human-reviewed, visible-confirmed workspace with an annotator", |
| "A reviewed visible boundary can replace the SAM3 proposal only with explicit human approval and provenance." |
| if reviewed_visible_approved |
| else "The reviewed-visible workspace lacks the required approval provenance.", |
| ) |
| ) |
| if sam3_quality is not None and not reviewed_visible_approved: |
| category_verification = dict(sam3_quality.get("category_verification") or {}) |
| selected_category = str(sam3_quality.get("selected_category") or "") |
| best_category = str(category_verification.get("best_scored_category") or "") |
| category_disagreement = bool(category_verification.get("category_disagreement", False)) |
| category_ok = ( |
| (not selected_category or selected_category == category) |
| and (not best_category or best_category == category) |
| and not category_disagreement |
| ) |
| trace.append( |
| _trace( |
| "category_semantic_consistency", |
| "accept" if category_ok else "manual_review", |
| { |
| "requested_category": category, |
| "selected_category": selected_category or None, |
| "best_scored_category": best_category or None, |
| "category_disagreement": category_disagreement, |
| }, |
| "selected and best-scored category agree with the requested category", |
| "The prompt evidence does not consistently identify the requested stairs/ramp/walkway structure; review category and support boundary." |
| if not category_ok |
| else "Prompt-category evidence is consistent with the requested support structure.", |
| ) |
| ) |
| if reviewed_visible_approved: |
| trace.append( |
| _trace( |
| "sam3_proposal_status", |
| "accept", |
| sam_status, |
| "recorded only; superseded by approved reviewed-visible mask", |
| "The original SAM3 proposal is retained for audit but does not override a separately approved visible target boundary.", |
| ) |
| ) |
| elif sam_status in {"reject_or_reprompt", "error"}: |
| trace.append( |
| _trace( |
| "sam3_review_status", |
| "reject", |
| sam_status, |
| "candidate_accept_after_visual_review or manual_review", |
| "The segmentation stage itself rejected this proposal; it must not be sent to automatic 3D generation.", |
| ) |
| ) |
| elif sam_status == "manual_review": |
| trace.append( |
| _trace( |
| "sam3_review_status", |
| "manual_review", |
| sam_status, |
| "candidate_accept_after_visual_review", |
| "The segmentation proposal needs human mask review before any 3D result is used.", |
| ) |
| ) |
| else: |
| trace.append( |
| _trace( |
| "sam3_review_status", |
| "accept" if sam_status == "candidate_accept_after_visual_review" else "manual_review", |
| sam_status, |
| "candidate_accept_after_visual_review", |
| "SAM3 status is recorded as evidence; automatic masks remain proposals rather than ground truth.", |
| ) |
| ) |
|
|
| visible_image_ratio = _ratio(visible_pixels, image_area) |
| for rule_id, observed, threshold, comparator, explanation in ( |
| ( |
| "minimum_observed_support", |
| visible_image_ratio, |
| policy["min_visible_image_ratio"], |
| ">=", |
| "The observed target footprint is too small to support a stable scene-level reconstruction.", |
| ), |
| ( |
| "visible_over_amodal_support", |
| visible_amodal_ratio, |
| policy["min_visible_amodal_ratio"], |
| ">=", |
| "Most of the alleged support is hidden, so the completion would be driven by hallucinated geometry rather than observed structure.", |
| ), |
| ( |
| "hidden_over_visible_support", |
| hidden_visible_ratio, |
| policy["max_hidden_visible_ratio"], |
| "<=", |
| "The hidden region is disproportionate to observed support and commonly indicates wall/railing leakage into the amodal mask.", |
| ), |
| ( |
| "hidden_over_amodal_support", |
| hidden_amodal_ratio, |
| policy["max_hidden_amodal_ratio"], |
| "<=", |
| "Automatic 3D must retain enough visible surface evidence rather than invent nearly the whole target.", |
| ), |
| ( |
| "obstacle_dominates_target", |
| obstacle_amodal_ratio, |
| policy["max_obstacle_amodal_ratio"], |
| "<=", |
| "An obstacle that occupies most of the alleged target is likely a side wall, railing, or segmentation leak rather than a compact occluder.", |
| ), |
| ): |
| passed = observed >= threshold if comparator == ">=" else observed <= threshold |
| trace.append( |
| _trace( |
| rule_id, |
| "accept" if passed else "reject", |
| _round(observed), |
| f"{comparator} {_round(threshold)}", |
| "Observed support satisfies the guard." if passed else explanation, |
| ) |
| ) |
|
|
| components = _component_stats(visible_mask) |
| fragmented = ( |
| components["component_count"] >= 8 |
| and components["largest_component_fraction"] < 0.35 |
| ) |
| trace.append( |
| _trace( |
| "visible_support_connectedness", |
| "manual_review" if fragmented else "accept", |
| components, |
| "largest component >= 35% when >= 8 components", |
| "Fragmented stair treads can be valid, but need a reviewed support boundary before surface completion." |
| if fragmented |
| else "Observed support is sufficiently connected for automatic processing.", |
| ) |
| ) |
|
|
| decision = _worst_decision(*(row["decision"] for row in trace)) |
| return { |
| "decision": decision, |
| "policy": policy, |
| "measurements": { |
| "image_pixels": image_area, |
| "visible_pixels": visible_pixels, |
| "amodal_pixels": amodal_pixels, |
| "hidden_pixels": hidden_pixels, |
| "obstacle_pixels": obstacle_pixels, |
| "visible_image_ratio": _round(visible_image_ratio), |
| "visible_amodal_ratio": _round(visible_amodal_ratio), |
| "hidden_visible_ratio": _round(hidden_visible_ratio), |
| "hidden_amodal_ratio": _round(hidden_amodal_ratio), |
| "obstacle_amodal_ratio": _round(obstacle_amodal_ratio), |
| **components, |
| }, |
| "audit_trace": trace, |
| } |
|
|
|
|
| def evaluate_geometry_structure( |
| category: str, |
| geometry_manifest: dict[str, Any] | None, |
| ) -> dict[str, Any]: |
| """Check deterministic evidence emitted by accessibilityamodal.reconstruct.""" |
| if not geometry_manifest: |
| return { |
| "decision": "manual_review", |
| "measurements": {}, |
| "audit_trace": [ |
| _trace( |
| "geometry_manifest_present", |
| "manual_review", |
| False, |
| True, |
| "No deterministic geometry manifest is available yet.", |
| ) |
| ], |
| } |
| trace: list[dict[str, Any]] = [] |
| expected_mode = { |
| "stairs": "stairs", |
| "ramp": "ramp", |
| "walkway": "walkable", |
| "curb_cut": "walkable", |
| "tactile_paving": "walkable", |
| }.get(category) |
| observed_mode = str(geometry_manifest.get("geometry_mode") or "") |
| trace.append( |
| _trace( |
| "geometry_category_mode_consistency", |
| "accept" if observed_mode == expected_mode else "manual_review", |
| {"requested_category": category, "geometry_mode": observed_mode or None}, |
| f"geometry_mode={expected_mode}", |
| "The deterministic geometry branch does not match the requested accessibility structure." |
| if observed_mode != expected_mode |
| else "The deterministic geometry branch matches the requested structure.", |
| ) |
| ) |
| log = list(geometry_manifest.get("completion_log") or []) |
| plane_bands = sum( |
| 1 for row in log if str(row.get("mode") or "").startswith("plane") |
| ) |
| fallback_bands = sum( |
| 1 for row in log if "fallback" in str(row.get("mode") or "")) |
| fallback_ratio = _ratio(fallback_bands, max(len(log), 1)) |
| trace.append( |
| _trace( |
| "completion_band_support", |
| "reject" if fallback_ratio > 0.25 else "accept", |
| {"band_count": len(log), "plane_bands": plane_bands, "fallback_bands": fallback_bands, "fallback_ratio": _round(fallback_ratio)}, |
| "fallback_ratio <= 0.25", |
| "Too many stair bands lacked observed points and fell back to image inpainting." |
| if fallback_ratio > 0.25 |
| else "Most completion bands are supported by fitted geometry.", |
| ) |
| ) |
| hidden_pixels = int(geometry_manifest.get("hidden_pixel_count") or 0) |
| confidence = float(geometry_manifest.get("mean_hidden_completion_confidence") or 0.0) |
| hidden_confidence_decision = "accept" if hidden_pixels == 0 else "manual_review" if confidence < 0.50 else "accept" |
| trace.append( |
| _trace( |
| "hidden_geometry_confidence", |
| hidden_confidence_decision, |
| "not_applicable_no_hidden_region" if hidden_pixels == 0 else _round(confidence), |
| "not applicable when hidden_pixel_count=0; otherwise >= 0.50", |
| "No target surface was extrapolated, so hidden-depth confidence is not applicable." |
| if hidden_pixels == 0 |
| else "Hidden depth confidence is low; do not treat the result as a publishable or navigation-ready surface." |
| if hidden_confidence_decision == "manual_review" |
| else "Hidden completion confidence meets the local visualization threshold.", |
| ) |
| ) |
| faces = int(geometry_manifest.get("mesh_faces") or 0) |
| trace.append( |
| _trace( |
| "mesh_nonempty", |
| "reject" if faces <= 0 else "accept", |
| faces, |
| "> 0", |
| "No mesh faces were produced." if faces <= 0 else "Mesh contains triangle faces.", |
| ) |
| ) |
| if category == "stairs": |
| edges = list(geometry_manifest.get("stair_edges_y") or []) |
| edge_confidence = float(geometry_manifest.get("stair_edge_confidence") or 0.0) |
| trace.append( |
| _trace( |
| "stair_repetition_evidence", |
| "manual_review" if len(edges) < 3 or edge_confidence < 0.45 else "accept", |
| {"edge_count": len(edges), "edge_confidence": _round(edge_confidence), "edge_slope": _round(float(geometry_manifest.get("stair_edge_slope") or 0.0))}, |
| "at least 3 edges and confidence >= 0.45", |
| "Too little repeated tread evidence is available for a reliable stair regularization." |
| if len(edges) < 3 or edge_confidence < 0.45 |
| else "Repeated stair-edge evidence supports a segmented stair prior.", |
| ) |
| ) |
| decision = _worst_decision(*(row["decision"] for row in trace)) |
| return { |
| "decision": decision, |
| "measurements": { |
| "completion_band_count": len(log), |
| "plane_band_count": plane_bands, |
| "fallback_band_count": fallback_bands, |
| "fallback_band_ratio": _round(fallback_ratio), |
| "hidden_pixel_count": hidden_pixels, |
| "mean_hidden_completion_confidence": _round(confidence), |
| "mesh_faces": faces, |
| }, |
| "audit_trace": trace, |
| } |
|
|
|
|
| def _foreground_measurement(path: Path) -> dict[str, float]: |
| image = np.asarray(Image.open(path).convert("RGB")) |
| foreground = np.any(image < 245, axis=2) |
| ys, xs = np.where(foreground) |
| if xs.size == 0: |
| return {"coverage": 0.0, "bbox_width_ratio": 0.0, "bbox_height_ratio": 0.0, "bbox_aspect_ratio": 0.0} |
| width_ratio = _ratio(int(xs.max() - xs.min() + 1), image.shape[1]) |
| height_ratio = _ratio(int(ys.max() - ys.min() + 1), image.shape[0]) |
| return { |
| "coverage": _round(float(foreground.mean())), |
| "bbox_width_ratio": _round(width_ratio), |
| "bbox_height_ratio": _round(height_ratio), |
| "bbox_aspect_ratio": _round(min(width_ratio, height_ratio) / max(width_ratio, height_ratio, 1e-6)), |
| } |
|
|
|
|
| def evaluate_full_gpu_render_contract(learned_dir: Path) -> dict[str, Any]: |
| """Require evidence that both learned representations were rasterized on CUDA.""" |
|
|
| manifest_path = learned_dir / "manifest.json" |
| required_files = ( |
| "sample_gaussian.gif", |
| "sample_mesh.gif", |
| "sample_multi.gif", |
| "multiview_contact_sheet.jpg", |
| "mesh.ply", |
| ) |
| missing_files = [ |
| name |
| for name in required_files |
| if not (learned_dir / name).is_file() |
| or (learned_dir / name).stat().st_size <= 0 |
| ] |
| payload: dict[str, Any] = {} |
| manifest_error = None |
| try: |
| value = json.loads(manifest_path.read_text(encoding="utf-8")) |
| if not isinstance(value, dict): |
| raise ValueError("manifest root is not an object") |
| payload = value |
| except Exception as exc: |
| manifest_error = f"{type(exc).__name__}: {exc}" |
|
|
| renderer = payload.get("gpu_renderer_runtime") |
| validation = payload.get("render_validation") |
| gaussian = renderer.get("gaussian") if isinstance(renderer, dict) else None |
| dense_mesh = ( |
| renderer.get("dense_mesh") if isinstance(renderer, dict) else None |
| ) |
| nviews = int(payload.get("nviews") or 0) |
| gaussian_views = sorted(learned_dir.glob("*_gs.png")) |
| mesh_views = sorted(learned_dir.glob("*_mesh.png")) |
| contract_ok = ( |
| manifest_error is None |
| and not missing_files |
| and isinstance(renderer, dict) |
| and isinstance(gaussian, dict) |
| and gaussian.get("available") is True |
| and gaussian.get("required") is True |
| and gaussian.get("device") == "cuda" |
| and gaussian.get("runtime_import_succeeded") is True |
| and isinstance(dense_mesh, dict) |
| and dense_mesh.get("available") is True |
| and dense_mesh.get("required") is True |
| and dense_mesh.get("device") == "cuda" |
| and dense_mesh.get("runtime_import_succeeded") is True |
| and dense_mesh.get("cuda_context_preflight_succeeded") is True |
| and renderer.get("cpu_render_fallback_allowed") is False |
| and renderer.get("gaussian_only_debug_mode") is False |
| and isinstance(validation, dict) |
| and validation.get("validated") is True |
| and validation.get("dense_mesh_rendered_on_gpu") is True |
| and validation.get("cpu_render_fallback_used") is False |
| and int(validation.get("mesh_face_count") or 0) > 0 |
| and nviews > 0 |
| and len(gaussian_views) == nviews |
| and len(mesh_views) == nviews |
| ) |
| return { |
| "decision": "accept" if contract_ok else "reject", |
| "measurements": { |
| "manifest_error": manifest_error, |
| "missing_files": missing_files, |
| "declared_view_count": nviews, |
| "gaussian_view_count": len(gaussian_views), |
| "mesh_view_count": len(mesh_views), |
| "gaussian_cuda": bool( |
| isinstance(gaussian, dict) |
| and gaussian.get("device") == "cuda" |
| ), |
| "dense_mesh_cuda": bool( |
| isinstance(dense_mesh, dict) |
| and dense_mesh.get("device") == "cuda" |
| ), |
| "cpu_render_fallback_used": ( |
| validation.get("cpu_render_fallback_used") |
| if isinstance(validation, dict) |
| else None |
| ), |
| }, |
| "audit_trace": [ |
| _trace( |
| "full_gpu_renderer_contract", |
| "accept" if contract_ok else "reject", |
| { |
| "manifest_present": manifest_path.is_file(), |
| "missing_files": missing_files, |
| "gaussian_views": len(gaussian_views), |
| "mesh_views": len(mesh_views), |
| "declared_views": nviews, |
| }, |
| "CUDA Gaussian and nvdiffrast mesh renders, no CPU fallback", |
| ( |
| "The learned result proves both CUDA render paths and a " |
| "validated dense triangle mesh." |
| if contract_ok |
| else "The learned result is incomplete or does not prove the required CUDA Gaussian + dense-mesh render contract." |
| ), |
| ) |
| ], |
| } |
|
|
|
|
| def evaluate_learned_multiview( |
| category: str, |
| learned_dir: Path | None, |
| ) -> dict[str, Any]: |
| """Check learned visual candidates without treating renderer coordinates as metric geometry.""" |
| if learned_dir is None or not learned_dir.is_dir(): |
| return { |
| "decision": "manual_review", |
| "measurements": {}, |
| "audit_trace": [ |
| _trace("learned_multiview_present", "manual_review", False, True, "No learned Accessibility3D multiview result is available.") |
| ], |
| } |
| views = sorted(learned_dir.glob("*_gs.png")) |
| if not views: |
| return { |
| "decision": "reject", |
| "measurements": {}, |
| "audit_trace": [ |
| _trace("learned_multiview_present", "reject", False, True, "The learned 3D result has no rendered multiview evidence.") |
| ], |
| } |
| measures = [_foreground_measurement(path) for path in views] |
| gpu_contract = evaluate_full_gpu_render_contract(learned_dir) |
| median_coverage = float(np.median([row["coverage"] for row in measures])) |
| median_aspect = float(np.median([row["bbox_aspect_ratio"] for row in measures])) |
| coverage_decision = ( |
| "reject" if median_coverage < 0.05 else "manual_review" if median_coverage < 0.12 else "accept" |
| ) |
| aspect_decision = ( |
| "reject" if median_aspect < 0.10 else "manual_review" if median_aspect < 0.30 else "accept" |
| ) |
| trace = [ |
| *gpu_contract["audit_trace"], |
| _trace( |
| "learned_multiview_evidence_type", |
| "accept", |
| "Gaussian-splat raster previews (*_gs.png)", |
| "visual reconstruction evidence only", |
| "These views can expose a collapsed visual candidate but do not establish physical dimensions or navigability.", |
| ), |
| _trace( |
| "multiview_foreground_coverage", |
| coverage_decision, |
| _round(median_coverage), |
| ">= 0.12", |
| "The learned object occupies almost none of the rendered views and is likely an empty or fragmentary result." |
| if coverage_decision == "reject" |
| else "The object is small in the rendered views; inspect its requested scale and framing before use." |
| if coverage_decision == "manual_review" |
| else "The rendered object has adequate view coverage.", |
| ), |
| _trace( |
| "multiview_silhouette_thickness", |
| aspect_decision, |
| _round(median_aspect), |
| ">= 0.30", |
| "Most views are nearly one-dimensional, which is inconsistent with a usable support-surface candidate." |
| if aspect_decision == "reject" |
| else "The views are elongated; this can be valid for a long ramp or stair flight, but needs human geometry review." |
| if aspect_decision == "manual_review" |
| else "Rendered silhouettes have a plausible two-dimensional extent.", |
| ), |
| ] |
| mesh_measurements: dict[str, Any] = {} |
| mesh_path = learned_dir / "mesh.ply" |
| if mesh_path.is_file(): |
| try: |
| import trimesh |
|
|
| mesh = trimesh.load(mesh_path, process=False) |
| extent = np.asarray(mesh.bounds[1] - mesh.bounds[0], dtype=np.float64) |
| minmax_ratio = float(extent.min() / max(float(extent.max()), 1e-6)) |
| mesh_measurements = { |
| "vertices": int(len(mesh.vertices)), |
| "faces": int(len(mesh.faces)), |
| "extent": [_round(value) for value in extent], |
| "minmax_extent_ratio": _round(minmax_ratio), |
| "watertight": bool(mesh.is_watertight), |
| } |
| extent_decision = ( |
| "reject" if minmax_ratio < 0.02 else "manual_review" if minmax_ratio < 0.08 else "accept" |
| ) |
| trace.append( |
| _trace( |
| "mesh_near_degeneracy", |
| extent_decision, |
| _round(minmax_ratio), |
| ">= 0.08 (manual review below); < 0.02 rejects", |
| "The learned mesh is almost flat in its own normalized coordinates, consistent with a degenerate fragment." |
| if extent_decision == "reject" |
| else "The learned mesh is elongated; normalized extents alone cannot distinguish a valid long ramp/staircase from a fragment." |
| if extent_decision == "manual_review" |
| else "No near-zero mesh axis was detected. This is not a physical-scale check.", |
| ) |
| ) |
| except Exception as exc: |
| trace.append(_trace("mesh_near_degeneracy", "manual_review", "unavailable", ">= 0.08", f"Could not inspect learned mesh: {type(exc).__name__}")) |
| decision = _worst_decision(*(row["decision"] for row in trace)) |
| return { |
| "decision": decision, |
| "measurements": { |
| "view_count": len(measures), |
| "median_foreground_coverage": _round(median_coverage), |
| "median_silhouette_aspect": _round(median_aspect), |
| "views": measures, |
| "mesh": mesh_measurements, |
| "gpu_render_contract": gpu_contract["measurements"], |
| }, |
| "audit_trace": trace, |
| } |
|
|
|
|
| def mobility_interpretation(category: str, decision: str) -> dict[str, Any]: |
| """Return conservative, non-metric audience-specific interpretation.""" |
| withheld = decision != "accept" |
| common = "withheld pending mask/geometry review" if withheld else "requires calibrated clearance and surface survey" |
| if category == "stairs": |
| return { |
| "pedestrian": common, |
| "blind_or_low_vision_pedestrian": "requires surveyed handrail, edge, tactile, lighting, and obstacle information; monocular 3D is insufficient", |
| "wheelchair": "stairs are not an accessible route; require a separately verified ramp/lift/alternate route", |
| "robot_or_robot_dog": "requires metric riser/tread, friction, width, and local obstacle sensing; do not execute from this visual model alone", |
| } |
| return { |
| "pedestrian": common, |
| "blind_or_low_vision_pedestrian": "requires surveyed tactile/edge/obstacle information; monocular 3D is insufficient", |
| "wheelchair": common, |
| "robot_or_robot_dog": "requires metric slope, clearance, friction, and local obstacle sensing; do not execute from this visual model alone", |
| } |
|
|
|
|
| def build_verification( |
| *, |
| sample_id: str, |
| category: str, |
| visible_mask: np.ndarray, |
| amodal_mask: np.ndarray, |
| hidden_mask: np.ndarray, |
| obstacle_mask: np.ndarray, |
| sam3_quality: dict[str, Any] | None = None, |
| reviewed_visible_metadata: dict[str, Any] | None = None, |
| geometry_manifest: dict[str, Any] | None = None, |
| learned_dir: Path | None = None, |
| ) -> dict[str, Any]: |
| """Build one JSON-ready, auditable accessibility 3D verification record.""" |
| preflight = evaluate_mask_preflight( |
| category=category, |
| visible_mask=visible_mask, |
| amodal_mask=amodal_mask, |
| hidden_mask=hidden_mask, |
| obstacle_mask=obstacle_mask, |
| sam3_quality=sam3_quality, |
| reviewed_visible_metadata=reviewed_visible_metadata, |
| ) |
| geometry = evaluate_geometry_structure(category, geometry_manifest) |
| learned = evaluate_learned_multiview(category, learned_dir) |
| overall = _worst_decision(preflight["decision"], geometry["decision"], learned["decision"]) |
| if geometry_manifest is None and learned_dir is None: |
| overall = preflight["decision"] |
| trace = [ |
| *preflight["audit_trace"], |
| *geometry["audit_trace"], |
| *learned["audit_trace"], |
| ] |
| return { |
| "schema_version": 1, |
| "sample_id": sample_id, |
| "category": category, |
| "decision": overall, |
| "gate": { |
| "allow_automatic_geometry": preflight["decision"] == "accept", |
| "allow_learned_object_3d": ( |
| preflight["decision"] == "accept" |
| and geometry["decision"] == "accept" |
| and learned["decision"] == "accept" |
| ), |
| "allow_publication": False, |
| "publication_note": "Human license/privacy review and calibrated geometry validation remain required.", |
| }, |
| "mask_preflight": preflight, |
| "geometry_structure": geometry, |
| "learned_multiview": learned, |
| "mobility_interpretation": mobility_interpretation(category, overall), |
| "audit_trace": trace, |
| "recommended_action": ( |
| "re_prompt_or_review_masks_before_3d" if preflight["decision"] != "accept" |
| else "review_geometry_before_release" if overall != "accept" |
| else "keep_as_local_visual_candidate_not_navigation_truth" |
| ), |
| "limitations": [ |
| "This is a structured reconstruction-quality gate, not chain-of-thought or a safety certification.", |
| "Monocular/depth-model geometry is not calibrated metric truth unless separately calibrated.", |
| "Do not use this record alone to control a pedestrian aid, wheelchair, robot, or robot dog.", |
| ], |
| } |
|
|