fix: einheitliche Schriftgroesse + Border-Cluster-Filter im Overlay
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 35s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m24s
CI / test-python-agent-core (push) Successful in 25s
CI / test-nodejs-website (push) Successful in 25s
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 35s
CI / test-go-edu-search (push) Successful in 31s
CI / test-python-klausur (push) Failing after 2m24s
CI / test-python-agent-core (push) Successful in 25s
CI / test-nodejs-website (push) Successful in 25s
1. Schriftgroesse basiert jetzt auf Median-Zeilenhoehe statt individueller Zellhoehe — keine Groessensprunge in Box-Bereichen 2. Sehr schmale Pixel-Cluster (< 0.5% Zellbreite) werden gefiltert, damit Box-Rahmen nicht als Textposition erkannt werden Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -316,6 +316,14 @@ export function OverlayReconstruction({ sessionId, onNext }: OverlayReconstructi
|
|||||||
const imgH = imageNaturalSize?.h || 1
|
const imgH = imageNaturalSize?.h || 1
|
||||||
const containerH = reconWidth * (imgH / imgW)
|
const containerH = reconWidth * (imgH / imgW)
|
||||||
|
|
||||||
|
// Compute median cell height (in px) for consistent font sizing
|
||||||
|
const medianCellHeightPx = useMemo(() => {
|
||||||
|
if (cells.length === 0) return 40
|
||||||
|
const heights = cells.map(c => containerH * (c.bboxPct.h / 100)).sort((a, b) => a - b)
|
||||||
|
const mid = Math.floor(heights.length / 2)
|
||||||
|
return heights.length % 2 === 0 ? (heights[mid - 1] + heights[mid]) / 2 : heights[mid]
|
||||||
|
}, [cells, containerH])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
{/* Toolbar */}
|
{/* Toolbar */}
|
||||||
@@ -460,13 +468,12 @@ export function OverlayReconstruction({ sessionId, onNext }: OverlayReconstructi
|
|||||||
const edited = isEdited(cell)
|
const edited = isEdited(cell)
|
||||||
const wordPos = cellWordPositions.get(cell.cellId)
|
const wordPos = cellWordPositions.get(cell.cellId)
|
||||||
const bboxPct = cell.bboxPct
|
const bboxPct = cell.bboxPct
|
||||||
const cellHeightPx = containerH * (bboxPct.h / 100)
|
|
||||||
const colorValue = textColor === 'black' ? '#1a1a1a' : textColor
|
const colorValue = textColor === 'black' ? '#1a1a1a' : textColor
|
||||||
|
|
||||||
// Pixel-analysed: render word-groups at detected positions
|
// Pixel-analysed: render word-groups at detected positions
|
||||||
if (wordPos && wordPos.length > 0) {
|
if (wordPos && wordPos.length > 0) {
|
||||||
return wordPos.map((wp, i) => {
|
return wordPos.map((wp, i) => {
|
||||||
const autoFontPx = cellHeightPx * wp.fontRatio * fontScale
|
const autoFontPx = medianCellHeightPx * wp.fontRatio * fontScale
|
||||||
const fs = Math.max(6, autoFontPx)
|
const fs = Math.max(6, autoFontPx)
|
||||||
|
|
||||||
if (wordPos.length > 1) {
|
if (wordPos.length > 1) {
|
||||||
@@ -536,7 +543,7 @@ export function OverlayReconstruction({ sessionId, onNext }: OverlayReconstructi
|
|||||||
// Fallback: no pixel data — single input at cell bbox
|
// Fallback: no pixel data — single input at cell bbox
|
||||||
if (!cell.text) return null
|
if (!cell.text) return null
|
||||||
|
|
||||||
const fontSize = Math.max(6, cellHeightPx * fontScale)
|
const fontSize = Math.max(6, medianCellHeightPx * fontScale)
|
||||||
return (
|
return (
|
||||||
<div key={cell.cellId} className="absolute group" style={{
|
<div key={cell.cellId} className="absolute group" style={{
|
||||||
left: `${bboxPct.x}%`,
|
left: `${bboxPct.x}%`,
|
||||||
|
|||||||
@@ -112,6 +112,11 @@ export function usePixelWordPositions(
|
|||||||
|
|
||||||
if (clusters.length === 0) continue
|
if (clusters.length === 0) continue
|
||||||
|
|
||||||
|
// Filter out very narrow clusters (likely box borders / vertical lines)
|
||||||
|
const minClusterW = Math.max(3, Math.round(cw * 0.005))
|
||||||
|
clusters = clusters.filter(c => (c.end - c.start + 1) > minClusterW)
|
||||||
|
if (clusters.length === 0) continue
|
||||||
|
|
||||||
if (rotation === 180) {
|
if (rotation === 180) {
|
||||||
clusters = clusters.map(c => ({
|
clusters = clusters.map(c => ({
|
||||||
start: cw - 1 - c.end,
|
start: cw - 1 - c.end,
|
||||||
|
|||||||
Reference in New Issue
Block a user