fix: Overlay-Zellen ohne _heal_row_gaps positionieren (skip_heal_gaps)
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 36s
CI / test-go-edu-search (push) Successful in 35s
CI / test-python-klausur (push) Failing after 2m12s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 21s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 36s
CI / test-go-edu-search (push) Successful in 35s
CI / test-python-klausur (push) Failing after 2m12s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 21s
_heal_row_gaps verschiebt Zell-Positionen nach Entfernung von Artefakt-Zeilen, was im Overlay zu sichtbarem Versatz fuehrt (z.B. 23px bei "badge"). Neuer skip_heal_gaps Parameter in build_cell_grid_v2 und words-Endpoint behaelt die exakten Zeilen-Positionen bei. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -218,7 +218,7 @@ export default function OcrOverlayPage() {
|
||||
case 4:
|
||||
return <StepRowDetection sessionId={sessionId} onNext={handleNext} />
|
||||
case 5:
|
||||
return <StepWordRecognition sessionId={sessionId} onNext={handleNext} goToStep={goToStep} />
|
||||
return <StepWordRecognition sessionId={sessionId} onNext={handleNext} goToStep={goToStep} skipHealGaps />
|
||||
case 6:
|
||||
return <OverlayReconstruction sessionId={sessionId} onNext={handleNext} />
|
||||
default:
|
||||
|
||||
@@ -44,9 +44,11 @@ interface StepWordRecognitionProps {
|
||||
sessionId: string | null
|
||||
onNext: () => void
|
||||
goToStep: (step: number) => void
|
||||
/** Skip _heal_row_gaps in cell grid (better overlay positioning) */
|
||||
skipHealGaps?: boolean
|
||||
}
|
||||
|
||||
export function StepWordRecognition({ sessionId, onNext, goToStep }: StepWordRecognitionProps) {
|
||||
export function StepWordRecognition({ sessionId, onNext, goToStep, skipHealGaps = false }: StepWordRecognitionProps) {
|
||||
const [gridResult, setGridResult] = useState<GridResult | null>(null)
|
||||
const [detecting, setDetecting] = useState(false)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
@@ -110,7 +112,7 @@ export function StepWordRecognition({ sessionId, onNext, goToStep }: StepWordRec
|
||||
let res: Response | null = null
|
||||
for (let attempt = 0; attempt < 2; attempt++) {
|
||||
res = await fetch(
|
||||
`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/words?stream=true&engine=${eng}&pronunciation=${pronunciation}`,
|
||||
`${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/words?stream=true&engine=${eng}&pronunciation=${pronunciation}${skipHealGaps ? '&skip_heal_gaps=true' : ''}`,
|
||||
{ method: 'POST' },
|
||||
)
|
||||
if (res.ok) break
|
||||
|
||||
@@ -264,6 +264,7 @@ def build_cell_grid_v2(
|
||||
lang: str = "eng+deu",
|
||||
ocr_engine: str = "auto",
|
||||
img_bgr: Optional[np.ndarray] = None,
|
||||
skip_heal_gaps: bool = False,
|
||||
) -> Tuple[List[Dict[str, Any]], List[Dict[str, Any]]]:
|
||||
"""Hybrid Grid: full-page OCR for broad columns, cell-crop for narrow ones.
|
||||
|
||||
@@ -330,7 +331,12 @@ def build_cell_grid_v2(
|
||||
else:
|
||||
bottom_bound = content_rows[-1].y + content_rows[-1].height
|
||||
|
||||
_heal_row_gaps(content_rows, top_bound=top_bound, bottom_bound=bottom_bound)
|
||||
# skip_heal_gaps: When True, keep cell positions at their exact row geometry
|
||||
# positions without expanding to fill gaps from removed rows. Useful for
|
||||
# overlay rendering where pixel-precise positioning matters more than
|
||||
# full-coverage OCR crops.
|
||||
if not skip_heal_gaps:
|
||||
_heal_row_gaps(content_rows, top_bound=top_bound, bottom_bound=bottom_bound)
|
||||
|
||||
relevant_cols.sort(key=lambda c: c.x)
|
||||
|
||||
|
||||
@@ -1857,6 +1857,7 @@ async def detect_words(
|
||||
engine: str = "auto",
|
||||
pronunciation: str = "british",
|
||||
stream: bool = False,
|
||||
skip_heal_gaps: bool = False,
|
||||
):
|
||||
"""Build word grid from columns × rows, OCR each cell.
|
||||
|
||||
@@ -1864,6 +1865,8 @@ async def detect_words(
|
||||
engine: 'auto' (default), 'tesseract', or 'rapid'
|
||||
pronunciation: 'british' (default) or 'american' — for IPA dictionary lookup
|
||||
stream: false (default) for JSON response, true for SSE streaming
|
||||
skip_heal_gaps: false (default). When true, cells keep exact row geometry
|
||||
positions without gap-healing expansion. Better for overlay rendering.
|
||||
"""
|
||||
if session_id not in _cache:
|
||||
logger.info("detect_words: session %s not in cache, loading from DB", session_id)
|
||||
@@ -2007,6 +2010,7 @@ async def detect_words(
|
||||
cells, columns_meta = build_cell_grid_v2(
|
||||
ocr_img, col_regions, row_geoms, img_w, img_h,
|
||||
ocr_engine=engine, img_bgr=dewarped_bgr,
|
||||
skip_heal_gaps=skip_heal_gaps,
|
||||
)
|
||||
duration = time.time() - t0
|
||||
|
||||
@@ -2136,6 +2140,7 @@ async def _word_batch_stream_generator(
|
||||
lambda: build_cell_grid_v2(
|
||||
ocr_img, col_regions, row_geoms, img_w, img_h,
|
||||
ocr_engine=engine, img_bgr=dewarped_bgr,
|
||||
skip_heal_gaps=skip_heal_gaps,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user