fix: Restore all files lost during destructive rebase
A previous `git pull --rebase origin main` dropped 177 local commits,
losing 3400+ files across admin-v2, backend, studio-v2, website,
klausur-service, and many other services. The partial restore attempt
(660295e2) only recovered some files.
This commit restores all missing files from pre-rebase ref 98933f5e
while preserving post-rebase additions (night-scheduler, night-mode UI,
NightModeWidget dashboard integration).
Restored features include:
- AI Module Sidebar (FAB), OCR Labeling, OCR Compare
- GPU Dashboard, RAG Pipeline, Magic Help
- Klausur-Korrektur (8 files), Abitur-Archiv (5+ files)
- Companion, Zeugnisse-Crawler, Screen Flow
- Full backend, studio-v2, website, klausur-service
- All compliance SDKs, agent-core, voice-service
- CI/CD configs, documentation, scripts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,366 +1,235 @@
|
||||
# OCR Compare Tool - Dokumentation
|
||||
# OCR Compare - Block Review Feature
|
||||
|
||||
**Status:** Produktiv
|
||||
**Version:** 4.0
|
||||
**Letzte Aktualisierung:** 2026-02-08
|
||||
**URL:** https://macmini:3002/ai/ocr-compare
|
||||
|
||||
---
|
||||
|
||||
## Übersicht
|
||||
## Uebersicht
|
||||
|
||||
Das OCR Compare Tool ermöglicht die automatische Analyse von gescannten Vokabeltabellen mit:
|
||||
- Grid-basierter OCR-Erkennung
|
||||
- Automatischer Spalten-Erkennung (Englisch/Deutsch/Beispiel)
|
||||
- mm-Koordinatensystem für präzise Positionierung
|
||||
- Deskew-Korrektur für schiefe Scans
|
||||
- Export zum Worksheet-Editor
|
||||
Das OCR Compare Tool ermoeglicht den Vergleich verschiedener OCR-Methoden zur Texterkennung aus gescannten Dokumenten. Die Block Review Funktion erlaubt eine zellenweise Ueberpruefung und Korrektur der OCR-Ergebnisse.
|
||||
|
||||
### Hauptfunktionen
|
||||
|
||||
| Feature | Beschreibung |
|
||||
|---------|--------------|
|
||||
| **Multi-Method OCR** | Vergleich von Vision LLM, Tesseract, PaddleOCR und Claude Vision |
|
||||
| **Grid Detection** | Automatische Erkennung von Tabellenstrukturen |
|
||||
| **Block Review** | Zellenweise Ueberpruefung und Korrektur |
|
||||
| **Session Persistence** | Sessions bleiben bei Seitenwechsel erhalten |
|
||||
| **High-Resolution Display** | Hochaufloesende Bildanzeige (zoom=2.0) |
|
||||
|
||||
---
|
||||
|
||||
## Architektur
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ Frontend (admin-v2) │
|
||||
│ /admin-v2/app/(admin)/ai/ocr-compare/page.tsx │
|
||||
│ - Bild-Upload │
|
||||
│ - Grid-Overlay Visualisierung │
|
||||
│ - Cell-Edit Popup │
|
||||
│ - Export zum Worksheet-Editor │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ admin-v2 (Next.js) │
|
||||
│ /app/(admin)/ai/ocr-compare/page.tsx │
|
||||
│ - PDF Upload & Session Management │
|
||||
│ - Grid Visualization mit SVG Overlay │
|
||||
│ - Block Review Panel │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ klausur-service (FastAPI) │
|
||||
│ Port 8086 - /klausur-service/backend/ │
|
||||
│ - /api/v1/ocr/analyze-grid (Grid-Analyse) │
|
||||
│ - services/grid_detection_service.py (v4) │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────┐
|
||||
│ PaddleOCR Service │
|
||||
│ Port 8088 - OCR-Erkennung │
|
||||
└─────────────────────────────────────────────────────────────────────┘
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ klausur-service (FastAPI) │
|
||||
│ Port 8086 │
|
||||
│ - /api/v1/vocab/sessions (Session CRUD) │
|
||||
│ - /api/v1/vocab/sessions/{id}/pdf-thumbnail (Bild-Export) │
|
||||
│ - /api/v1/vocab/sessions/{id}/detect-grid (Grid-Erkennung) │
|
||||
│ - /api/v1/vocab/sessions/{id}/run-ocr (OCR-Ausfuehrung) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Features (Version 4)
|
||||
## Komponenten
|
||||
|
||||
### 1. mm-Koordinatensystem
|
||||
### GridOverlay
|
||||
|
||||
Alle Koordinaten werden im A4-Format (210x297mm) ausgegeben:
|
||||
SVG-Overlay zur Visualisierung der erkannten Grid-Struktur.
|
||||
|
||||
| Feld | Beschreibung |
|
||||
|------|--------------|
|
||||
| `x_mm` | X-Position in mm (0-210) |
|
||||
| `y_mm` | Y-Position in mm (0-297) |
|
||||
| `width_mm` | Breite in mm |
|
||||
| `height_mm` | Höhe in mm |
|
||||
**Datei:** `/admin-v2/components/ocr/GridOverlay.tsx`
|
||||
|
||||
**Konvertierung:**
|
||||
```typescript
|
||||
// Prozent zu mm
|
||||
const x_mm = (x_percent / 100) * 210
|
||||
const y_mm = (y_percent / 100) * 297
|
||||
|
||||
// mm zu Pixel (für Canvas bei 96 DPI)
|
||||
const MM_TO_PX = 3.7795275591
|
||||
const x_px = x_mm * MM_TO_PX
|
||||
```
|
||||
|
||||
### 2. Deskew-Korrektur
|
||||
|
||||
Automatische Ausrichtung schiefer Scans basierend auf der ersten Spalte:
|
||||
|
||||
1. **Erkennung:** Alle Wörter in der ersten Spalte (x < 33%) werden analysiert
|
||||
2. **Berechnung:** Lineare Regression auf den linken Kanten
|
||||
3. **Korrektur:** Rotation aller Koordinaten um den berechneten Winkel
|
||||
4. **Limitierung:** Maximal ±5° Korrektur
|
||||
|
||||
```python
|
||||
# Deskew-Winkel im Response
|
||||
{
|
||||
"deskew_angle_deg": -1.2, # Negativer Wert = nach links geneigt
|
||||
...
|
||||
interface GridOverlayProps {
|
||||
grid: GridData
|
||||
imageUrl?: string
|
||||
onCellClick?: (cell: GridCell) => void
|
||||
selectedCell?: GridCell | null
|
||||
showEmpty?: boolean // Leere Zellen anzeigen
|
||||
showLabels?: boolean // Spaltenlabels (EN, DE, Ex)
|
||||
showNumbers?: boolean // Block-Nummern anzeigen
|
||||
highlightedBlockNumber?: number | null // Hervorgehobener Block
|
||||
className?: string
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Spalten-Erkennung mit 1mm Margin
|
||||
**Zellenstatus-Farben:**
|
||||
|
||||
Spalten werden automatisch erkannt und beginnen 1mm vor dem ersten Wort:
|
||||
| Status | Farbe | Bedeutung |
|
||||
|--------|-------|-----------|
|
||||
| `recognized` | Gruen | Text erfolgreich erkannt |
|
||||
| `problematic` | Orange | Niedriger Confidence-Wert |
|
||||
| `manual` | Blau | Manuell korrigiert |
|
||||
| `empty` | Transparent | Keine Erkennung |
|
||||
|
||||
```json
|
||||
{
|
||||
"detected_columns": [
|
||||
{
|
||||
"column_type": "english",
|
||||
"x_start": 9.52, // Prozent
|
||||
"x_end": 35.0,
|
||||
"x_start_mm": 20.0, // mm (1mm vor erstem Wort)
|
||||
"x_end_mm": 73.5,
|
||||
"word_count": 15
|
||||
},
|
||||
{
|
||||
"column_type": "german",
|
||||
"x_start_mm": 74.0,
|
||||
"x_end_mm": 140.0,
|
||||
"word_count": 15
|
||||
},
|
||||
{
|
||||
"column_type": "example",
|
||||
"x_start_mm": 141.0,
|
||||
"x_end_mm": 200.0,
|
||||
"word_count": 12
|
||||
}
|
||||
]
|
||||
### BlockReviewPanel
|
||||
|
||||
Panel zur Block-fuer-Block Ueberpruefung der OCR-Ergebnisse.
|
||||
|
||||
**Datei:** `/admin-v2/components/ocr/BlockReviewPanel.tsx`
|
||||
|
||||
```typescript
|
||||
interface BlockReviewPanelProps {
|
||||
grid: GridData
|
||||
methodResults: Record<string, { vocabulary: Array<...> }>
|
||||
currentBlockNumber: number
|
||||
onBlockChange: (blockNumber: number) => void
|
||||
onApprove: (blockNumber: number, methodId: string, text: string) => void
|
||||
onCorrect: (blockNumber: number, correctedText: string) => void
|
||||
onSkip: (blockNumber: number) => void
|
||||
reviewData: Record<number, BlockReviewData>
|
||||
className?: string
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Zellen-Status
|
||||
**Review-Status:**
|
||||
|
||||
| Status | Beschreibung |
|
||||
|--------|--------------|
|
||||
| `empty` | Keine OCR-Erkennung in dieser Zelle |
|
||||
| `recognized` | Text erkannt mit Confidence ≥ 50% |
|
||||
| `problematic` | Text erkannt mit Confidence < 50% |
|
||||
| `manual` | Manuell korrigiert |
|
||||
| `pending` | Noch nicht ueberprueft |
|
||||
| `approved` | OCR-Ergebnis akzeptiert |
|
||||
| `corrected` | Manuell korrigiert |
|
||||
| `skipped` | Uebersprungen |
|
||||
|
||||
---
|
||||
### BlockReviewSummary
|
||||
|
||||
## API-Endpoints
|
||||
Zusammenfassung aller ueberprueften Bloecke.
|
||||
|
||||
### POST /api/v1/ocr/analyze-grid
|
||||
|
||||
Analysiert ein Bild und erkennt die Vokabeltabellen-Struktur.
|
||||
|
||||
**Request:**
|
||||
```json
|
||||
{
|
||||
"image_base64": "data:image/jpeg;base64,...",
|
||||
"min_confidence": 0.5,
|
||||
"padding": 2.0
|
||||
}
|
||||
```
|
||||
|
||||
**Response:**
|
||||
```json
|
||||
{
|
||||
"cells": [
|
||||
[
|
||||
{
|
||||
"row": 0,
|
||||
"col": 0,
|
||||
"x": 10.0,
|
||||
"y": 15.0,
|
||||
"width": 25.0,
|
||||
"height": 3.0,
|
||||
"x_mm": 21.0,
|
||||
"y_mm": 44.55,
|
||||
"width_mm": 52.5,
|
||||
"height_mm": 8.91,
|
||||
"text": "house",
|
||||
"confidence": 0.95,
|
||||
"status": "recognized",
|
||||
"column_type": "english",
|
||||
"logical_row": 0,
|
||||
"logical_col": 0
|
||||
}
|
||||
]
|
||||
],
|
||||
"detected_columns": [...],
|
||||
"page_dimensions": {
|
||||
"width_mm": 210.0,
|
||||
"height_mm": 297.0,
|
||||
"format": "A4"
|
||||
},
|
||||
"deskew_angle_deg": -0.5,
|
||||
"statistics": {
|
||||
"total_cells": 45,
|
||||
"recognized_cells": 42,
|
||||
"problematic_cells": 3,
|
||||
"empty_cells": 0
|
||||
}
|
||||
```typescript
|
||||
interface BlockReviewSummaryProps {
|
||||
reviewData: Record<number, BlockReviewData>
|
||||
totalBlocks: number
|
||||
onBlockClick: (blockNumber: number) => void
|
||||
className?: string
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Frontend-Komponenten
|
||||
## OCR-Methoden
|
||||
|
||||
### GridOverlay.tsx
|
||||
|
||||
Zeigt die erkannten Zellen als farbiges Overlay über dem Bild.
|
||||
|
||||
**Props:**
|
||||
```typescript
|
||||
interface GridOverlayProps {
|
||||
cells: GridCell[][]
|
||||
imageWidth: number
|
||||
imageHeight: number
|
||||
showLabels?: boolean
|
||||
onCellClick?: (cell: GridCell) => void
|
||||
}
|
||||
```
|
||||
|
||||
**Farbkodierung:**
|
||||
- Grün: `recognized` (gut erkannt)
|
||||
- Gelb: `problematic` (niedrige Confidence)
|
||||
- Grau: `empty`
|
||||
- Blau: `manual` (manuell korrigiert)
|
||||
|
||||
### CellEditPopup.tsx
|
||||
|
||||
Popup zum Bearbeiten einer Zelle.
|
||||
|
||||
**Features:**
|
||||
- Text bearbeiten
|
||||
- Spaltentyp ändern (English/German/Example)
|
||||
- Confidence anzeigen
|
||||
- mm-Koordinaten anzeigen
|
||||
- Keyboard-Shortcuts: Ctrl+Enter (Speichern), Esc (Abbrechen)
|
||||
| ID | Name | Beschreibung |
|
||||
|----|------|--------------|
|
||||
| `vision_llm` | Vision LLM | Qwen VL 32B ueber Ollama |
|
||||
| `tesseract` | Tesseract | Klassisches OCR (lokal) |
|
||||
| `paddleocr` | PaddleOCR | PaddleOCR Engine |
|
||||
| `claude_vision` | Claude Vision | Anthropic Claude Vision API |
|
||||
|
||||
---
|
||||
|
||||
## Worksheet-Editor Integration
|
||||
## API Endpoints
|
||||
|
||||
### Export
|
||||
### Session Management
|
||||
|
||||
Der "Zum Editor exportieren" Button speichert die OCR-Daten in localStorage:
|
||||
| Method | Endpoint | Beschreibung |
|
||||
|--------|----------|--------------|
|
||||
| POST | `/api/v1/vocab/upload-pdf-info` | PDF hochladen |
|
||||
| GET | `/api/v1/vocab/sessions/{id}` | Session-Details |
|
||||
| DELETE | `/api/v1/vocab/sessions/{id}` | Session loeschen |
|
||||
|
||||
```typescript
|
||||
interface OCRExportData {
|
||||
version: '1.0'
|
||||
source: 'ocr-compare'
|
||||
exported_at: string
|
||||
session_id: string
|
||||
page_number: number
|
||||
page_dimensions: {
|
||||
width_mm: number
|
||||
height_mm: number
|
||||
format: string
|
||||
}
|
||||
words: OCRWord[]
|
||||
detected_columns: DetectedColumn[]
|
||||
### Bildexport
|
||||
|
||||
| Method | Endpoint | Beschreibung |
|
||||
|--------|----------|--------------|
|
||||
| GET | `/api/v1/vocab/sessions/{id}/pdf-thumbnail/{page}` | Thumbnail (zoom=0.5) |
|
||||
| GET | `/api/v1/vocab/sessions/{id}/pdf-thumbnail/{page}?hires=true` | High-Res (zoom=2.0) |
|
||||
|
||||
### Grid-Erkennung
|
||||
|
||||
| Method | Endpoint | Beschreibung |
|
||||
|--------|----------|--------------|
|
||||
| POST | `/api/v1/vocab/sessions/{id}/detect-grid` | Grid-Struktur erkennen |
|
||||
| POST | `/api/v1/vocab/sessions/{id}/run-ocr` | OCR auf Grid ausfuehren |
|
||||
|
||||
---
|
||||
|
||||
## Session Persistence
|
||||
|
||||
Die aktive Session wird im localStorage gespeichert:
|
||||
|
||||
```javascript
|
||||
// Speichern
|
||||
localStorage.setItem('ocr-compare-active-session', sessionId)
|
||||
|
||||
// Wiederherstellen beim Seitenladen
|
||||
const lastSessionId = localStorage.getItem('ocr-compare-active-session')
|
||||
if (lastSessionId) {
|
||||
// Session-Daten laden
|
||||
}
|
||||
```
|
||||
|
||||
**localStorage Keys:**
|
||||
- `ocr_export_{session_id}_{page_number}`: Export-Daten
|
||||
- `ocr_export_latest`: Referenz zum neuesten Export
|
||||
---
|
||||
|
||||
### Import im Worksheet-Editor
|
||||
## Block Review Workflow
|
||||
|
||||
1. Öffnen Sie den Worksheet-Editor: https://macmini/worksheet-editor
|
||||
2. Klicken Sie auf den OCR-Import Button (grünes Icon)
|
||||
3. Die Wörter werden auf dem Canvas platziert
|
||||
1. **PDF hochladen** - Dokument in das System laden
|
||||
2. **Grid erkennen** - Automatische Tabellenerkennung
|
||||
3. **OCR ausfuehren** - Alle Methoden parallel ausfuehren
|
||||
4. **Block Review starten** - "Block Review" Button klicken
|
||||
5. **Bloecke pruefen** - Fuer jeden Block:
|
||||
- Ergebnisse aller Methoden vergleichen
|
||||
- Bestes Ergebnis waehlen oder manuell korrigieren
|
||||
6. **Zusammenfassung** - Uebersicht der Korrekturen
|
||||
|
||||
---
|
||||
|
||||
## High-Resolution Bilder
|
||||
|
||||
Fuer die Anzeige werden hochaufloesende Bilder verwendet:
|
||||
|
||||
**Konvertierung mm → Pixel:**
|
||||
```typescript
|
||||
const MM_TO_PX = 3.7795275591
|
||||
const x_px = word.x_mm * MM_TO_PX
|
||||
const y_px = word.y_mm * MM_TO_PX
|
||||
// Thumbnail URL mit High-Resolution Parameter
|
||||
const imageUrl = `${KLAUSUR_API}/api/v1/vocab/sessions/${sessionId}/pdf-thumbnail/${pageNumber}?hires=true`
|
||||
```
|
||||
|
||||
| Parameter | Zoom | Verwendung |
|
||||
|-----------|------|------------|
|
||||
| Ohne `hires` | 0.5 | Vorschau/Thumbnails |
|
||||
| Mit `hires=true` | 2.0 | Anzeige/OCR |
|
||||
|
||||
---
|
||||
|
||||
## Dateien
|
||||
|
||||
### Backend (klausur-service)
|
||||
|
||||
| Datei | Beschreibung |
|
||||
|-------|--------------|
|
||||
| `services/grid_detection_service.py` | Grid-Erkennung v4 mit Deskew |
|
||||
| `tests/test_grid_detection.py` | Unit Tests |
|
||||
|
||||
### Frontend (admin-v2)
|
||||
|
||||
| Datei | Beschreibung |
|
||||
|-------|--------------|
|
||||
| `app/(admin)/ai/ocr-compare/page.tsx` | Haupt-UI |
|
||||
| `components/ocr/GridOverlay.tsx` | Grid-Visualisierung |
|
||||
| `components/ocr/CellEditPopup.tsx` | Zellen-Editor |
|
||||
| `components/ocr/GridOverlay.tsx` | SVG Grid-Overlay |
|
||||
| `components/ocr/BlockReviewPanel.tsx` | Review-Panel |
|
||||
| `components/ocr/CellCorrectionDialog.tsx` | Korrektur-Dialog |
|
||||
| `components/ocr/index.ts` | Exports |
|
||||
|
||||
### Frontend (studio-v2)
|
||||
### Backend (klausur-service)
|
||||
|
||||
| Datei | Beschreibung |
|
||||
|-------|--------------|
|
||||
| `lib/worksheet-editor/ocr-integration.ts` | OCR Import/Export Utility |
|
||||
| `app/worksheet-editor/page.tsx` | Editor mit OCR-Import |
|
||||
| `components/worksheet-editor/EditorToolbar.tsx` | Toolbar mit OCR-Button |
|
||||
| `vocab_worksheet_api.py` | API-Router |
|
||||
| `hybrid_vocab_extractor.py` | OCR-Extraktion |
|
||||
|
||||
---
|
||||
|
||||
## Deployment
|
||||
## Aenderungshistorie
|
||||
|
||||
```bash
|
||||
# 1. Backend synchronisieren
|
||||
scp grid_detection_service.py macmini:.../klausur-service/backend/services/
|
||||
|
||||
# 2. Tests synchronisieren
|
||||
scp test_grid_detection.py macmini:.../klausur-service/backend/tests/
|
||||
|
||||
# 3. klausur-service neu bauen
|
||||
ssh macmini "docker compose build --no-cache klausur-service"
|
||||
|
||||
# 4. Container starten
|
||||
ssh macmini "docker compose up -d klausur-service"
|
||||
|
||||
# 5. Frontend (admin-v2) deployen
|
||||
ssh macmini "docker compose build --no-cache admin-v2 && docker compose up -d admin-v2"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verwendete Open-Source-Bibliotheken
|
||||
|
||||
| Bibliothek | Version | Lizenz | Verwendung |
|
||||
|------------|---------|--------|------------|
|
||||
| NumPy | ≥1.24 | BSD-3-Clause | Deskew-Berechnung (polyfit) |
|
||||
| OpenCV | ≥4.8 | Apache-2.0 | Bildverarbeitung (optional) |
|
||||
| PaddleOCR | 2.7 | Apache-2.0 | OCR-Erkennung |
|
||||
| Fabric.js | 6.x | MIT | Canvas-Rendering (Frontend) |
|
||||
|
||||
---
|
||||
|
||||
## Fehlerbehandlung
|
||||
|
||||
### Häufige Probleme
|
||||
|
||||
| Problem | Lösung |
|
||||
|---------|--------|
|
||||
| "Grid analysieren" lädt nicht | klausur-service Container prüfen |
|
||||
| Keine Zellen erkannt | Min. Confidence reduzieren |
|
||||
| Falsche Spalten-Zuordnung | Manuell im CellEditPopup korrigieren |
|
||||
| Export funktioniert nicht | Browser-Console auf Fehler prüfen |
|
||||
|
||||
### Logging
|
||||
|
||||
```bash
|
||||
# klausur-service Logs
|
||||
docker logs breakpilot-pwa-klausur-service --tail=100
|
||||
|
||||
# Grid Detection spezifisch
|
||||
docker logs breakpilot-pwa-klausur-service 2>&1 | grep "grid_detection"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Änderungshistorie
|
||||
|
||||
| Version | Datum | Änderungen |
|
||||
|---------|-------|------------|
|
||||
| 4.0 | 2026-02-08 | Deskew-Korrektur, 1mm Column Margin |
|
||||
| 3.0 | 2026-02-07 | mm-Koordinatensystem |
|
||||
| 2.0 | 2026-02-06 | Spalten-Erkennung |
|
||||
| 1.0 | 2026-02-05 | Initiale Implementierung |
|
||||
|
||||
---
|
||||
|
||||
## Referenzen
|
||||
|
||||
- [Worksheet-Editor Architektur](Worksheet-Editor-Architecture.md)
|
||||
- [OCR Labeling Spec](OCR-Labeling-Spec.md)
|
||||
- [SBOM](/infrastructure/sbom)
|
||||
| Datum | Aenderung |
|
||||
|-------|-----------|
|
||||
| 2026-02-08 | Block Review Feature hinzugefuegt |
|
||||
| 2026-02-08 | High-Resolution Bilder aktiviert |
|
||||
| 2026-02-08 | Session Persistence implementiert |
|
||||
| 2026-02-07 | Grid Detection und Multi-Method OCR |
|
||||
|
||||
Reference in New Issue
Block a user