mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 17:00:23 +00:00
fix: refine thin-border rect filter to only skip dark-gray decorations
Skip only thin-border unfilled rects with near-gray color and low brightness — these are PyMuPDF get_drawings() false positives from clipping paths. Keep colored thin borders (legitimate boxes) and pure black thin borders (legitimate black frames). Added 2 tests (colored border kept, black border kept). Verified via 50-paper audit: all 14 dark-gray rects filtered, all colored/black rects preserved.
This commit is contained in:
parent
1e1acebbe8
commit
190ce2440a
3 changed files with 50 additions and 7 deletions
|
|
@ -125,7 +125,6 @@ def _extract_visual_container_rects(page: Any) -> list:
|
|||
except Exception:
|
||||
return rects
|
||||
|
||||
page_area = (page.rect.width or 1) * (page.rect.height or 1)
|
||||
for drawing in drawings:
|
||||
fill = drawing.get("fill")
|
||||
color = drawing.get("color")
|
||||
|
|
@ -145,12 +144,18 @@ def _extract_visual_container_rects(page: Any) -> list:
|
|||
|
||||
has_border = bool(color) and (isinstance(color, (list, tuple))) and stroke_width > 0
|
||||
|
||||
# Skip thin-bordered, unfilled rectangles that cover >50% of page —
|
||||
# these are page decoration lines (e.g. text area frame), not callout containers.
|
||||
# Skip thin-bordered, unfilled rectangles in dark near-gray color —
|
||||
# these are PDF layout/drawing frame lines (text area borders, figure
|
||||
# borders, clipping paths returned as drawings by PyMuPDF), not callout
|
||||
# containers. Real callout boxes have a colored fill, a thick/colored
|
||||
# border (>1pt), or a true black border (pure RGB 0,0,0).
|
||||
if has_border and not is_filled and stroke_width <= 1.0:
|
||||
coverage = (rect.width * rect.height) / page_area
|
||||
if coverage > 0.5:
|
||||
continue
|
||||
if color and len(color) >= 3:
|
||||
r, g, b = color[0], color[1], color[2]
|
||||
is_gray = max(r, g, b) - min(r, g, b) < 0.05
|
||||
brightness = (r + g + b) / 3
|
||||
if is_gray and 0.02 < brightness < 0.3:
|
||||
continue
|
||||
|
||||
if is_filled or has_border:
|
||||
rects.append(rect)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from pathlib import Path
|
|||
from paperforge.core.io import read_json, write_json
|
||||
|
||||
CURRENT_SPAN_BACKFILL_VERSION = "2026-06-22.1"
|
||||
CURRENT_SPAN_VISUAL_CONTAINER_VERSION = "2026-06-26.2"
|
||||
CURRENT_SPAN_VISUAL_CONTAINER_VERSION = "2026-06-26.4"
|
||||
MIN_SPAN_BACKFILL_COVERAGE = 0.90
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -188,6 +188,44 @@ def test_extract_visual_container_detects_thick_border_box() -> None:
|
|||
assert len(rects) == 1, "Thick border box should be detected"
|
||||
|
||||
|
||||
def test_extract_visual_container_keeps_colored_thin_border() -> None:
|
||||
"""A colored (non-gray) thin-border rectangle should still be detected."""
|
||||
import fitz
|
||||
|
||||
from paperforge.worker.ocr_pdf_spans import _extract_visual_container_rects
|
||||
|
||||
doc = fitz.open()
|
||||
page = doc.new_page(width=612, height=792)
|
||||
shape = page.new_shape()
|
||||
shape.draw_rect(fitz.Rect(400, 600, 550, 650)) # magenta colored thin border
|
||||
shape.finish(fill=None, color=(0.6, 0.2, 0.6), width=0.6)
|
||||
shape.commit()
|
||||
|
||||
rects = _extract_visual_container_rects(page)
|
||||
doc.close()
|
||||
|
||||
assert len(rects) == 1, "Colored thin border should be detected"
|
||||
|
||||
|
||||
def test_extract_visual_container_keeps_black_thin_border() -> None:
|
||||
"""A pure black thin-border rectangle should still be detected."""
|
||||
import fitz
|
||||
|
||||
from paperforge.worker.ocr_pdf_spans import _extract_visual_container_rects
|
||||
|
||||
doc = fitz.open()
|
||||
page = doc.new_page(width=612, height=792)
|
||||
shape = page.new_shape()
|
||||
shape.draw_rect(fitz.Rect(400, 600, 550, 650))
|
||||
shape.finish(fill=None, color=(0, 0, 0), width=0.5)
|
||||
shape.commit()
|
||||
|
||||
rects = _extract_visual_container_rects(page)
|
||||
doc.close()
|
||||
|
||||
assert len(rects) == 1, "Black thin border should be detected"
|
||||
|
||||
|
||||
def test_extract_visual_container_skips_small_thin_border() -> None:
|
||||
"""A small thin-border rectangle below min size should be skipped."""
|
||||
import fitz
|
||||
|
|
|
|||
Loading…
Reference in a new issue