Visitenkarten-Scanner: Stapelscan, Extraktion, Übersicht, vCard-Export
Selbst gehostete PWA, die Visitenkarten von einem Foto freistellt, ausliest und als Kontakt bereitstellt. - Stapelscan: OpenCV findet die Kartenrechtecke über mehrere Binärmasken, entzerrt sie perspektivisch und schneidet sie einzeln aus. Ohne Fund gilt das ganze Foto als eine Karte. - Extraktion: ein Aufruf je Zuschnitt an das Vision-Modell mit JSON-Schema. Kein vorgeschaltetes OCR - das würde Layout und Schriftgrößen wegwerfen, aus denen die Feldzuordnung entsteht. - Metadaten: Aufnahmezeit und GPS aus den EXIF-Daten des Fotos, Ortsname über Nominatim, Browserstandort nur als Rückfallebene. - Übersicht mit Volltextsuche und Filtern, Detailansicht mit Korrekturmaske. - Notizfeld je Karte, Erinnerungen per Mail inklusive Nachholen verpasster Termine nach einem Neustart. - vCard 3.0 einzeln und als Sammeldatei, Karte gilt danach als exportiert. - Anmeldung über ein Passwort, Sitzung als signiertes Cookie. - Deployment per Tag-Push nach den Konventionen in DEPLOY.md. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
39
docker-compose.yml
Normal file
39
docker-compose.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
# Fester Projektname. Ohne das leitet Compose ihn aus dem Verzeichnisnamen
|
||||
# ab - und der ist im CI-Job ein anderer als auf dem Host.
|
||||
name: business-card-scanner
|
||||
|
||||
services:
|
||||
app:
|
||||
# Versionstag ermoeglicht Rollback ohne Rebuild.
|
||||
image: business-card-scanner:${IMAGE_TAG:-latest}
|
||||
build: .
|
||||
# Fester Name: das ist die Adresse, auf die der Proxy zeigt.
|
||||
container_name: business-card-scanner
|
||||
restart: unless-stopped
|
||||
# Wird im Workflow aus dem Secret DOTENV erzeugt.
|
||||
env_file: .env
|
||||
volumes:
|
||||
- business-card-scanner-data:/data
|
||||
networks:
|
||||
- nginx-proxy-manager_default
|
||||
# Pflicht: der Deploy-Schritt nutzt --wait und macht das zum Gate.
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- python
|
||||
- -c
|
||||
- import urllib.request,sys; sys.exit(0 if urllib.request.urlopen('http://127.0.0.1:8080/healthz', timeout=4).status == 200 else 1)
|
||||
interval: 60s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
|
||||
# Kein ports-Mapping: Der Proxy erreicht den Container ueber das gemeinsame
|
||||
# Netz unter seinem Container-Namen.
|
||||
networks:
|
||||
nginx-proxy-manager_default:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
business-card-scanner-data:
|
||||
# Fester Name, damit das Volume nicht am Projektnamen haengt.
|
||||
name: business-card-scanner-data
|
||||
Reference in New Issue
Block a user