feat(pdf): recover non-repeating headers/footers mis-tagged as furniture #3697
feat(pdf): recover non-repeating headers/footers mis-tagged as furniture #3697DanielNg0729 wants to merge 2 commits into
Conversation
|
✅ DCO Check Passed Thanks @DanielNg0729, all your commits are properly signed off. 🎉 |
Merge Protections🟢 Merge protection satisfied — ready to merge. Show 1 satisfied protection🟢 Enforce conventional commitMake sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
…ure (docling-project#3693) The layout model labels regions PAGE_HEADER/PAGE_FOOTER from per-page position only, so a one-off heading at the top of a page is tagged as a header, moved to the FURNITURE layer and dropped from the default export. Add an opt-in HeaderFooterModel stage that runs before reading order and, using whole-document context, demotes header/footer detections that neither repeat across pages nor cover most pages back into the body (headers -> SECTION_HEADER, footers -> TEXT). Disabled by default to preserve current output; gated via PdfPipelineOptions.header_footer_options. Signed-off-by: Daniel Nguyen <danielnguyenh07@gmail.com>
Signed-off-by: Daniel Nguyen <danielnguyenh07@gmail.com>
6f28338 to
68032ec
Compare
|
Hi Dr @PeterStaar-IBM, I've resolved the merge conflict. This is ready for review whenever you have a moment. Thank you very much! |
re-running the CI. |
|
Hi Dr. @PeterStaar-IBM Dr. @cau-git, just a gentle reminder that this PR is ready for review whenever you have the chance. Thank you very much! |
Summary
This PR resolves #3693. The layout model labels regions as
PAGE_HEADER/PAGE_FOOTERfrom per-page position alone. It has no notion of whether the text actually repeats across pages. A one-off heading sitting at the top of a page therefore gets tagged as a page header, moved to theFURNITUREcontent layer by the reading-order model, and silently dropped from the default export (which only emitsBODY). On the affected PDF this removes obvious section headings.This PR adds an opt-in document-level pass,
HeaderFooterModel, that runs just before the reading-order model, the first stage with whole-document context, and demotes header/footer detections that are not genuine running furniture back into the body.Heuristic
A
PAGE_HEADER/PAGE_FOOTERdetection is kept as furniture when either:"Page 3 of 10"matches"Page 4 of 10") appears on ≥min_repeat_pagespages (a consistent running header/footer); ormin_coverageof the pages. A real running header/footer appears on (almost) every page, so a side that only shows up on a few scattered pages is most likely mis-detected content, while a header whose text legitimately changes per section is still trusted because it covers most pages.Otherwise it is reclassified: a non-repeating header →
SECTION_HEADER(so the existing heading-hierarchy step can level it), a non-repeating footer →TEXT. The pass never drops, adds or reorders items, and never touches genuine repeating headers/footers. It only runs on documents with ≥min_pagespages, since repetition/coverage aren't observable on 1–2 page docs.Configuration
New
HeaderFooterOptions, exposed asPdfPipelineOptions.header_footer_options:enabledFalsemin_pages3min_repeat_pages2min_coverage0.5promote_headers_to_sectionTrueSECTION_HEADER(elseTEXT)Tests
tests/test_header_footer.pyfocused unit tests for the heuristic (both sample-PDF scenarios, section-varying headers, short-doc guard, footer/text targets, blank detections, disabled no-op) and the in-place relabeling + bucket move. All pass.Notes
standard_pdf_pipelineandlegacy_standard_pdf_pipeline, before reading order.