From b91f799ccfd19f432dcf53553c1d3c30bb7d7106 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Wed, 11 Mar 2026 08:29:06 +0100 Subject: [PATCH] fix: Zeilen-Regularisierung im Overlay ueberspringen (generisch fuer gemischte Inhalte) Seiten mit Info-Boxen (andere Zeilenhoehe) fuehren dazu, dass _regularize_row_grid die Zeilenpositionen verzerrt. Neuer skip_regularize Parameter nutzt stattdessen die gap-basierten Zeilen, die der tatsaechlichen Seitengeometrie folgen. Co-Authored-By: Claude Opus 4.6 --- admin-lehrer/app/(admin)/ai/ocr-overlay/page.tsx | 2 +- .../components/ocr-pipeline/StepRowDetection.tsx | 11 ++++++++--- klausur-service/backend/cv_layout.py | 10 ++++++++-- klausur-service/backend/ocr_pipeline_api.py | 9 ++++++--- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/admin-lehrer/app/(admin)/ai/ocr-overlay/page.tsx b/admin-lehrer/app/(admin)/ai/ocr-overlay/page.tsx index b9dd5b0..b7e9a48 100644 --- a/admin-lehrer/app/(admin)/ai/ocr-overlay/page.tsx +++ b/admin-lehrer/app/(admin)/ai/ocr-overlay/page.tsx @@ -216,7 +216,7 @@ export default function OcrOverlayPage() { case 3: return case 4: - return + return case 5: return case 6: diff --git a/admin-lehrer/components/ocr-pipeline/StepRowDetection.tsx b/admin-lehrer/components/ocr-pipeline/StepRowDetection.tsx index 6d971ad..34e0aec 100644 --- a/admin-lehrer/components/ocr-pipeline/StepRowDetection.tsx +++ b/admin-lehrer/components/ocr-pipeline/StepRowDetection.tsx @@ -8,9 +8,11 @@ const KLAUSUR_API = '/klausur-api' interface StepRowDetectionProps { sessionId: string | null onNext: () => void + /** Skip word-center regularization (better for mixed-content pages with boxes) */ + skipRegularize?: boolean } -export function StepRowDetection({ sessionId, onNext }: StepRowDetectionProps) { +export function StepRowDetection({ sessionId, onNext, skipRegularize = false }: StepRowDetectionProps) { const [rowResult, setRowResult] = useState(null) const [detecting, setDetecting] = useState(false) const [error, setError] = useState(null) @@ -46,7 +48,10 @@ export function StepRowDetection({ sessionId, onNext }: StepRowDetectionProps) { setDetecting(true) setError(null) try { - const res = await fetch(`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/rows`, { + const rowsUrl = skipRegularize + ? `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/rows?skip_regularize=true` + : `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/rows` + const res = await fetch(rowsUrl, { method: 'POST', }) if (!res.ok) { @@ -60,7 +65,7 @@ export function StepRowDetection({ sessionId, onNext }: StepRowDetectionProps) { } finally { setDetecting(false) } - }, [sessionId]) + }, [sessionId, skipRegularize]) const handleGroundTruth = useCallback(async (isCorrect: boolean) => { if (!sessionId) return diff --git a/klausur-service/backend/cv_layout.py b/klausur-service/backend/cv_layout.py index d269fac..71a7066 100644 --- a/klausur-service/backend/cv_layout.py +++ b/klausur-service/backend/cv_layout.py @@ -1525,6 +1525,7 @@ def detect_row_geometry( word_dicts: List[Dict], left_x: int, right_x: int, top_y: int, bottom_y: int, + skip_regularize: bool = False, ) -> List['RowGeometry']: """Detect row geometry using horizontal whitespace-gap analysis. @@ -1789,8 +1790,13 @@ def detect_row_geometry( # and evenly-spaced rows than the gap-based approach alone. # Also detects section breaks (headings, paragraphs) where the pitch # exceeds 1.8× the median, and handles each section independently. - rows = _regularize_row_grid(rows, word_dicts, left_x, right_x, top_y, - content_w, content_h, inv) + # + # skip_regularize=True: Keep gap-based rows as-is. Useful for full-page + # overlay rendering where mixed content (info boxes, different line + # spacings) must preserve original geometry faithfully. + if not skip_regularize: + rows = _regularize_row_grid(rows, word_dicts, left_x, right_x, top_y, + content_w, content_h, inv) type_counts = {} for r in rows: diff --git a/klausur-service/backend/ocr_pipeline_api.py b/klausur-service/backend/ocr_pipeline_api.py index 998870a..12d32c0 100644 --- a/klausur-service/backend/ocr_pipeline_api.py +++ b/klausur-service/backend/ocr_pipeline_api.py @@ -1577,7 +1577,7 @@ async def _get_columns_overlay(session_id: str) -> Response: # --------------------------------------------------------------------------- @router.post("/sessions/{session_id}/rows") -async def detect_rows(session_id: str): +async def detect_rows(session_id: str, skip_regularize: bool = False): """Run row detection on the cropped (or dewarped) image using horizontal gap analysis.""" if session_id not in _cache: await _load_session_to_cache(session_id) @@ -1686,6 +1686,7 @@ async def detect_rows(session_id: str): combined_h = combined_inv.shape[0] rows = detect_row_geometry( combined_inv, combined_words, left_x, right_x, 0, combined_h, + skip_regularize=skip_regularize, ) # Remap y-coordinates back to absolute page coords @@ -1702,10 +1703,12 @@ async def detect_rows(session_id: str): r.y = abs_y r.height = abs_y_end - abs_y else: - rows = detect_row_geometry(inv, word_dicts, left_x, right_x, top_y, bottom_y) + rows = detect_row_geometry(inv, word_dicts, left_x, right_x, top_y, bottom_y, + skip_regularize=skip_regularize) else: # No boxes — standard row detection - rows = detect_row_geometry(inv, word_dicts, left_x, right_x, top_y, bottom_y) + rows = detect_row_geometry(inv, word_dicts, left_x, right_x, top_y, bottom_y, + skip_regularize=skip_regularize) duration = time.time() - t0