Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bench/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Each harness downloads what it needs into a scratch directory.
| Benchmark | Dataset | Measures | Report |
| --- | --- | --- | --- |
| [`icdar2013/`](icdar2013/) | ICDAR 2013 Table Competition (125 PDFs) | table detection + structure | [2026-08-02](../docs/evaluations/2026-08-02-icdar2013-table-structure.md) |
| [`icdar2013/compare.py`](icdar2013/compare.py) | same, 10 systems | pdfgrab vs the whole field | [2026-09-17](../docs/evaluations/2026-09-17-field-comparison-and-metric-correction.md) |
| [`icdar2013/compare.py`](icdar2013/compare.py) | same, 13 systems | pdfgrab vs the whole field | [2026-09-17](../docs/evaluations/2026-09-17-field-comparison-and-metric-correction.md) |
| [`icdar2013/oracle.py`](icdar2013/oracle.py) | same, with ground-truth boundaries | the ceiling a layout model could reach | [2026-08-03](../docs/evaluations/2026-08-03-hybrid-ceiling-oracle-boundaries.md) |

## Why the numbers live in `docs/evaluations/`
Expand Down
10 changes: 10 additions & 0 deletions bench/icdar2013/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func main() {
strategy := flag.String("strategy", "lines",
"lines | text | mixed | auto | lines-then-mixed | fallback")
merge := flag.Bool("merge", false, "TableSettings.MergeSplitTokens")
detect := flag.Bool("detect", false, "TableSettings.DetectRegions (text-alignment region detection)")
oracle := flag.String("oracle", "",
`JSON of per-page explicit edges: {"1":{"v":[..],"h":[..]}}`)
flag.Parse()
Expand Down Expand Up @@ -69,6 +70,15 @@ func main() {
attempts = []pdfgrab.TableSettings{lines}
}

// Region detection is a property of the run, not of a strategy, so
// it is applied to whichever attempts the strategy selected. It only
// affects text-derived axes; on a pure "lines" run it is inert.
if *detect {
for i := range attempts {
attempts[i].DetectRegions = true
}
}

// Oracle mode: the caller supplies the row/column boundaries and
// pdfgrab only fills the cells. This is exactly the shape of the
// hybrid a layout model would drive — and fed GROUND-TRUTH edges it
Expand Down
11 changes: 10 additions & 1 deletion bench/icdar2013/systems.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ def timed(fn: Callable[[str], Tables], pdf: str, t: Timing) -> Tables:
# --- adapters ---------------------------------------------------------


def pdfgrab(exe: str, strategy: str, merge: bool = False) -> Callable[[str], Tables]:
def pdfgrab(exe: str, strategy: str, merge: bool = False,
detect: bool = False) -> Callable[[str], Tables]:
"""pdfgrab, via the benchmark's Go extractor binary."""

def run(pdf: str) -> Tables:
Expand All @@ -144,6 +145,8 @@ def run(pdf: str) -> Tables:
cmd = [exe, "-strategy", strategy]
if merge:
cmd.append("-merge")
if detect:
cmd.append("-detect")
cmd.append(pdf)
out = subprocess.run(cmd, capture_output=True, timeout=120).stdout
return [t["rows"] for t in json.loads(out or b"[]")]
Expand Down Expand Up @@ -261,6 +264,12 @@ def build_adapters(exe: str, gx_exe: str = "") -> list[Adapter]:
note="the library under test"),
Adapter("pdfgrab (auto)", pdfgrab(exe, "auto"),
note="one-axis-ruled support, opt-in"),
Adapter("pdfgrab (text+detect)", pdfgrab(exe, "text", detect=True),
note="HAL-1362: text-alignment region detection"),
Adapter("pdfgrab (fallback+detect)", pdfgrab(exe, "fallback", detect=True),
note="HAL-1362: lines, then text within detected regions"),
Adapter("pdfgrab (text, no detect)", pdfgrab(exe, "text"),
note="control: page-wide text strategy"),
Adapter("pdfplumber (lines)", pdfplumber_tables("lines"),
module="pdfplumber", install="pdfplumber",
note="the implementation pdfgrab is a port of"),
Expand Down
Loading
Loading