Files
fuelish/test_batch.sh
ml ca85530b5a
build / build (push) Successful in 2m57s
Add adaptive preprocessing escalation and single-receipt test scripts
Preprocessing now tries progressively heavier variants per receipt
(plain -> high-pass -> edge-enhance -> both), stopping as soon as a
cheap LLM-free arithmetic check on the OCR text looks plausible, so
the extra processing only applies to receipts that need it. A flat
version of the same heavier processing regressed the full batch by
helping hard receipts but hurting easy ones; the adaptive version
improves date-matching 37/52 -> 40/52 with no regression (see
testing/2026_10_04_gimp_highpass_nlfilter_experiment.md).

Also adds test_ocr.sh and test_single.sh for checking a single
receipt's OCR text or full pipeline result without a batch run.
2026-10-04 10:25:41 +02:00

97 lines
3.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# Test-only tool: runs the full container pipeline
# (12_adaptive_preprocess_ocr.sh, 3_extract_data.sh) over every *.jpg in
# a test-data directory, then compares the results against that
# directory's ground-truth spreadsheet (benzin_kosten.ods). Everything -
# preprocessing, OCR, structuring, and the comparison itself - runs
# inside the tooling container; nothing here depends on a host Python
# environment.
#
# For an input directory <path>/<name>, two sibling directories are
# created (mirroring <path>/<name>):
# <path>/<name>-scratch/<receipt>/ - intermediate step output: one
# variant<N>/ subdir per
# preprocessing variant tried
# (01_gray.png, ..., 0X_final.png,
# ocr.txt each) plus ocr.txt for
# the winning variant, for
# inspecting each step on its own
# <path>/<name>-result/<receipt>/ - final extracted.json per receipt,
# plus summary.txt with the overall
# ground-truth comparison
#
# Usage: ./test_batch.sh -in <test-data-dir>
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
ROOT="$(pwd)"
fail() { echo "FAIL: $*" >&2; exit 1; }
IN_DIR=""
while [ $# -gt 0 ]; do
case "$1" in
-in) IN_DIR="${2:-}"; shift 2 ;;
*) fail "unknown argument: $1" ;;
esac
done
[ -n "$IN_DIR" ] || fail "usage: $0 -in <test-data-dir>"
[ -d "$IN_DIR" ] || fail "input directory not found: $IN_DIR"
IN_ABS="$(realpath "$IN_DIR")"
ODS_PATH="$(find "$IN_ABS" -maxdepth 1 -name '*.ods' | head -n1)"
[ -n "$ODS_PATH" ] || fail "no .ods ground-truth file found in $IN_ABS"
PARENT_DIR="$(dirname "$IN_ABS")"
BASE_NAME="$(basename "$IN_ABS")"
SCRATCH_DIR="$PARENT_DIR/$BASE_NAME-scratch"
RESULT_DIR="$PARENT_DIR/$BASE_NAME-result"
mkdir -p "$SCRATCH_DIR" "$RESULT_DIR"
shopt -s nullglob
IMAGES=("$IN_ABS"/*.jpg)
[ "${#IMAGES[@]}" -gt 0 ] || fail "no .jpg files found in $IN_ABS"
echo "== Running pipeline over ${#IMAGES[@]} receipts =="
for img in "${IMAGES[@]}"; do
name="$(basename "${img%.jpg}")"
receipt_scratch="$SCRATCH_DIR/$name"
receipt_result="$RESULT_DIR/$name"
mkdir -p "$receipt_scratch" "$receipt_result"
echo "--- $name ---"
./12_adaptive_preprocess_ocr.sh -in "$img" -out "$receipt_scratch" >/dev/null
./3_extract_data.sh -in "$receipt_scratch/ocr.txt" -out "$receipt_result" >/dev/null
done
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"
echo
echo "== Done =="
echo "Intermediate step output: $SCRATCH_DIR/<receipt>/"
echo "Final results + summary: $RESULT_DIR/<receipt>/, $RESULT_DIR/summary.txt"