| Server IP : 202.61.199.114 / Your IP : 216.73.217.139 Web Server : nginx/1.22.1 System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64 User : web20 ( 1018) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/clients/client2/web31/web/plate-ai-api/ |
Upload File : |
# plate-ai-api
Kennzeichen- und Fahrzeugerkennung als API (Fokus **Deutschland/Europa**).
FastAPI · CPU-tauglich · austauschbare Modelle · DSGVO-bewusst.
Erkennt aus einem Bild: **Kennzeichen, Land, Zulassungsbezirk, Fahrzeugtyp,
Marke, (Modell), Farbe** – jeweils mit **Confidence** und optionalen Bounding-Boxes.
---
## Architektur in einem Satz
Ein Bild durchläuft eine Pipeline aus austauschbaren Services
(`vehicle_detector → plate_detector → plate_ocr → plate_postprocessor →
country_detector → color_detector → vehicle_classifier`), orchestriert von
`recognition_pipeline.py`. **Der deterministische Teil (Normalisierung, DE-Bezirk,
EU-Land, Farbe) läuft immer** – die ML-Teile (Detection/OCR/Marke) werden **lazy**
geladen und sind optional. Fehlt ein Modell, gibt es eine `warning` statt eines
Absturzes (*graceful degradation*).
```
app/
main.py FastAPI-App, Middleware, Exception-Handler
config.py .env-Konfiguration (Pydantic Settings)
api/ deps (Auth/RateLimit/Usage) + v1-Endpunkte
core/ security, rate_limit, logging, errors
services/ Bild, Detektoren, OCR, Postprocessing, Farbe, Klassifikator, Pipeline
schemas/ Pydantic-Antwortschemas
database/ SQLAlchemy Engine + 9 Tabellen
data/regions/ de_regions.json (Bezirke), eu_countries.json (Länder)
deploy/ gunicorn, systemd, nginx, DEPLOY.md
scripts/ init_db.py, import_regions.py
tests/ pytest (Postprocessing, Land/Farbe, API)
test_recognition.py CLI-Testtool
```
## Endpunkte
| Methode | Pfad | Auth | Zweck |
|---|---|---|---|
| GET | `/api/v1/health` | – | Status + geladene Modelle |
| POST | `/api/v1/recognize` | API-Key | Bild-Upload → Ergebnis |
| POST | `/api/v1/recognize-url` | API-Key | Bild-URL (SSRF-geschützt) |
| GET | `/api/v1/job/{id}` | API-Key | gespeichertes Ergebnis (async = Ausbaustufe) |
| GET | `/api/v1/usage` | API-Key | Verbrauch im Zeitraum |
| POST/GET/DELETE | `/api/v1/admin/*` | Admin-Token | Clients, Keys, Usage, Errors, Korrekturen |
Auth: Header `X-API-Key: pk_live_…` (oder `Authorization: Bearer …`).
Admin: Header `X-Admin-Token: …`.
## Schnellstart (lokal)
```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # API läuft (deterministic mode)
pip install -r requirements-ml.txt # optional: Detection + OCR
cp .env.example .env # SECRET_KEY/ADMIN_TOKEN setzen!
python scripts/init_db.py --demo # DB + Demo-Key
python scripts/import_regions.py
uvicorn app.main:app --reload
# CLI ohne Server:
python test_recognition.py bild.jpg --pretty
```
Vollständige Server-Installation: **`deploy/DEPLOY.md`**.
## Beispiel-Antwort
```json
{
"success": true,
"request_id": "…",
"processing_time_ms": 312,
"vehicle": {
"detected": true, "type": "car", "type_confidence": 0.9,
"make": {"value": "Volkswagen", "confidence": 0.91},
"model": {"value": "Golf", "confidence": 0.74},
"color": {"value": "gray", "label_de": "Grau", "confidence": 0.86},
"bbox": [120, 80, 900, 620]
},
"license_plate": {
"detected": true, "raw_text": "HRO AB 123", "normalized": "HRO-AB-123",
"country": {"code": "DE", "name": "Deutschland", "confidence": 0.95},
"region": {"code": "HRO", "name": "Rostock", "state": "Mecklenburg-Vorpommern", "confidence": 0.99},
"plate_type": "standard", "confidence": 0.93, "bbox": [420, 510, 610, 565]
},
"warnings": [],
"model_versions": {"plate_detector": "…", "ocr": "…", "vehicle_detector": "…"}
}
```
`plate_type`: `standard | season | electric | historic | dealer | historic_red | diplomatic | unknown`.
Bei Saison zusätzlich `season` (z. B. `"04-10"`).
---
## Client-Beispiele
**cURL**
```bash
curl -H "X-API-Key: pk_live_xxx" -F "file=@auto.jpg" \
https://api.deine-domain.de/api/v1/recognize
```
**PHP**
```php
<?php
$ch = curl_init('https://api.deine-domain.de/api/v1/recognize');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['X-API-Key: pk_live_xxx'],
CURLOPT_POSTFIELDS => ['file' => new CURLFile('/pfad/auto.jpg', 'image/jpeg')],
]);
$res = json_decode(curl_exec($ch), true);
echo $res['license_plate']['normalized'] ?? 'n/a';
```
**JavaScript (Node/Browser)**
```js
const fd = new FormData();
fd.append("file", fileInput.files[0]);
const r = await fetch("https://api.deine-domain.de/api/v1/recognize", {
method: "POST", headers: { "X-API-Key": "pk_live_xxx" }, body: fd,
});
console.log((await r.json()).license_plate);
```
**Python**
```python
import requests
r = requests.post(
"https://api.deine-domain.de/api/v1/recognize",
headers={"X-API-Key": "pk_live_xxx"},
files={"file": open("auto.jpg", "rb")},
)
print(r.json()["license_plate"]["normalized"])
```
---
## Phase 9 – Kommerzialisierung (SaaS)
**Tarifmodell (Vorschlag)**
| Tarif | Preis | Inklusive | Rate-Limit |
|---|---|---|---|
| Free | 0 € | 100 Req/Monat | 10/min |
| Starter | 19 €/Mon | 5.000 Req | 60/min |
| Business | 99 €/Mon | 50.000 Req | 300/min |
| Pay-per-Use | ab 0,004 €/Req | nach Verbrauch | individuell |
- **API-Key-System:** pro Kunde n Keys, nur Hash gespeichert, einmalige Klartext-Anzeige, Revoke möglich (`admin`-Endpunkte).
- **Usage-Tracking:** `usage_stats` je Kunde/Monat (request/success/error). `GET /usage` für Kunden, `GET /admin/usage` für Betreiber.
- **Monatslimit + Rate-Limit:** pro Client konfigurierbar (`monthly_limit`, `rate_limit_per_minute`); Überschreitung → HTTP 429.
- **Abrechnung:** Usage-Zähler → Export an Billing (z. B. Stripe Metered Billing) – Anbindung ist Ausbaustufe.
- **Admin-Dashboard:** Endpunkte vorhanden; UI (React/HTMX) als Ausbaustufe.
- **Kundendoku:** dieses README + `/docs` (OpenAPI/Swagger).
**Rechtliche/DSGVO-Hinweise (unbedingt aufnehmen)**
- Kennzeichen sind **personenbeziehbare Daten** → Verarbeitung nur mit Rechtsgrundlage (Art. 6 DSGVO); ggf. Auftragsverarbeitungsvertrag (AVV) mit Kunden.
- Standardmäßig werden **keine Bilder gespeichert** (`STORE_IMAGES=false`); Ergebnis-Metadaten mit maskiertem Kennzeichen, automatische Löschung nach `RESULT_RETENTION_DAYS`.
- Kein Verkauf/Weitergabe der Erkennungsdaten; Zweckbindung dokumentieren.
- Hinweis an Kunden: Einsatz zur Massen-/Bewegungsüberwachung kann unzulässig sein.
---
## Phase 10 – Ehrliche Einschätzung (Machbarkeit & Grenzen)
**Zuverlässig heute (ohne eigenes Training):**
- Kennzeichen-**Normalisierung**, **DE-Zulassungsbezirk** (HRO→Rostock …), **EU-Land per Format**, **Farbe** – deterministisch, gut kontrollierbar. ✔ getestet.
- Fahrzeug-**Typ** (car/truck/bus/motorcycle) via YOLO-COCO. ✔
**Braucht ML-Modelle (Weights bereitstellen):**
- **Kennzeichen-Detektion:** feingetuntes YOLO-Plate-Modell (Datensätze: CCPD, „Car License Plate Detection“ u. a.). Der OpenCV-Fallback ist nur Notbetrieb.
- **OCR:** PaddleOCR liest FE-Schrift ordentlich; für **Produktionsqualität FE-Fine-Tuning** des rec-Modells nötig (O/0, B/8, D/O, Umlaute).
**Braucht eigene Trainingsdaten (schwach out-of-the-box):**
- **Modell** (Golf vs. Passat …) → deshalb `unknown`/Kandidaten unterhalb `MODEL_MIN_CONFIDENCE`.
- Feine **Fahrzeugtypen** (Transporter/Wohnmobil) – nicht in COCO.
- Robustheit bei **Winkel/Regen/Nacht/Unschärfe** ist primär eine Daten-/Trainingsfrage.
**Realistische Trefferquoten:** DE-Plate gute Bilder ~90–97 %; schwierige Bedingungen ohne Eigen-Training ~60–80 %; Land >95 % (bei sauberer Lesung); Bezirk ~100 % sobald Text stimmt; Marke ~80–90 %; Modell oft <70 %; Farbe ~85 %.
**Wann GPU nötig:** CPU reicht für MVP/erste Kunden (~1–4 Bilder/s). Ab ~5–10 Req/s dauerhaft oder für Training → GPU (+ async Queue mit Celery/RQ + Redis).
**Speichern erlaubt:** Metadaten/Confidence ja; Rohbilder nur mit Rechtsgrundlage und Opt-in (`STORE_IMAGES`).
**Verbesserung durch Korrekturen:** Fehllesungen über `POST /admin/training-samples` (Modellausgabe + korrigierter Text) sammeln → periodisch OCR/Detektor **nachtrainieren** (aktiver Lernkreis). Tabelle `training_samples` + `model_versions` bilden die Grundlage.
---
## Tests
```bash
pip install pytest
PYTHONPATH=. pytest -q # 28 Tests: Postprocessing, Land/Farbe, API (degraded)
```
## Lizenz / Status
MVP-Grundgerüst, produktionsnah aufgebaut und erweiterbar. Modelle/Weights sind
nicht enthalten und müssen (siehe Phase 10) bereitgestellt bzw. trainiert werden.