Self-hosted-Dienst zur Erkennung und Textextraktion von Behördenstempeln aus PDF- und Bild-Dokumenten. Verwendet OpenCV für die Bildanalyse und EasyOCR für die Texterkennung — vollständig CPU-basiert, kein GPU erforderlich.
Dokument (PDF / JPG / PNG …)
│
▼
pdf2image (bei PDF → 150 DPI Rasterbilder)
│
▼
OpenCV Vorverarbeitung
├── Farberkennung (Rot / Blau / Lila, HSV-Filter)
├── Morphologische Bereinigung (Close + Open)
├── Konturanalyse + Formfilter
├── Positionsbewertung (Header-Abweisung + Gewichtung)
└── Fallback: Hough-Kreiserkennung (graue / schwarze Stempel)
│
▼
Bewertung: Farbdichte × Positionsgewicht
→ Bester Kandidat pro Dokument
│
▼
EasyOCR (CPU, DE + EN)
└── Text je Stempelregion
│
▼
JSON-Ergebnis (BBox, Text, Base64-Bild)
Detaillierte Beschreibung: Erkennungsalgorithmus C4-Diagramme: C4-Architektur
- Docker >= 24 + Docker Compose v2
- Kein GPU erforderlich (reine CPU-Ausführung)
docker compose buildBeim ersten Build werden die EasyOCR-Modelle (~200 MB) heruntergeladen und im Image gecacht. Folge-Builds sind deutlich schneller.
docker compose upAPI läuft unter http://localhost:8000 Web UI: http://localhost:8000 Swagger-UI: http://localhost:8000/docs
# Einzeldatei
curl -X POST http://localhost:8000/detect \
-F "file=@./samples/beispiel.pdf" \
| python -m json.tool
# Mehrere Dateien auf einmal
curl -X POST http://localhost:8000/detect/batch \
-F "files=@./samples/a.pdf" \
-F "files=@./samples/b.jpg" \
| python -m json.toolVerzeichnis lokal verarbeiten (ohne laufende API):
# Im Container ausführen
docker compose run --rm stamp-detector \
python cli.py --input /app/samples --output /app/output
# Lokal (mit installierten Abhängigkeiten)
python cli.py --input ./samples --output ./output --lang germanErgebnisse werden als .json-Dateien in ./output/ abgelegt,
plus _summary.json mit einer Gesamtübersicht.
Pro Dokument wird maximal 1 Stempel erkannt (der Kandidat mit der höchsten Bewertung).
{
"filename": "bescheid.jpg",
"stamp_count": 1,
"stamps": [
{
"bbox": [142, 830, 412, 1020],
"text": "Landratsamt Musterstadt Abt. Ordnungsrecht",
"image": "<base64-encoded PNG>"
}
]
}{
"filename": "dokument.pdf",
"total_pages": 3,
"total_stamps": 1,
"pages": [
{ "page": 1, "stamp_count": 0, "stamps": [] },
{ "page": 2, "stamp_count": 0, "stamps": [] },
{
"page": 3,
"stamp_count": 1,
"stamps": [
{
"bbox": [555, 801, 756, 1016],
"text": "IHK Elbe-Weser ...",
"image": "<base64-encoded PNG>"
}
]
}
]
}- Repo in VS Code öffnen
- „Reopen in Container" wählen
- API mit Hot-Reload starten:
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000| Parameter | Datei | Beschreibung |
|---|---|---|
lang |
detector.py → StampDetector(lang=…) |
OCR-Sprache (german, en, …) |
MIN_STAMP_AREA |
detector.py |
Minimale Pixelfläche einer Region (15 000 px²) |
MAX_STAMP_AREA |
detector.py |
Maximale Pixelfläche einer Region (250 000 px²) |
MIN_CIRCULARITY |
detector.py |
Mindest-Rundheit 0.30 (1.0 = perfekter Kreis) |
MAX_ASPECT_RATIO |
detector.py |
Max. Seitenverhältnis 2.5 |
REGION_PADDING |
detector.py |
Randpuffer um erkannte Regionen (20 px) |
MIN_COLOUR_DENSITY |
detector.py |
Min. Farbpixel-Anteil in BBox (3 %) |
HEADER_ZONE |
detector.py |
Oberer Seitenbereich → Abweisung (15 %) |
POSITION_WEIGHT_MIN |
detector.py |
Positionsgewicht oben (0.5) |
POSITION_WEIGHT_MAX |
detector.py |
Positionsgewicht unten (1.0) |
STAMP_COLOUR_RANGES |
detector.py |
HSV-Bereiche für Stempelfarben |
--workers |
Dockerfile CMD |
Uvicorn-Worker-Anzahl |
Vollständige Parameter-Referenz: Erkennungsalgorithmus → Konfigurierbare Konstanten
stamp-detector/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI-Server (Endpunkte)
│ ├── detector.py # Kernlogik (StampDetector)
│ └── static/
│ └── index.html # Web-Oberfläche
├── docs/
│ ├── c4-architecture.md # C4-Diagramme (Mermaid)
│ └── detection-algorithm.md # Algorithmus-Dokumentation
├── tests/
│ ├── api.http # HTTP-Testdateien
│ └── fixtures/ # Test-PDFs/-Bilder (nicht im Repo)
├── cli.py # Stapelverarbeitung (CLI)
├── Dockerfile # Mehrstufiger Build
├── docker-compose.yml
└── requirements.txt
- Schwarze Stempel: Graustufen-Fallback mit Hough-Kreiserkennung vorhanden, aber weniger zuverlässig als Farberkennung
- Schlechte Scan-Qualität: Vorverarbeitung mit
cv2.fastNlMeansDenoisingColoredergänzen - Höherer Durchsatz: GPU-Image (PyTorch CUDA für EasyOCR) + mehrere Uvicorn-Worker
- Mehrere Stempel: Aktuell wird nur der beste Kandidat pro Dokument zurückgegeben
- Klassifikation: Welche Behörde? → LLM-Nachverarbeitung auf extrahiertem Text