PaddleOCR Integration#
MinerU uses a PyTorch-native port of PaddleOCR (PP-OCRv6) — no PaddlePaddle runtime required. The core class is PytorchPaddleOCR, which extends TextSystem from MinerU's own pytorchocr inference stack. Models are resolved at runtime from models_config.yml and downloaded on demand.
PDF Classification: txt vs ocr Path#
Before any OCR runs, classify(pdf_bytes) in pdf_classify.py determines whether a PDF is text-extractable ("txt") or must go through full OCR ("ocr"). It samples up to 10 pages and applies a waterfall of heuristic checks; the first failing check short-circuits to "ocr":
| Check | Trigger condition |
|---|---|
| Empty pages / extreme aspect ratio | ratio > 10.0 |
| Too few characters | avg cleaned chars/page < 50 |
| PDFium Unicode map errors | error ratio ≥ 0.04 |
| CID font without ToUnicode | usage count ≥ 30 and ratio ≥ 0.01 |
| Latin-charset font decoding as CJK | CJK ratio ≥ 0.8 |
| Abnormal character quality | ratio ≥ 0.03 over 300+ chars |
| Suspicious cross-script mixing | ratio ≥ 0.18 with 3+ scripts |
| Suspicious U+7280–U+72DF block | count ≥ 30 and CJK ratio ≥ 0.026 |
| Dense ASCII punctuation runs | punct ratio ≥ 0.25 and run ratio ≥ 0.10 |
| High image coverage | image area ≥ 80% of page area |
Only a PDF that clears all checks returns "txt".
Model Configuration and Language Support#
models_config.yml maps language keys to their detector, recognizer, and character-dictionary files. All detector paths for most languages reuse ch_PP-OCRv6_small_det_infer.safetensors . Recognizer weights vary by language family:
- Chinese (default,
ch) —ch_PP-OCRv6_small_rec_infer.safetensors - Server-grade Chinese (
ch_server) —ch_PP-OCRv6_medium_rec_infer.safetensors - Seal stamps (
seal/seal_lite) — dedicated detector (seal_PP-OCRv4_det_server_infer.pth) with a specializedpolybox pipeline - Other scripts (Korean, Arabic, Cyrillic, Devanagari, Thai, Greek, etc.) — language-specific PP-OCRv5 recognizers with PP-OCRv6 detector
The seal mode changes several detection hyperparameters: det_limit_side_len=736, det_db_thresh=0.2, det_box_type='poly', and drop_score=0 .
Confidence Threshold and Result Filtering#
OcrConfidence in ocr_utils.py sets two hard-coded thresholds:
min_confidence = 0.5— results below this score are dropped inget_ocr_result_list()min_width = 3— bounding boxes narrower than 3 pixels are also discarded
Inside PytorchPaddleOCR.__call__(), there is a secondary filter using self.drop_score (inherited from TextSystem): only detection-recognition pairs where score >= drop_score are returned . For the seal pipeline, drop_score is forced to 0 so all detections pass through to downstream scoring .
Formula regions are masked white before the OCR detector runs to prevent interference with adjacent text lines via mask_formula_regions_for_ocr_det().
OCR Fallback for Text-Based PDFs#
For PDFs classified as "txt", MinerU still falls back to OCR at the span level in two scenarios handled by fill_char_in_spans() and _prepare_post_ocr_spans():
1. Empty spans after character mapping
After native characters are spatially mapped into layout spans, any span whose content is too sparse relative to its dimensions is queued for OCR .
2. Private-Use Area (PUA) characters
Spans containing U+E000–U+F8FF characters — a sign of missing or garbled font encoding — trigger _should_fallback_to_post_ocr_for_private_use_text(). The fallback activates when:
pua_count ≥ 2and eithermax_pua_run ≥ 2orpua_ratio ≥ 0.05
When a span is flagged, its original native text is preserved in _post_ocr_fallback_content . If the OCR image has contrast below 0.17, the fallback restores the native text rather than discarding the span entirely via _restore_post_ocr_fallback() .
A hard cap of 65535 native characters per page (MAX_NATIVE_TEXT_CHARS_PER_PAGE) also forces a full-page OCR fallback to avoid processing pathological documents .
Key Source Files#
| File | Purpose |
|---|---|
mineru/model/ocr/pytorch_paddle.py | PytorchPaddleOCR class — det+rec pipeline, seal mode, score filtering |
mineru/utils/pdf_classify.py | classify() — waterfall heuristics for txt vs ocr routing |
mineru/utils/ocr_utils.py | OcrConfidence, box helpers, formula masking, result assembly |
mineru/utils/span_pre_proc.py | Per-span OCR fallback — PUA detection, contrast check, native text restore |
mineru/utils/pdf_text_tool.py | Native char extraction and deduplication for the txt path |
mineru/model/utils/pytorchocr/utils/resources/models_config.yml | Language → model file mapping |