firecrawl / firecrawl/pdf-inspector

[Image: …] placeholder items defeat the invisible-text retry decision: sample and density count treat pixels as text

Open Beginner friendly
#466 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
19.2k
Forks
1.3k
Avg merge
9h 21m
Merged PRs (30d)
51

Description

Summary

The invisible-text (Tr 3) retry in process_document decides whether to fire by sampling the items from the normal extraction pass. That sample — and the sparse-extraction heuristic proposed in #385 — counts [Image: RXX] placeholder items as if they were text. On scanned pages the placeholders are often the only items, so the sample is non-empty and non-garbage, and the retry that would have recovered the OCR layer never fires.

Root cause

In the retry decision (currently src/lib.rs ~4175, Mixed branch):

let sample: String = items
    .iter()
    .filter(|item| /* page filter */)
    .take(200)
    .map(|item| item.text.as_str())
    .collect();
if is_garbage_text(&sample) || sample.trim().is_empty() { /* retry */ }

items includes ItemType::Image placeholders, whose synthesized text ([Image: R15]) is ~60% alphanumeric. A page with a raster image and an invisible OCR layer therefore produces a sample like [Image: R15][Image: R16]… that passes is_garbage_text and is not empty — the retry is skipped and the document reports "no extractable text". The same bias affects any item-count density floor (as suggested in #385): five images on one page already satisfy items.len() >= 5 * page_count.

Elsewhere the crate already has this rule: non_placeholder_alnum() (src/lib.rs ~1000) explicitly excludes ItemType::Image "they mark that pixels exist, not that text was read". The retry decision predates that helper and never got the same filter.

Fix

Filter placeholders out of both the sample and any density count:

.filter(|item| !matches!(item.item_type, types::ItemType::Image))

Measured impact

On a private corpus of 4,114 real-world PDFs (Dutch/German administrative documents, OCRmyPDF-processed scans): 96 documents fail extraction on v1.14.2. Adding this filter (together with the retry widening from #385) recovers 13 of them that fail purely because of placeholder bias; no output changed for any previously-succeeding document.

Related: #385 (retry never fires for dense TextBased OCR layers — same code path, independent defect).

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/lib.rs around process_document's Mixed-branch retry decision and compare its filtering with non_placeholder_alnum(). Trace the sample and any item-count density logic, then verify that ItemType::Image placeholders are excluded from both; done means placeholder-only scanned pages can trigger the OCR retry without changing previously successful extraction.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
82/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.