#!/usr/bin/env bash # Test-only tool: runs the full container pipeline # (12_adaptive_preprocess_ocr.sh, 3_extract_data.sh) on a single receipt # photo - the test_batch.sh equivalent for re-checking one receipt (e.g. # a known failure, after a preprocessing/prompt tweak) without re-running # a whole directory. If a ground-truth spreadsheet (*.ods) is found next # to the photo, compares the result against it the same way # test_batch.sh does; otherwise just prints the extracted JSON. # Everything - preprocessing, OCR, structuring, and the comparison itself # - runs inside the tooling container; nothing here depends on a host # Python environment. # # For an input photo /.jpg, two sibling directories are # created (mirroring test_batch.sh's layout, just for one receipt): # /-scratch// - intermediate step output: one # variant/ subdir per preprocessing # variant tried, plus ocr.txt for the # winning variant # /-result// - extracted.json, plus summary.txt # if a ground-truth .ods was found # # Usage: ./test_single.sh -in set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")" ROOT="$(pwd)" fail() { echo "FAIL: $*" >&2; exit 1; } IN_PATH="" while [ $# -gt 0 ]; do case "$1" in -in) IN_PATH="${2:-}"; shift 2 ;; *) fail "unknown argument: $1" ;; esac done [ -n "$IN_PATH" ] || fail "usage: $0 -in " [ -f "$IN_PATH" ] || fail "input file not found: $IN_PATH" IN_ABS="$(realpath "$IN_PATH")" IN_DIR="$(dirname "$IN_ABS")" NAME="$(basename "${IN_ABS%.jpg}")" SCRATCH_DIR="$IN_DIR/$NAME-scratch" RESULT_DIR="$IN_DIR/$NAME-result" receipt_scratch="$SCRATCH_DIR/$NAME" receipt_result="$RESULT_DIR/$NAME" mkdir -p "$receipt_scratch" "$receipt_result" echo "== Running pipeline on $NAME ==" ./12_adaptive_preprocess_ocr.sh -in "$IN_ABS" -out "$receipt_scratch" >/dev/null ./3_extract_data.sh -in "$receipt_scratch/ocr.txt" -out "$receipt_result" >/dev/null echo echo "== Extracted ==" cat "$receipt_result/extracted.json" echo ODS_PATH="$(find "$IN_DIR" -maxdepth 1 -name '*.ods' | head -n1)" if [ -n "$ODS_PATH" ]; then echo echo "== Comparing against ground truth ==" IMAGE="${REGISTRY_IMAGE:-fuelish/tools}" if [ -f "$ROOT/registry.env" ]; then # shellcheck disable=SC1091 source "$ROOT/registry.env" IMAGE="${REGISTRY_IMAGE:-$IMAGE}" fi VERSION="$(<"$ROOT/tooling-container/VERSION")" IMAGE="$IMAGE:$VERSION" ODS_DIR="$(dirname "$ODS_PATH")" ODS_FILE="$(basename "$ODS_PATH")" GROUP_ADD_ARGS=(--group-add "$(stat -c %g "$ODS_DIR")") RESULT_GID="$(stat -c %g "$RESULT_DIR")" [ "$RESULT_GID" = "$(stat -c %g "$ODS_DIR")" ] || GROUP_ADD_ARGS+=(--group-add "$RESULT_GID") docker run --rm \ --user "$(id -u):$(id -g)" \ "${GROUP_ADD_ARGS[@]}" \ -v "$ODS_DIR:/data/gt:ro" \ -v "$RESULT_DIR:/data/results:ro" \ "$IMAGE" \ python3 /opt/app/src/compare_ground_truth.py -gt "/data/gt/$ODS_FILE" -results /data/results \ | tee "$RESULT_DIR/summary.txt" else echo "(no ground-truth .ods found next to $IN_PATH - skipping comparison)" fi echo echo "== Done ==" echo "Intermediate step output: $receipt_scratch/" echo "Final result: $receipt_result/extracted.json"