bae705aa97
- Add NFC ePassport roadmap (ICAO 9303, eIDAS) - Add TensorFlow.js edge face detection (BlazeFace) - Add structured audit logger (GDPR-compliant) - Risk scoring support Part of KYC Apple Native UX v1.1.0
212 lines
6.7 KiB
Markdown
212 lines
6.7 KiB
Markdown
# quiXzoom — Smart Scan Architecture
|
|
*Beslutad: 2026-06-17. Ersätter "fotoflöde"-tänket.*
|
|
|
|
---
|
|
|
|
## Paradigmskiftet
|
|
|
|
| Fotoflöde (v1/v2) | Smart Scan |
|
|
|-------------------|------------|
|
|
| Zoomern tar bilder | Zoomern skannar ett objekt |
|
|
| AI bedömer varje bild | AI bygger upp ett bevispaket |
|
|
| Kvalitetsansvar: Zoomern | Kvalitetsansvar: systemet |
|
|
| Input: foto | Input: kontinuerlig videoström |
|
|
| Output: godkänd/nekad bild | Output: verifierad kontrollpunkt |
|
|
| Känsla: formulär | Känsla: Face ID / 3D-skanner |
|
|
|
|
**Kärninsikt:** Zoomern förstår inte uppdraget. AI vet redan vilka datapunkter som krävs, vilka vinklar som behövs, vilka detaljer som måste vara synliga, och när bevisningen är tillräcklig.
|
|
|
|
Zoomerns enda uppgift: *"Peka kameran mot objektet och följ instruktionerna."*
|
|
|
|
---
|
|
|
|
## Arkitektur
|
|
|
|
### Evidenspaketet (ersätter "foto")
|
|
|
|
Varje kontrollpunkt definierar ett `evidence_requirements`-objekt:
|
|
|
|
```json
|
|
{
|
|
"control_point": "electricity_meter",
|
|
"evidence_requirements": [
|
|
{ "id": "e1", "label": "Översikt", "type": "visual_coverage", "min_coverage_pct": 85 },
|
|
{ "id": "e2", "label": "Serienummer", "type": "ocr", "target": "serial_number" },
|
|
{ "id": "e3", "label": "Mätarställning","type": "ocr", "target": "meter_reading" },
|
|
{ "id": "e4", "label": "Plombering", "type": "presence_check", "target": "seal" }
|
|
]
|
|
}
|
|
```
|
|
|
|
Kontrollpunkten är **inte klar** förrän alla `evidence_requirements` är uppfyllda.
|
|
Det spelar ingen roll hur många frames det tar.
|
|
|
|
---
|
|
|
|
### Scanloopen (on-device, kontinuerlig)
|
|
|
|
```
|
|
Videoström
|
|
│
|
|
▼
|
|
Frame-sampler (~5fps)
|
|
│
|
|
▼
|
|
Evidence Matcher
|
|
├─ e1 täckt? → ja (frame 142)
|
|
├─ e2 läsbar? → ja (frame 198)
|
|
├─ e3 läsbar? → nej → direktiv: "Visa displayen"
|
|
└─ e4 synlig? → nej → direktiv: "Visa plomberingen"
|
|
│
|
|
▼
|
|
En direktiv åt gången → AR-overlay
|
|
│
|
|
▼ (när alla ej uppfyllda)
|
|
Bästa frame per requirement väljs ut
|
|
│
|
|
▼
|
|
All clear → "Kontrollpunkt klar ✓"
|
|
```
|
|
|
|
**Systemet väljer frames** — Zoomern fattar aldrig ett fotograferingsbeslut.
|
|
|
|
---
|
|
|
|
### Frame-selektion
|
|
|
|
När ett requirement är uppfyllt sparas den bästa frame:
|
|
|
|
```json
|
|
{
|
|
"requirement_id": "e2",
|
|
"frame_number": 198,
|
|
"timestamp_ms": 4820,
|
|
"confidence": 0.94,
|
|
"extracted_value": "SE-4821-9938-01",
|
|
"selected": true
|
|
}
|
|
```
|
|
|
|
Systemet väljer den frame med högst confidence inom ett kvalitetsfönster (skärpa, ljus, täckning). Aldrig den sista — den bästa.
|
|
|
|
---
|
|
|
|
### Evidenspaketet som skickas till server
|
|
|
|
Inte ett foto. Ett paket:
|
|
|
|
```json
|
|
{
|
|
"control_point": "electricity_meter",
|
|
"session_id": "sess_abc123",
|
|
"zoomer_id": "z_9981",
|
|
"geo": { "lat": 59.334, "lng": 18.063, "accuracy_m": 4 },
|
|
"device_id": "dev_ios_xyz",
|
|
"scan_duration_ms": 12400,
|
|
"evidence": [
|
|
{ "requirement_id": "e1", "frame": "frame_142.jpg", "confidence": 0.97 },
|
|
{ "requirement_id": "e2", "frame": "frame_198.jpg", "confidence": 0.94, "value": "SE-4821-9938-01" },
|
|
{ "requirement_id": "e3", "frame": "frame_265.jpg", "confidence": 0.91, "value": "04821.3" },
|
|
{ "requirement_id": "e4", "frame": "frame_302.jpg", "confidence": 0.88 }
|
|
]
|
|
}
|
|
```
|
|
|
|
Server-AVO verifierar paketet. Inte enskilda bilder.
|
|
|
|
---
|
|
|
|
### Server-AVO på evidenspaketet
|
|
|
|
```json
|
|
{
|
|
"phase": "evidence_review",
|
|
"control_point": "electricity_meter",
|
|
"decision": "approved",
|
|
"confidence": 0.942,
|
|
"evidence_summary": {
|
|
"e1": { "status": "verified", "confidence": 0.97 },
|
|
"e2": { "status": "verified", "confidence": 0.94, "value": "SE-4821-9938-01" },
|
|
"e3": { "status": "verified", "confidence": 0.91, "value": "04821.3" },
|
|
"e4": { "status": "verified", "confidence": 0.88 }
|
|
},
|
|
"deviations": [],
|
|
"summary": "🟢 Elmätare verifierad. Alla 4 datapunkter insamlade."
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## reject_class i Smart Scan
|
|
|
|
reject_class kvarstår men beter sig annorlunda:
|
|
|
|
| reject_class | Situation | Åtgärd |
|
|
|-------------|-----------|--------|
|
|
| `capture` | Requirement kan inte uppfyllas pga scan-kvalitet (för mörkt, för ostadigt) | Direktiv, fortsätt scanning |
|
|
| `content` | Requirement kan aldrig uppfyllas (skylt förstörd, mätare plomberad på fel sätt) | Stoppa, registrera avvikelse, eskalera |
|
|
| `evidence_incomplete` | Scanning avbröts innan alla krav uppfylldes | Återuppta scanning |
|
|
|
|
---
|
|
|
|
## UX-känslan
|
|
|
|
### Traditionellt fotoflöde
|
|
```
|
|
Öppna kamera → ta bild → vänta → underkänt → ta om
|
|
```
|
|
|
|
### Smart Scan
|
|
```
|
|
Öppna kontrollpunkt → kamera startar → följ guidning →
|
|
"Kontrollpunkt klar ✓" → nästa
|
|
```
|
|
|
|
Det närmaste analogin är **Face ID** — inte "ta ett foto av ditt ansikte", bara "titta mot telefonen".
|
|
|
|
Eller en **3D-skanner** — inte "ta 12 foton från dessa vinklar", bara "rör kameran runt objektet".
|
|
|
|
---
|
|
|
|
## Vad det innebär för skala
|
|
|
|
**Gammalt:** Uppdragsgivaren definierar bildkrav → Zoomer tolkar → kvalitetsvariation
|
|
**Nytt:** Uppdragsgivaren definierar datakrav → AI samlar in → konsekvent kvalitet
|
|
|
|
Uppdragsgivaren behöver inte längre tänka i bilder. De anger:
|
|
- Vilka värden de behöver (serienummer, mätarställning, skadetyp)
|
|
- Vilka element som måste vara synliga (plombering, skylt, fasad)
|
|
|
|
AI:n avgör hur det samlas in.
|
|
|
|
---
|
|
|
|
## Teknisk implementation
|
|
|
|
| Komponent | Ansvar |
|
|
|-----------|--------|
|
|
| Frame-sampler | ~5fps från videoström, on-device |
|
|
| Evidence Matcher | Per-frame check mot requirements, TF Lite / CoreML |
|
|
| AR Directive Layer | En instruktion åt gången, uppdateras per frame |
|
|
| Frame Store | Temporär ring-buffer, behåller kandidat-frames |
|
|
| Frame Selector | Väljer bästa frame per requirement vid completion |
|
|
| Evidence Packager | Bygger JSON-paketet för server-upload |
|
|
| Server AVO | Full verifiering, OCR-validering, avvikelseanalys |
|
|
| Audit Trail | `image_hash + geo + timestamp + device_id` per frame |
|
|
|
|
---
|
|
|
|
## Öppna frågor (uppdaterade)
|
|
|
|
1. **Liveness / anti-spoofing** — hur verifierar vi att videoströmmen är levande och inte en inspelning eller skärmdump? Device attestation (iOS App Attest / Android Play Integrity)?
|
|
2. **Frame-kvalitetströskel** — vilken minsta confidence krävs för att en frame ska väljas? Konfigurerbart per requirement?
|
|
3. **Offline scanning** — frames buffras lokalt, paket skickas vid uppkoppling. Max buffer-storlek?
|
|
4. **GDPR / ansikten** — scanning av fasader och miljöer fångar troligen ansikten. Face blurring before upload?
|
|
5. **Scan-timeout** — max tid per kontrollpunkt? (förslag: 120 sek → eskalera)
|
|
6. **Multi-objekt** — kan en scanning-session samla bevis för flera kontrollpunkter parallellt?
|
|
|
|
---
|
|
|
|
*Ersätter QUIXZOOM_CAPTURE_FLOW.md och AVO-masterprompt v1/v2 som konceptuellt underlag.*
|
|
*AVO-masternprompt v2 gäller fortfarande som tekniskt kontrakt för fas B (server-AVO).*
|