| #!/usr/bin/env bash |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| set -euo pipefail |
| mkdir -p Logs |
|
|
| PROJECT_DIR="${PROJECT_DIR:-${SLURM_SUBMIT_DIR:-$PWD}}" |
| IMAGE="${IMAGE:?Set IMAGE=/absolute/or/project-relative/image.jpg}" |
| CATEGORY="${CATEGORY:-walkway}" |
| SAMPLE_ID="${SAMPLE_ID:-}" |
| OUTPUT_DIR="${OUTPUT_DIR:-$PROJECT_DIR/output/inference/$SLURM_JOB_ID}" |
| ACCESSIBILITY3D_DIR="$OUTPUT_DIR/accessibility3d" |
| RUN_GPU_2D="${RUN_GPU_2D:-${RUN_SD_2D:-1}}" |
| RUN_FAST_2D="${RUN_FAST_2D:-0}" |
| ALLOW_LARGE_2D="${ALLOW_LARGE_2D:-0}" |
| RUN_DEPTH="${RUN_DEPTH:-1}" |
| RUN_AMODAL3D_3D="${RUN_ACCESSIBILITYAMODAL_VISUAL_3D:-${RUN_AMODAL3D_3D:-1}}" |
| RUN_AMODAL3D_GLB="${EXPORT_ACCESSIBILITYAMODAL_VISUAL_GLB:-${RUN_AMODAL3D_GLB:-0}}" |
| NO_TARGET_OCCLUDER="${NO_TARGET_OCCLUDER:-0}" |
| REVIEWED_VISIBLE_WORKSPACE="${REVIEWED_VISIBLE_WORKSPACE:-}" |
|
|
| SAM3_PYTHON="${SAM3_PYTHON:-$PROJECT_DIR/.envs/sam3/bin/python}" |
| AMODAL3D_PYTHON="${AMODAL3D_PYTHON:-$PROJECT_DIR/.envs/amodal3d/bin/python}" |
| SAM3_REPO="${SAM3_REPO:-$PROJECT_DIR/repos/sam3}" |
| SAM3_CHECKPOINT="${SAM3_CHECKPOINT:-$PROJECT_DIR/weights/sam3/sam3.pt}" |
| AMODAL_CHECKPOINT="${AMODAL_CHECKPOINT:-$PROJECT_DIR/weights/accessibility_amodal_adapter/best.pt}" |
| DEPTH_REPO="${DEPTH_REPO:-$PROJECT_DIR/repos/Depth-Anything-V2}" |
| DEPTH_CHECKPOINT="${DEPTH_CHECKPOINT:-$PROJECT_DIR/weights/depth_anything_v2_metric_hypersim_vitl.pth}" |
| PROMPT_CONFIG="${PROMPT_CONFIG:-}" |
| if [[ -z "$PROMPT_CONFIG" ]]; then |
| if [[ "$NO_TARGET_OCCLUDER" == "1" && "$CATEGORY" == "stairs" ]]; then |
| PROMPT_CONFIG="$PROJECT_DIR/configs/accessibility_stairs_outdoor_no_occlusion_prompts.json" |
| else |
| |
| |
| PROMPT_CONFIG="$PROJECT_DIR/configs/accessibility_mask_prompts_e5_v2.json" |
| fi |
| fi |
| SD_MODEL="${SD_MODEL:-$PROJECT_DIR/weights/stable-diffusion-inpainting}" |
| AMODAL3D_MODEL="${AMODAL3D_MODEL:-$PROJECT_DIR/weights/Amodal3R}" |
| AMODAL3D_TORCH_HOME="${AMODAL3D_TORCH_HOME:-$PROJECT_DIR/weights/torch}" |
| LOG_SANITIZER="$PROJECT_DIR/tools/sanitize_log_stream.py" |
| METADATA_SANITIZER="$PROJECT_DIR/tools/sanitize_output_metadata.py" |
| VERIFICATION_TOOL="$PROJECT_DIR/tools/audit_accessibility_3d_candidate.py" |
| REVIEWED_VISIBLE_VALIDATOR="$PROJECT_DIR/tools/validate_accessibility_reviewed_visible_workspace.py" |
| GPU_TURNTABLE_TOOL="$PROJECT_DIR/tools/render_accessibility_turntable.py" |
| REVIEW_BUNDLE_TOOL="$PROJECT_DIR/tools/build_accessibility_review_bundle.py" |
|
|
| |
| |
| privacy_filter_args=( |
| --project-root "$PROJECT_DIR" |
| --output-root "$OUTPUT_DIR" |
| --sensitive-path "$IMAGE" |
| --sensitive-path "$PROMPT_CONFIG" |
| --sensitive-path "$SAM3_PYTHON" |
| --sensitive-path "$AMODAL3D_PYTHON" |
| --sensitive-path "$SAM3_REPO" |
| --sensitive-path "$SAM3_CHECKPOINT" |
| --sensitive-path "$AMODAL_CHECKPOINT" |
| --sensitive-path "$DEPTH_REPO" |
| --sensitive-path "$DEPTH_CHECKPOINT" |
| --sensitive-path "$SD_MODEL" |
| --sensitive-path "$AMODAL3D_MODEL" |
| --sensitive-path "$AMODAL3D_TORCH_HOME" |
| ) |
| if [[ -n "$REVIEWED_VISIBLE_WORKSPACE" ]]; then |
| privacy_filter_args+=(--sensitive-path "$REVIEWED_VISIBLE_WORKSPACE") |
| fi |
| LOG_FILTER_PYTHON="$AMODAL3D_PYTHON" |
| if [[ ! -x "$LOG_FILTER_PYTHON" ]]; then |
| LOG_FILTER_PYTHON="$(command -v python3 || true)" |
| fi |
| if [[ -n "$LOG_FILTER_PYTHON" ]] && [[ -f "$LOG_SANITIZER" ]]; then |
| exec > >("$LOG_FILTER_PYTHON" "$LOG_SANITIZER" "${privacy_filter_args[@]}") |
| exec 2> >("$LOG_FILTER_PYTHON" "$LOG_SANITIZER" "${privacy_filter_args[@]}" >&2) |
| fi |
|
|
| module load cuda/13.0 || true |
|
|
| case "$CATEGORY" in |
| curb_cut|ramp|stairs|tactile_paving|walkway) ;; |
| *) echo "Unsupported CATEGORY=$CATEGORY" >&2; exit 2 ;; |
| esac |
|
|
| if ! cd "$PROJECT_DIR" 2>/dev/null; then |
| echo "Could not enter the configured project directory." >&2 |
| exit 2 |
| fi |
| [[ -f "$IMAGE" ]] || { echo "The configured input image was not found." >&2; exit 2; } |
| IMAGE="$(realpath "$IMAGE")" |
| if [[ -z "$SAMPLE_ID" ]]; then |
| SAMPLE_ID="$(basename "$IMAGE")" |
| SAMPLE_ID="${SAMPLE_ID%.*}" |
| SAMPLE_ID="${SAMPLE_ID//[^A-Za-z0-9_-]/_}" |
| fi |
|
|
| [[ -x "$AMODAL3D_PYTHON" ]] || { echo "The Accessibility3D Python environment is missing." >&2; exit 2; } |
| for tool_path in "$VERIFICATION_TOOL" "$GPU_TURNTABLE_TOOL" "$REVIEW_BUNDLE_TOOL"; do |
| [[ -f "$tool_path" ]] || { echo "A required AccessibilityAmodal tool is missing." >&2; exit 2; } |
| done |
| [[ -e "$AMODAL_CHECKPOINT" ]] || { echo "The amodal-mask runtime asset is missing." >&2; exit 2; } |
| if [[ -n "$REVIEWED_VISIBLE_WORKSPACE" ]]; then |
| [[ -d "$REVIEWED_VISIBLE_WORKSPACE" ]] || { echo "The reviewed-visible workspace is missing." >&2; exit 2; } |
| [[ -f "$REVIEWED_VISIBLE_VALIDATOR" ]] || { echo "The reviewed-visible validator is missing." >&2; exit 2; } |
| else |
| [[ -x "$SAM3_PYTHON" ]] || { echo "The SAM3 Python environment is missing." >&2; exit 2; } |
| for path in "$SAM3_REPO" "$SAM3_CHECKPOINT"; do |
| [[ -e "$path" ]] || { echo "A required SAM3 runtime asset is missing." >&2; exit 2; } |
| done |
| fi |
| if [[ "$RUN_DEPTH" == "1" ]]; then |
| for path in "$DEPTH_REPO" "$DEPTH_CHECKPOINT"; do |
| [[ -e "$path" ]] || { echo "A required depth runtime asset is missing." >&2; exit 2; } |
| done |
| fi |
| if [[ "$RUN_GPU_2D" == "1" ]] && [[ ! -e "$SD_MODEL" ]]; then |
| echo "The Stable Diffusion inpainting model is missing." >&2 |
| exit 2 |
| fi |
| if [[ "$RUN_AMODAL3D_3D" == "1" ]]; then |
| for path in \ |
| "$AMODAL3D_MODEL/pipeline.json" \ |
| "$AMODAL3D_TORCH_HOME/hub/facebookresearch_dinov2_main"; do |
| [[ -e "$path" ]] || { echo "A required Accessibility3D runtime asset is missing." >&2; exit 2; } |
| done |
| fi |
|
|
| export JOB_TMPDIR="$TMPDIR/job-$SLURM_JOB_ID" |
| export XDG_CACHE_HOME="$JOB_TMPDIR/xdg_cache" |
| export HF_HOME="$JOB_TMPDIR/huggingface" |
| export TORCH_HOME="$JOB_TMPDIR/torch" |
| export TRITON_CACHE_DIR="$JOB_TMPDIR/triton" |
| export MPLCONFIGDIR="$JOB_TMPDIR/matplotlib" |
| export PYTHONNOUSERSITE=1 |
| mkdir -p "$JOB_TMPDIR" "$XDG_CACHE_HOME" "$HF_HOME" "$TORCH_HOME" \ |
| "$TRITON_CACHE_DIR" "$MPLCONFIGDIR" "$OUTPUT_DIR" |
|
|
| |
| |
| |
| SAM3_WEIGHT=150 |
| if [[ -n "$REVIEWED_VISIBLE_WORKSPACE" ]]; then |
| SAM3_WEIGHT=5 |
| fi |
| MASK_WEIGHT=13 |
| FAST_2D_WEIGHT=12 |
| GPU_2D_WEIGHT=40 |
| GEOMETRY_WEIGHT=24 |
| if [[ "$RUN_DEPTH" != "1" ]]; then |
| GEOMETRY_WEIGHT=6 |
| fi |
| TURNTABLE_WEIGHT=3 |
| VARIANTS_WEIGHT=420 |
| AMODAL3D_WEIGHT=75 |
| if [[ "$RUN_AMODAL3D_GLB" == "1" ]]; then |
| |
| |
| AMODAL3D_WEIGHT=615 |
| fi |
|
|
| TOTAL_WEIGHT=$((SAM3_WEIGHT + MASK_WEIGHT + GEOMETRY_WEIGHT + TURNTABLE_WEIGHT + VARIANTS_WEIGHT)) |
| if [[ "$RUN_FAST_2D" == "1" ]]; then |
| TOTAL_WEIGHT=$((TOTAL_WEIGHT + FAST_2D_WEIGHT)) |
| fi |
| if [[ "$RUN_GPU_2D" == "1" ]]; then |
| TOTAL_WEIGHT=$((TOTAL_WEIGHT + GPU_2D_WEIGHT)) |
| fi |
| if [[ "$RUN_AMODAL3D_3D" == "1" ]]; then |
| TOTAL_WEIGHT=$((TOTAL_WEIGHT + AMODAL3D_WEIGHT)) |
| fi |
|
|
| PROGRESS_FILE="$OUTPUT_DIR/progress.json" |
| PROGRESS_WRITER="$PROJECT_DIR/tools/update_accessibility_inference_progress.py" |
| COMPLETED_WEIGHT=0 |
| CURRENT_STAGE_KEY="initializing" |
| CURRENT_STAGE_LABEL="Initializing GPU job" |
|
|
| start_stage() { |
| local stage_key="$1" |
| local stage_label="$2" |
| local stage_weight="$3" |
| local start_percent end_percent |
| start_percent=$((COMPLETED_WEIGHT * 100 / TOTAL_WEIGHT)) |
| end_percent=$(((COMPLETED_WEIGHT + stage_weight) * 100 / TOTAL_WEIGHT)) |
| CURRENT_STAGE_KEY="$stage_key" |
| CURRENT_STAGE_LABEL="$stage_label" |
| "$AMODAL3D_PYTHON" "$PROGRESS_WRITER" \ |
| --path "$PROGRESS_FILE" \ |
| --status running \ |
| --stage-key "$stage_key" \ |
| --stage-label "$stage_label" \ |
| --percent "$start_percent" \ |
| --stage-end-percent "$end_percent" \ |
| --stage-expected-seconds "$stage_weight" \ |
| --total-estimated-seconds "$TOTAL_WEIGHT" |
| } |
|
|
| finish_stage() { |
| COMPLETED_WEIGHT=$((COMPLETED_WEIGHT + $1)) |
| } |
|
|
| sanitize_output_metadata() { |
| if [[ -x "$AMODAL3D_PYTHON" ]] && [[ -f "$METADATA_SANITIZER" ]]; then |
| "$AMODAL3D_PYTHON" "$METADATA_SANITIZER" \ |
| --root "$OUTPUT_DIR" \ |
| --project-root "$PROJECT_DIR" \ |
| --sensitive-path "$IMAGE" \ |
| --sensitive-path "$PROMPT_CONFIG" \ |
| --sensitive-path "$SAM3_PYTHON" \ |
| --sensitive-path "$AMODAL3D_PYTHON" \ |
| --sensitive-path "$SAM3_REPO" \ |
| --sensitive-path "$SAM3_CHECKPOINT" \ |
| --sensitive-path "$AMODAL_CHECKPOINT" \ |
| --sensitive-path "$DEPTH_REPO" \ |
| --sensitive-path "$DEPTH_CHECKPOINT" \ |
| --sensitive-path "$SD_MODEL" \ |
| --sensitive-path "$AMODAL3D_MODEL" \ |
| --sensitive-path "$AMODAL3D_TORCH_HOME" |
| fi |
| } |
|
|
| record_exit() { |
| local exit_code=$? |
| if [[ "$exit_code" -ne 0 ]]; then |
| set +e |
| "$AMODAL3D_PYTHON" "$PROGRESS_WRITER" \ |
| --path "$PROGRESS_FILE" \ |
| --status failed \ |
| --message "Stage failed: $CURRENT_STAGE_LABEL" \ |
| --exit-code "$exit_code" |
| fi |
| sanitize_output_metadata |
| } |
| trap record_exit EXIT |
|
|
| echo "Image: $IMAGE" |
| echo "Category: $CATEGORY" |
| echo "No target occluder mode: $NO_TARGET_OCCLUDER" |
| echo "Reviewed visible workspace: ${REVIEWED_VISIBLE_WORKSPACE:-none}" |
| echo "Sample ID: $SAMPLE_ID" |
| echo "Output: $OUTPUT_DIR" |
| echo "Estimated GPU runtime: about $(( (TOTAL_WEIGHT + 59) / 60 )) minutes (queue time excluded)" |
|
|
| TARGET_VISIBLE_MASK="" |
| OBSTACLE_CANDIDATE_MASK="" |
| if [[ -n "$REVIEWED_VISIBLE_WORKSPACE" ]]; then |
| REVIEWED_VISIBLE_OUTPUT="$OUTPUT_DIR/01_reviewed_visible" |
| start_stage "reviewed_visible" "Validated human-reviewed visible target mask" "$SAM3_WEIGHT" |
| "$AMODAL3D_PYTHON" "$REVIEWED_VISIBLE_VALIDATOR" \ |
| --workspace "$REVIEWED_VISIBLE_WORKSPACE" \ |
| --image "$IMAGE" \ |
| --sample-id "$SAMPLE_ID" \ |
| --category "$CATEGORY" \ |
| --output-dir "$REVIEWED_VISIBLE_OUTPUT" |
| finish_stage "$SAM3_WEIGHT" |
| TARGET_VISIBLE_MASK="$REVIEWED_VISIBLE_OUTPUT/target_visible.png" |
| OBSTACLE_CANDIDATE_MASK="$REVIEWED_VISIBLE_OUTPUT/obstacle.png" |
| else |
| SAM3_OUTPUT="$OUTPUT_DIR/01_sam3" |
| start_stage "sam3" "SAM3 target and obstacle masks" "$SAM3_WEIGHT" |
| "$SAM3_PYTHON" tools/accessibility_mask_proposals.py \ |
| --image "$IMAGE" \ |
| --single-sample-id "$SAMPLE_ID" \ |
| --single-category "$CATEGORY" \ |
| --prompt-config "$PROMPT_CONFIG" \ |
| --output-dir "$SAM3_OUTPUT" \ |
| --backend sam3 \ |
| --device cuda \ |
| --artifact-level standard \ |
| --sam3-repo "$SAM3_REPO" \ |
| --sam3-checkpoint "$SAM3_CHECKPOINT" |
| finish_stage "$SAM3_WEIGHT" |
| SAM3_SAMPLE="$SAM3_OUTPUT/samples/$SAMPLE_ID" |
| TARGET_VISIBLE_MASK="$SAM3_SAMPLE/target_visible_candidate.png" |
| OBSTACLE_CANDIDATE_MASK="$SAM3_SAMPLE/obstacle.png" |
| fi |
|
|
| MASK_OUTPUT="$OUTPUT_DIR/02_masks" |
| start_stage "amodal_masks" "Visible, hidden, amodal, and obstacle masks" "$MASK_WEIGHT" |
| "$AMODAL3D_PYTHON" tools/accessibility_amodal_mask.py \ |
| --image "$IMAGE" \ |
| --target-visible-mask "$TARGET_VISIBLE_MASK" \ |
| --obstacle-candidate-mask "$OBSTACLE_CANDIDATE_MASK" \ |
| --category "$CATEGORY" \ |
| --checkpoint "$AMODAL_CHECKPOINT" \ |
| --output-dir "$MASK_OUTPUT" \ |
| --device cuda |
| finish_stage "$MASK_WEIGHT" |
|
|
| |
| |
| |
| PREFLIGHT_DIR="$OUTPUT_DIR/05_quality_checks" |
| PREFLIGHT_DECISION="$("$AMODAL3D_PYTHON" "$VERIFICATION_TOOL" \ |
| --run-dir "$OUTPUT_DIR" \ |
| --sample-id "$SAMPLE_ID" \ |
| --category "$CATEGORY" \ |
| --output "$PREFLIGHT_DIR/preflight.json" \ |
| --preflight-only \ |
| --print-decision)" |
| echo "3D preflight decision: $PREFLIGHT_DECISION" |
| if [[ "$PREFLIGHT_DECISION" != "accept" ]]; then |
| "$AMODAL3D_PYTHON" "$PROGRESS_WRITER" \ |
| --path "$PROGRESS_FILE" \ |
| --status completed \ |
| --stage-key mask_gate \ |
| --stage-label "3D withheld: re-prompt or review masks" \ |
| --percent 100 \ |
| --stage-end-percent 100 \ |
| --stage-expected-seconds 0 \ |
| --total-estimated-seconds "$TOTAL_WEIGHT" \ |
| --message "3D preflight=$PREFLIGHT_DECISION; see 05_quality_checks/preflight.json" |
| echo "3D generation withheld. Review: $PREFLIGHT_DIR/preflight.json" |
| exit 0 |
| fi |
|
|
| if [[ "$RUN_FAST_2D" == "1" ]]; then |
| start_stage "fast_2d" "Optional OpenCV 2D baseline" "$FAST_2D_WEIGHT" |
| completion_cmd=( |
| "$AMODAL3D_PYTHON" tools/accessibility_fast_2d_baseline.py |
| --image "$IMAGE" |
| --single-sample-id "$SAMPLE_ID" |
| --target-visible-mask "$MASK_OUTPUT/target_visible.png" |
| --target-amodal-mask "$MASK_OUTPUT/target_amodal.png" |
| --hidden-mask "$MASK_OUTPUT/hidden.png" |
| --obstacle-mask "$MASK_OUTPUT/obstacle.png" |
| --output-dir "$OUTPUT_DIR/03_fast_2d_baseline" |
| --mask-mode hidden |
| --opencv-mode pyramid |
| --overwrite |
| ) |
| if [[ "$ALLOW_LARGE_2D" == "1" ]]; then |
| completion_cmd+=(--allow-large-mask) |
| fi |
| "${completion_cmd[@]}" |
| finish_stage "$FAST_2D_WEIGHT" |
| fi |
|
|
| if [[ "$RUN_GPU_2D" == "1" ]]; then |
| start_stage "gpu_2d" "GPU generative 2D completion and candidate selection" "$GPU_2D_WEIGHT" |
| "$AMODAL3D_PYTHON" tools/accessibility_2d_completion.py \ |
| --image "$IMAGE" \ |
| --mask "$MASK_OUTPUT/hidden.png" \ |
| --obstacle-mask "$MASK_OUTPUT/obstacle_all_detected.png" \ |
| --target-visible-mask "$MASK_OUTPUT/target_visible.png" \ |
| --target-amodal-mask "$MASK_OUTPUT/target_amodal.png" \ |
| --category "$CATEGORY" \ |
| --output-dir "$OUTPUT_DIR/03_2d_completion" \ |
| --model "$SD_MODEL" \ |
| --device cuda |
| finish_stage "$GPU_2D_WEIGHT" |
| COMPLETION_STATUS="$("$AMODAL3D_PYTHON" -c 'import json,sys; print(json.load(open(sys.argv[1], encoding="utf-8")).get("status", "completed"))' "$OUTPUT_DIR/03_2d_completion/manifest.json")" |
| echo "2D completion quality status: $COMPLETION_STATUS" |
| case "$COMPLETION_STATUS" in |
| candidate_selected_for_review|skipped_empty_removal_mask) |
| ;; |
| *) |
| echo "The 2D candidate needs review and will not condition either 3D backend." |
| echo "Accessibility3D will still use the original RGB plus the strict three-value mask." |
| ;; |
| esac |
| fi |
|
|
| start_stage "geometry" "Depth and 3D geometry reconstruction" "$GEOMETRY_WEIGHT" |
| REFERENCE_IMAGE="" |
| if [[ "$RUN_GPU_2D" == "1" ]] \ |
| && [[ "${COMPLETION_STATUS:-}" =~ ^(candidate_selected_for_review|skipped_empty_removal_mask)$ ]]; then |
| REFERENCE_IMAGE="$OUTPUT_DIR/03_2d_completion/completed_rgb_selected.png" |
| fi |
| pipeline_cmd=( |
| "$AMODAL3D_PYTHON" -m accessibilityamodal.pipeline |
| --image "$IMAGE" |
| --sample-id "$SAMPLE_ID" |
| --preset "$CATEGORY" |
| --target-visible-mask "$MASK_OUTPUT/target_visible.png" |
| --target-amodal-mask "$MASK_OUTPUT/target_amodal.png" |
| --obstacle-mask "$MASK_OUTPUT/obstacle.png" |
| --output-dir "$OUTPUT_DIR/04_3d_completion" |
| ) |
| if [[ -n "$REFERENCE_IMAGE" ]]; then |
| pipeline_cmd+=( |
| --reference-image "$REFERENCE_IMAGE" |
| --completed-rgb "$REFERENCE_IMAGE" |
| ) |
| fi |
| if [[ "$RUN_DEPTH" == "1" ]]; then |
| pipeline_cmd+=( |
| --estimate-depth |
| --depth-engine depth_anything_v2 |
| --depth-device cuda |
| --depth-anything-repo "$DEPTH_REPO" |
| --depth-checkpoint "$DEPTH_CHECKPOINT" |
| --depth-encoder vitl |
| --metric-depth |
| --max-depth 20 |
| --depth-fallback error |
| ) |
| fi |
| "${pipeline_cmd[@]}" |
| finish_stage "$GEOMETRY_WEIGHT" |
|
|
| start_stage "surface_variants" "Auxiliary surface and canonical 3D views" "$VARIANTS_WEIGHT" |
| variants_cmd=( |
| "$AMODAL3D_PYTHON" tools/accessibility_3d_variants.py |
| --geometry-dir "$OUTPUT_DIR/04_3d_completion/geometry" |
| --output-dir "$OUTPUT_DIR/04_3d_completion/geometry/presentation_models" |
| --sample-id "$SAMPLE_ID" |
| --category "$CATEGORY" |
| --frames 72 |
| --duration-ms 140 |
| --hidden-tint 0 |
| --model-only |
| ) |
| if [[ -n "$REFERENCE_IMAGE" ]]; then |
| variants_cmd+=(--texture-image "$REFERENCE_IMAGE") |
| fi |
| "${variants_cmd[@]}" |
| finish_stage "$VARIANTS_WEIGHT" |
|
|
| PRESENTATION_MESH="$OUTPUT_DIR/04_3d_completion/geometry/completed_mesh.ply" |
| if [[ -f "$OUTPUT_DIR/04_3d_completion/geometry/presentation_models/02_canonical_stairs/02_canonical_stairs.ply" ]]; then |
| PRESENTATION_MESH="$OUTPUT_DIR/04_3d_completion/geometry/presentation_models/02_canonical_stairs/02_canonical_stairs.ply" |
| elif [[ -f "$OUTPUT_DIR/04_3d_completion/geometry/presentation_models/02_continuous_support_surface/02_continuous_support_surface.ply" ]]; then |
| PRESENTATION_MESH="$OUTPUT_DIR/04_3d_completion/geometry/presentation_models/02_continuous_support_surface/02_continuous_support_surface.ply" |
| fi |
|
|
| start_stage "turntable" "Diagnostic category-geometry turntable" "$TURNTABLE_WEIGHT" |
| "$AMODAL3D_PYTHON" "$GPU_TURNTABLE_TOOL" \ |
| --ply "$PRESENTATION_MESH" \ |
| --output-dir "$OUTPUT_DIR/04_3d_completion/turntable" \ |
| --sample-id "$SAMPLE_ID" \ |
| --category "$CATEGORY" \ |
| --frames 96 \ |
| --fps 24 \ |
| --shader defaultUnlit \ |
| --background 0.82,0.82,0.80,1 \ |
| --orbit-mode front_arc \ |
| --orbit-span 140 \ |
| --multiview-yaws=-60,-30,0,30,60 \ |
| --require-vertex-colors |
| finish_stage "$TURNTABLE_WEIGHT" |
|
|
| if [[ "$RUN_AMODAL3D_3D" == "1" ]]; then |
| start_stage "amodal3d" "Accessibility3D CUDA Gaussian rotation and dense mesh" "$AMODAL3D_WEIGHT" |
| amodal3d_cmd=( |
| "$AMODAL3D_PYTHON" tools/accessibility_3d_completion.py |
| --image "$IMAGE" |
| --conditioning-rgb original |
| --mask "$OUTPUT_DIR/04_3d_completion/amodal3d_three_value_mask.png" |
| --output-dir "$ACCESSIBILITY3D_DIR" |
| --model "$AMODAL3D_MODEL" |
| ) |
| |
| |
| |
| if [[ "$RUN_AMODAL3D_GLB" == "1" ]]; then |
| amodal3d_cmd+=(--export-glb) |
| fi |
| AMODAL3D_TORCH_HOME="$AMODAL3D_TORCH_HOME" "${amodal3d_cmd[@]}" |
| finish_stage "$AMODAL3D_WEIGHT" |
|
|
| POST_3D_DECISION="$("$AMODAL3D_PYTHON" "$VERIFICATION_TOOL" \ |
| --run-dir "$OUTPUT_DIR" \ |
| --sample-id "$SAMPLE_ID" \ |
| --category "$CATEGORY" \ |
| --output "$PREFLIGHT_DIR/verification.json" \ |
| --print-decision)" |
| echo "Generated 3D verification decision: $POST_3D_DECISION" |
|
|
| if [[ "$POST_3D_DECISION" == "accept" ]]; then |
| echo "Local 3D candidate passed the reconstruction-quality gate." |
| echo "Paper/GitHub packaging is intentionally withheld pending explicit human release approval for license/privacy and calibrated-geometry review." |
| else |
| echo "Learned 3D debug artifacts are withheld because generated 3D verification=$POST_3D_DECISION" |
| fi |
| fi |
|
|
| |
| |
| |
| sanitize_output_metadata |
|
|
| if [[ "$RUN_GPU_2D" == "1" ]]; then |
| PRIMARY_3D_ROLE="open_world_accessibility_surface" |
| PRIMARY_3D_GIF="$OUTPUT_DIR/04_3d_completion/turntable/turntable.gif" |
| PRIMARY_3D_MULTIVIEW="$OUTPUT_DIR/04_3d_completion/turntable/multiview.jpg" |
| PRIMARY_3D_MESH="$PRESENTATION_MESH" |
| if [[ |
| "$RUN_AMODAL3D_3D" == "1" && |
| "${POST_3D_DECISION:-}" == "accept" && |
| -f "$ACCESSIBILITY3D_DIR/sample_gaussian.gif" && |
| -f "$ACCESSIBILITY3D_DIR/multiview_contact_sheet.jpg" && |
| -f "$ACCESSIBILITY3D_DIR/mesh.ply" |
| ]]; then |
| PRIMARY_3D_ROLE="learned_amodal3d_gaussian" |
| PRIMARY_3D_GIF="$ACCESSIBILITY3D_DIR/sample_gaussian.gif" |
| PRIMARY_3D_MULTIVIEW="$ACCESSIBILITY3D_DIR/multiview_contact_sheet.jpg" |
| PRIMARY_3D_MESH="$ACCESSIBILITY3D_DIR/mesh.ply" |
| fi |
| review_cmd=( |
| "$AMODAL3D_PYTHON" "$REVIEW_BUNDLE_TOOL" |
| --source "$IMAGE" |
| --completion-2d "$OUTPUT_DIR/03_2d_completion/completed_rgb_selected.png" |
| --turntable-gif "$PRIMARY_3D_GIF" |
| --multiview "$PRIMARY_3D_MULTIVIEW" |
| --mesh "$PRIMARY_3D_MESH" |
| --primary-3d-role "$PRIMARY_3D_ROLE" |
| --completion-manifest "$OUTPUT_DIR/03_2d_completion/manifest.json" |
| --geometry-manifest "$OUTPUT_DIR/04_3d_completion/geometry/geometry_manifest.json" |
| --category "$CATEGORY" |
| --sample-id "$SAMPLE_ID" |
| --output-dir "$OUTPUT_DIR" |
| ) |
| if [[ -f "$PREFLIGHT_DIR/verification.json" ]]; then |
| review_cmd+=( |
| --verification-manifest "$PREFLIGHT_DIR/verification.json" |
| ) |
| fi |
| "${review_cmd[@]}" |
| fi |
|
|
| FINAL_STAGE_LABEL="All requested local outputs completed" |
| if [[ "$RUN_AMODAL3D_3D" == "1" ]]; then |
| FINAL_STAGE_LABEL="Local 3D outputs completed; public release withheld pending human approval" |
| if [[ "$POST_3D_DECISION" != "accept" ]]; then |
| FINAL_STAGE_LABEL="3D debug artifacts generated but withheld after verification" |
| fi |
| fi |
| "$AMODAL3D_PYTHON" "$PROGRESS_WRITER" \ |
| --path "$PROGRESS_FILE" \ |
| --status completed \ |
| --stage-key completed \ |
| --stage-label "$FINAL_STAGE_LABEL" \ |
| --percent 100 \ |
| --stage-end-percent 100 \ |
| --stage-expected-seconds 0 \ |
| --total-estimated-seconds "$TOTAL_WEIGHT" |
|
|
| echo "Completed. Review these first:" |
| if [[ "$RUN_GPU_2D" == "1" ]]; then |
| echo " $OUTPUT_DIR/00_quick_review/overview.jpg" |
| echo " $OUTPUT_DIR/00_quick_review/03_3d_turntable.gif" |
| fi |
| echo " $MASK_OUTPUT/mask_overlay.png" |
| if [[ "$RUN_GPU_2D" == "1" ]]; then |
| echo " $OUTPUT_DIR/03_2d_completion/completed_rgb_selected.png" |
| echo " $OUTPUT_DIR/03_2d_completion/candidate_comparison.jpg" |
| fi |
| if [[ "$RUN_FAST_2D" == "1" ]]; then |
| echo " $OUTPUT_DIR/03_fast_2d_baseline/$SAMPLE_ID/contact_sheet.jpg" |
| fi |
| echo " $OUTPUT_DIR/04_3d_completion/geometry/completed_region_overlay.png" |
| echo " $OUTPUT_DIR/04_3d_completion/geometry/completed_mesh.ply" |
| echo " $OUTPUT_DIR/04_3d_completion/geometry/presentation_models/manifest.json" |
| echo " diagnostic geometry mesh: $PRESENTATION_MESH" |
| if [[ "$RUN_AMODAL3D_3D" == "1" ]]; then |
| echo " $OUTPUT_DIR/05_quality_checks/verification.json" |
| echo " source-colored CUDA rotation: $ACCESSIBILITY3D_DIR/sample_gaussian.gif" |
| echo " CUDA mesh-normal diagnostic: $ACCESSIBILITY3D_DIR/sample_mesh.gif" |
| echo " primary multiview: $ACCESSIBILITY3D_DIR/multiview_contact_sheet.jpg" |
| echo " dense triangle mesh: $ACCESSIBILITY3D_DIR/mesh.ply" |
| if [[ "$RUN_AMODAL3D_GLB" == "1" ]]; then |
| echo " dense GLB mesh: $ACCESSIBILITY3D_DIR/mesh.glb" |
| fi |
| fi |
|
|