Skip to content

test(ocr): add degraded regression dataset + improve rotation/low-contrast OCR #4

test(ocr): add degraded regression dataset + improve rotation/low-contrast OCR

test(ocr): add degraded regression dataset + improve rotation/low-contrast OCR #4

name: OCR Regression Test (Degraded)
on:
push:
paths:
- 'app/ai-service/services/ocr.py'
- 'app/ai-service/services/preprocessing.py'
- 'app/ai-service/regression_harness/dataset/degraded/**'
- 'app/ai-service/regression_harness/**'
branches: [ main, develop ]
pull_request:
paths:
- 'app/ai-service/services/ocr.py'
- 'app/ai-service/services/preprocessing.py'
- 'app/ai-service/regression_harness/dataset/degraded/**'
- 'app/ai-service/regression_harness/**'
branches: [ main ]
workflow_dispatch:
jobs:
regression-degraded:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
cache: 'pip'
- name: Install System Dependencies
run: |
sudo apt-get update
sudo apt-get install -y tesseract-ocr libtesseract-dev
- name: Install Python Dependencies
working-directory: ./app/ai-service
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install Pillow pytesseract
- name: Run OCR Regression Harness (degraded)
working-directory: ./app/ai-service
run: |
set -euo pipefail
export PYTHONPATH=$PYTHONPATH:.
python regression_harness/cli.py \
--dataset regression_harness/dataset/degraded/ground_truth.json \
--output ocr_degraded_report.json \
--threshold 0.8 \
--min_pass_ratio 0.5
python - <<'PYTHON_SCRIPT'
import json
with open('ocr_degraded_report.json', 'r') as f:
report = json.load(f)
summary = report.get('summary', {})
total = summary.get('total', 0)
passed = summary.get('passed', 0)
accuracy = float(summary.get('accuracy', 0.0))
pass_ratio = (passed / total) if total else 0.0
print('Degraded regression summary:', {
'total': total,
'passed': passed,
'pass_ratio': pass_ratio,
'accuracy': accuracy
})
# The degraded dataset intentionally includes near-unreadable samples
# (heavy blur, watermark overlays) that no OCR engine can fully recover.
# The thresholds below are calibrated to the achievable baseline
# (~8/12 recoverable) while still failing on meaningful regressions.
if pass_ratio < 0.5:
raise SystemExit('FAILED: pass_ratio {:.3f} < 0.5'.format(pass_ratio))
if accuracy < 55.0:
raise SystemExit('FAILED: accuracy {:.3f}% < 55.0%'.format(accuracy))
PYTHON_SCRIPT
- name: Upload Regression Report
if: always()
uses: actions/upload-artifact@v4
with:
name: ocr-regression-degraded-report
path: app/ai-service/ocr_degraded_report.json
retention-days: 14