# Roadmap: Kamera-/Linsenfehler simulieren (billige WebCams) **Status:** ✅ umgesetzt (A–D) in `setup/generateSets/render_robot.py`, Parameter in `robot.json → renderingInfo`. **A ist isoliert getestet** (deterministisches npz-Rauschen). **B–D sind Compositor-Effekte und müssen einmal in Blender 4.5 visuell geprüft werden** — jeder Effekt ist in `try/except` gekapselt: ein API-Problem überspringt nur den betroffenen Effekt mit Log-Warnung `[render][WARN] skipped: ...`, der Render läuft weiter. ### Parameter (robot.json → renderingInfo) | Effekt | Parameter | Beispiel | |---|---|---| | A Brennweiten-Restfehler | `focalErrorPct` | 0.5 (±%) | | A Hauptpunkt-Versatz | `principalErrorPx` | 3.0 (±px) | | A Rest-Verzeichnung | `residualDistortion` | [0.02, -0.01] (k1,k2) | | B Linsenstaub | `lensDirt` / `lensDirtStrength` | true / 0.08 | | C Vignette | `vignette` / `vignetteStrength` | true / 0.08 | | C Rand-Unschärfe | `localizedBlur` / `localizedBlurStrength` | false / 0.15 | | D Sensor-Rauschen | `sensorNoise` / `sensorNoiseStrength` | true / 0.01 | | D chromat. Aberration | `lensDistortion` / `lensDistortionStrength` | true / 0.002 | **Wichtig:** A verfälscht nur die **npz-Kalibrierung** (Bild bleibt ideal) → echter geometrischer Härtetest gegen unvollständige Kalibrierung; deterministisch pro Kamera (Seed aus `cameraPosition`), damit über alle Posen konsistent. B–D ändern nur das **Bild** (Detektion erschwert), nicht die Ground-Truth. --- (Ursprüngliche Detailplanung als Referenz:) **Ziel:** Realistische WebCam-Fehler in den Blender-Renderer (`setup/generateSets/render_robot.py`) einbauen, um die Pose-Pipeline gegen reale Kamera-Imperfektionen zu härten — analog zu den bereits umgesetzten Marker-Störungen (`markerOffsetMaxMm`, `motionBlur`, `arucoDust`). ## Kernkonzept (wichtig!) Es gibt zwei Fehlerklassen: 1. **Geometrische Fehler** (Brennweite, Hauptpunkt, Verzeichnung): verschieben die Marker-Pixel. **Entscheidend:** Kennt die Kalibrierung (`render_*.npz`) den Fehler exakt, korrigiert die `undistort`-Kette ihn vollständig → *kein* Pose-Fehler. Den Fehler erzeugt nur die **unvollständige Kalibrierung**. Daher: nicht „Bild verzeichnen", sondern die **npz-Intrinsik leicht von der Wahrheit abweichen lassen** (Kalibrier-Restfehler). 2. **Photometrische Fehler** (Staub, Vignette, Rand-Unschärfe, Rauschen): ändern die npz nicht, erschweren nur die Detektion (verrauschte Ecken, fehlende Marker). ## Hinweis: tote Parameter In `robot.json → renderingInfo` existieren bereits, werden aber von `render_robot.py` **nicht angewandt**: `lensDirt`, `lensDirtStrength`, `vignette`, `vignetteStrength`, `sensorNoise`, `sensorNoiseStrength`, `lensDistortion`, `lensDistortionStrength`, `localizedBlur`, `localizedBlurStrength`. Diese zum Leben erwecken. ## A — Kalibrier-Restfehler (geometrisch) ⭐ zuerst Höchster Testwert, deckt eine Lücke der bisherigen Störungen ab. Modell-konsistent (kein Blender↔OpenCV-Mismatch), weil das Bild ideal bleibt und nur die *angenommene* Kalibrierung in der npz falsch ist. **Implementierung:** im npz-Schreibblock von `render_robot.py` (~Zeile 460–510, wo `camera_matrix`/`dist_coeffs` gebaut werden) die Werte gezielt verrauschen — **deterministisch pro Kamera** (Seed aus Kameraposition/-id), damit über alle Posen konsistent. Neue robot.json-Parameter (Vorschlag): - `focalErrorPct` (z. B. 0.5) → `fx,fy *= 1 ± rnd·focalErrorPct/100` - `principalErrorPx` (z. B. 3) → `cx,cy += rnd·principalErrorPx` - `residualDistortion` (z. B. [0.02, -0.01]) → kleine `k1,k2` in `dist_coeffs`, die die Pipeline „korrigiert", obwohl das Bild ideal ist (Rest-Verzeichnung) ## B — Staub auf der Linse (photometrisch) Halbtransparentes Schmutz-Overlay über dem *ganzen* Bild (Compositor), verdeckt zufällig Marker teilweise. Parameter: `lensDirt`, `lensDirtStrength`. **Implementierung:** Compositor — RenderLayers → Mix (über eine prozedurale Fleckentextur, Voronoi/Noise mit hoher Schwelle) → Composite. Wenige, weiche, leicht abdunkelnde Flecken. ## C — Vignette + Rand-Unschärfe (Feldkrümmung) Randabdunklung und radial nach außen zunehmende Unschärfe (billige Linsen sind am Rand schlechter). Parameter: `vignette`/`vignetteStrength`, `localizedBlur`/`localizedBlurStrength`. **Implementierung:** Compositor — Vignette via Ellipse-Maske × Bild; Rand-Unschärfe via `CompositorNodeBlur` gemischt über eine radiale Maske (Lens Distortion „Distort" auf einer Maske oder Ellipse-Maske als Mix-Faktor zwischen scharf und Blur). ## D — Sensor-Rauschen + chromatische Aberration Leichtes Pixelrauschen und Farbsäume an Kanten. Parameter: `sensorNoise`/`sensorNoiseStrength`, `lensDistortion`/`lensDistortionStrength` (Dispersion). **Implementierung:** Compositor — additives Noise (klein) auf das Bild; chromatische Aberration via `CompositorNodeLensdist` mit kleinem `dispersion`-Wert. ## Reihenfolge & Test 1. **A** (geometrisch, einfach, konsistent) — danach Benchmark *mit* vs. *ohne* laufen lassen. 2. **B + C** (Detektions-Robustheit). 3. **D** (Feinschliff). Wichtig: Compositor-Node-API variiert leicht je Blender-Version — Code im echten Blender (4.5) gegenchecken. Determinismus pro Kamera nur bei A nötig (geometrische Konsistenz); B–D dürfen pro Aufnahme zufällig sein.