Protokoll #21956

ID21956
Zeitstempel2025-12-27 11:40:01.802004
Clientroot
IP145.224.72.140
Modellclaude-sonnet-4-20250514
Statuscompleted
Tokens2,641 (Input: 30, Output: 2,611)
Dauer81 ms
Request-Zeit2025-12-27 11:40:01.802004
Response-Zeit2025-12-27 11:40:01.882660

Request

{
    "event": "PreToolUse",
    "tool_name": "mcp__mcp-tasks__tasks_status",
    "tool_input": {
        "id": 442,
        "status": "in_progress"
    }
}

Response

{
    "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\": \"in_progress\",\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:40:01.818302\",\n    \"completed_at\": null,\n    \"metadata\": {}\n  },\n  \"message\": \"Task #442 status changed: pending -> in_progress\"\n}"
        }
    ]
}
← Vorheriger Zur Liste Nächster →