{
"tool_response": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"task\": {\n \"id\": 442,\n \"uuid\": \"b22debfc-fde0-4a34-bf6d-08a0bd96110e\",\n \"title\": \"PDF-Rotationserkennung und -korrektur implementieren\",\n \"description\": \"## KONTEXT\\n\\nPDF-Dokumente enthalten teilweise um 90°\/180°\/270° gedrehte Seiten. Die aktuelle Pipeline ignoriert die Rotation, was zu:\\n- Fehlerhafter OCR-Extraktion\\n- Unlesbaren Vision-Analysen\\n- Korrupten Embeddings\\n\\nführt.\\n\\n---\\n\\n## CODE-ANALYSE\\n\\n### Betroffene Dateien\\n\\n| Datei | Funktion | Zeilen | Problem |\\n|-------|----------|--------|---------|\\n| `extract.py` | `extract_pdf()` | 13-45 | Keine Rotationserkennung |\\n| `vision.py` | `pdf_to_images()` | 30-67 | Rotation wird ignoriert |\\n| `config.py` | OCR-Settings | 74-76 | OCR_ENABLED=True |\\n\\n### Aktuelle Implementierung\\n\\n**extract.py:13-45**\\n```python\\ndef extract_pdf(file_path):\\n import fitz # PyMuPDF\\n doc = fitz.open(file_path)\\n pages = []\\n \\n for page_num, page in enumerate(doc):\\n text = page.get_text() # ← Ignoriert Rotation\\n \\n # OCR-Fallback (Zeile 24-40)\\n if OCR_ENABLED and len(text.strip()) < 50:\\n pix = page.get_pixmap(dpi=300) # ← Rotation nicht berücksichtigt\\n img = Image.open(io.BytesIO(img_data))\\n ocr_text = pytesseract.image_to_string(img, lang=OCR_LANGUAGE)\\n # ← Keine Orientierungserkennung\\n```\\n\\n**vision.py:30-67**\\n```python\\ndef pdf_to_images(file_path, dpi=IMAGE_DPI):\\n import fitz\\n doc = fitz.open(file_path)\\n \\n for page_num in range(len(doc)):\\n page = doc[page_num]\\n mat = fitz.Matrix(dpi \/ 72, dpi \/ 72)\\n pix = page.get_pixmap(matrix=mat) # ← Rotation ignoriert\\n```\\n\\n### Systemzustand\\n\\n| Komponente | Status |\\n|------------|--------|\\n| PyMuPDF | ✓ 1.26.7 installiert |\\n| pytesseract | ✓ 0.3.13 installiert |\\n| Pillow | ✓ 12.0.0 installiert |\\n| **tesseract binary** | ❌ **NICHT INSTALLIERT** |\\n| OCR_ENABLED | True (aber funktioniert nicht!) |\\n\\n---\\n\\n## LÖSUNG: Mehrstufige Orientierungserkennung\\n\\n### Architektur\\n\\n```\\n┌─────────────────────────────────────────────────────────┐\\n│ Stufe 1: PDF-Metadaten (page.rotation) │\\n│ PyMuPDF liest \/Rotate Flag aus PDF │\\n│ → Schnell, kostenlos, 0ms │\\n└─────────────────────┬───────────────────────────────────┘\\n │ Falls rotation == 0\\n ▼\\n┌─────────────────────────────────────────────────────────┐\\n│ Stufe 2: Tesseract OSD (Orientation Script Detection) │\\n│ pytesseract.image_to_osd(img) │\\n│ → Erkennt 0°\/90°\/180°\/270°, Confidence-Score │\\n│ → ~50-100ms pro Seite │\\n└─────────────────────┬───────────────────────────────────┘\\n │ Falls Confidence < 2.0\\n ▼\\n┌─────────────────────────────────────────────────────────┐\\n│ Stufe 3: Vision-LLM Fallback (optional) │\\n│ \\\"Ist diese Seite korrekt orientiert?\\\" │\\n│ → Für Bilder ohne Text │\\n└─────────────────────────────────────────────────────────┘\\n```\\n\\n### Implementierung\\n\\n#### 1. Voraussetzung: Tesseract installieren\\n\\n```bash\\napt-get install tesseract-ocr tesseract-ocr-deu\\n```\\n\\n#### 2. Neue Datei: `\/var\/www\/scripts\/pipeline\/orientation.py`\\n\\n```python\\n\\\"\\\"\\\"\\nPage Orientation Detection Module\\nDetects and corrects rotated PDF pages.\\n\\\"\\\"\\\"\\n\\nimport io\\nfrom PIL import Image\\nimport pytesseract\\nimport fitz # PyMuPDF\\n\\nfrom db import db\\n\\n\\ndef detect_orientation(image_bytes: bytes) -> dict:\\n \\\"\\\"\\\"\\n Detect page orientation using Tesseract OSD.\\n \\n Args:\\n image_bytes: PNG\/JPEG image as bytes\\n \\n Returns:\\n dict: {\\n 'rotation': int (0, 90, 180, 270),\\n 'confidence': float,\\n 'script': str,\\n 'method': str ('osd' or 'fallback')\\n }\\n \\\"\\\"\\\"\\n try:\\n img = Image.open(io.BytesIO(image_bytes))\\n osd = pytesseract.image_to_osd(img, output_type=pytesseract.Output.DICT)\\n \\n return {\\n 'rotation': osd.get('rotate', 0),\\n 'confidence': osd.get('orientation_conf', 0.0),\\n 'script': osd.get('script', 'Unknown'),\\n 'method': 'osd'\\n }\\n except Exception as e:\\n db.log(\\\"WARNING\\\", f\\\"OSD detection failed: {e}\\\")\\n return {\\n 'rotation': 0,\\n 'confidence': 0.0,\\n 'script': 'Unknown',\\n 'method': 'fallback'\\n }\\n\\n\\ndef get_page_rotation(page) -> int:\\n \\\"\\\"\\\"\\n Get effective rotation for a PDF page.\\n \\n Combines PDF metadata rotation with detected orientation.\\n \\n Args:\\n page: PyMuPDF page object\\n \\n Returns:\\n int: Total rotation needed (0, 90, 180, 270)\\n \\\"\\\"\\\"\\n # Stufe 1: PDF-Metadaten\\n pdf_rotation = page.rotation # 0, 90, 180, 270\\n \\n if pdf_rotation != 0:\\n return pdf_rotation\\n \\n # Stufe 2: Tesseract OSD\\n pix = page.get_pixmap(dpi=150) # Lower DPI for speed\\n img_bytes = pix.tobytes(\\\"png\\\")\\n \\n detection = detect_orientation(img_bytes)\\n \\n if detection['confidence'] >= 2.0:\\n return detection['rotation']\\n \\n return 0\\n\\n\\ndef rotate_image(image_bytes: bytes, rotation: int) -> bytes:\\n \\\"\\\"\\\"\\n Rotate image by specified degrees.\\n \\n Args:\\n image_bytes: Original image\\n rotation: Degrees to rotate (90, 180, 270)\\n \\n Returns:\\n bytes: Rotated image as PNG\\n \\\"\\\"\\\"\\n if rotation == 0:\\n return image_bytes\\n \\n img = Image.open(io.BytesIO(image_bytes))\\n \\n # PIL rotation is counter-clockwise, PDF is clockwise\\n rotated = img.rotate(-rotation, expand=True)\\n \\n output = io.BytesIO()\\n rotated.save(output, format='PNG')\\n return output.getvalue()\\n```\\n\\n#### 3. Integration in extract.py\\n\\n**Änderung in `extract_pdf()` (Zeile 20-27 einfügen):**\\n\\n```python\\ndef extract_pdf(file_path):\\n import fitz\\n from orientation import get_page_rotation, rotate_image\\n \\n doc = fitz.open(file_path)\\n pages = []\\n \\n for page_num, page in enumerate(doc):\\n # NEU: Rotation erkennen\\n rotation = get_page_rotation(page)\\n \\n # Text mit korrekter Rotation extrahieren\\n if rotation != 0:\\n # Seite vor Extraktion rotieren\\n page.set_rotation(rotation)\\n \\n text = page.get_text()\\n \\n # OCR-Fallback mit rotiertem Bild\\n if OCR_ENABLED and len(text.strip()) < 50:\\n pix = page.get_pixmap(dpi=300)\\n img_data = pix.tobytes(\\\"png\\\")\\n \\n # NEU: Bild rotieren falls nötig\\n if rotation != 0:\\n img_data = rotate_image(img_data, rotation)\\n \\n img = Image.open(io.BytesIO(img_data))\\n ocr_text = pytesseract.image_to_string(img, lang=OCR_LANGUAGE)\\n```\\n\\n#### 4. Integration in vision.py\\n\\n**Änderung in `pdf_to_images()` (Zeile 46-54):**\\n\\n```python\\ndef pdf_to_images(file_path, dpi=IMAGE_DPI):\\n import fitz\\n from orientation import get_page_rotation, rotate_image\\n \\n doc = fitz.open(file_path)\\n pages = []\\n \\n for page_num in range(len(doc)):\\n page = doc[page_num]\\n \\n # NEU: Rotation erkennen\\n rotation = get_page_rotation(page)\\n \\n mat = fitz.Matrix(dpi \/ 72, dpi \/ 72)\\n pix = page.get_pixmap(matrix=mat)\\n img_bytes = pix.tobytes(IMAGE_FORMAT)\\n \\n # NEU: Bild rotieren falls nötig\\n if rotation != 0:\\n img_bytes = rotate_image(img_bytes, rotation)\\n db.log(\\\"INFO\\\", f\\\"Page {page_num+1} rotated by {rotation}°\\\")\\n```\\n\\n---\\n\\n## KONFIGURATION\\n\\n**config.py erweitern:**\\n\\n```python\\n# Rotation Detection Settings\\nROTATION_DETECTION_ENABLED = True\\nROTATION_OSD_CONFIDENCE_THRESHOLD = 2.0\\nROTATION_USE_VISION_FALLBACK = False # Für Bilder ohne Text\\n```\\n\\n---\\n\\n## TESTPLAN\\n\\n1. [ ] Tesseract installieren: `apt-get install tesseract-ocr tesseract-ocr-deu`\\n2. [ ] Tesseract verifizieren: `tesseract --version`\\n3. [ ] orientation.py erstellen\\n4. [ ] Unit-Tests für detect_orientation()\\n5. [ ] extract.py integrieren\\n6. [ ] vision.py integrieren\\n7. [ ] Test mit gedrehtem PDF:\\n - 90° gedrehte Seite → korrekt erkannt\\n - 180° gedrehte Seite → korrekt erkannt\\n - OCR-Text lesbar\\n - Vision-Analyse korrekt\\n8. [ ] Performance-Test: <100ms overhead pro Seite\\n\\n---\\n\\n## VALIDIERUNG\\n\\n```bash\\n# Tesseract OSD Test\\necho \\\"Test\\\" | tesseract stdin stdout --psm 0\\n\\n# Python-Test\\npython3 -c \\\"\\nimport pytesseract\\nfrom PIL import Image\\nimg = Image.new('RGB', (100, 100), 'white')\\nprint(pytesseract.image_to_osd(img))\\n\\\"\\n```\\n\\n---\\n\\n## ABHÄNGIGKEITEN\\n\\n| Paket | Version | Status |\\n|-------|---------|--------|\\n| tesseract-ocr | >= 4.0 | ❌ INSTALLIEREN |\\n| tesseract-ocr-deu | - | ❌ INSTALLIEREN |\\n| PyMuPDF | 1.26.7 | ✓ |\\n| pytesseract | 0.3.13 | ✓ |\\n| Pillow | 12.0.0 | ✓ |\\n\\n---\\n\\n## GESCHÄTZTER AUFWAND\\n\\n| Schritt | Zeit |\\n|---------|------|\\n| Tesseract installieren | 5 min |\\n| orientation.py erstellen | 30 min |\\n| extract.py anpassen | 15 min |\\n| vision.py anpassen | 15 min |\\n| config.py erweitern | 5 min |\\n| Tests | 30 min |\\n| **Gesamt** | **~100 min** |\",\n \"type\": \"ai_task\",\n \"status\": \"completed\",\n \"created_by\": \"mcp-tasks\",\n \"created_by_type\": \"ai\",\n \"parent_task_id\": null,\n \"due_date\": null,\n \"created_at\": \"2025-12-27T11:37:05.363073\",\n \"updated_at\": \"2025-12-27T11:44:51.000825\",\n \"completed_at\": \"2025-12-27T11:44:51.000828\",\n \"metadata\": {}\n },\n \"message\": \"Task #442 status changed: in_progress -> completed\",\n \"warning\": \"Hinweis: Code-Task ohne Quality-Check abgeschlossen. Empfehlung:... [TRUNCATED-48675f883abb5f51]"
}
]
}