Skip to main content

Document OCR toolkit

Run docTR 1.1.0 on your own GPU — detection, recognition, layout and tables in one local pipeline

docTR is Mindee's open-source document OCR library, Apache 2.0, shipped on PyPI as python-doctr. The default fast_base + crnn_vgg16_bn pipeline is 32.1M parameters — under 130MB in fp32. VRAM was never the bottleneck here; throughput is.

docTR is a classic two-stage system: a detection model localises every word, then the cropped word images go through a recognition model that decodes them character by character. `ocr_predictor()` defaults to det_arch="fast_base" and reco_arch="crnn_vgg16_bn", with detection fixed at 1024×1024×3 input and recognition at 32×128×3 (official benchmarks use batch 64). Since 1.0.0 the TensorFlow backend is gone entirely — PyTorch only, torch>=2.0,<3.0 — and 1.1.0 raised the minimum Python from 3.10 to 3.11, which is the first thing most upgrades trip over.

1.1.0 is the biggest change this project has shipped. It added LW-DETR layout analysis (lw_detr_s at 15.1M params, mAP@[.5:.95] 66.89; lw_detr_m at 29.5M) covering 11 element classes including titles, body text, tables, headers and footers. It added TableCenterNet table structure recognition (7.1M params, StarNet backbone, Recall 82.31 / Precision 96.01 / F1 88.64) that reconstructs a table into a logical row/column grid you can hand straight to pandas. On top sits a reading-order-aware linearizer with exporters for Markdown, AsciiDoc, HTML and XML, plus the new doctr-cli, vocab whitelisting, ignore_regions layout masking and preserve_original_coords.

One thing worth saying plainly: the performance table in docTR's own docs was measured on an 11th Gen Intel Core i7-11800H @ 2.30GHz — a CPU. So when you see master at 17.6 sec/it for batch 64, or db_resnet50 detection at 1.1 sec per page, that is not a GPU scorecard. On GPU with bf16 the picture changes completely: the ONNX sibling project OnnxTR publishes roughly 0.05 s/page on FUNSD with GPU float16 versus roughly 0.38 s/page on CPU 8-bit. NexGPU runs 1,175 verified rentable nodes and 2,498 GPUs across 51 countries and regions, metered per second with no minimum and no quota request — which is exactly the shape of a bursty batch OCR job.

01 —

The docTR model zoo: detection, recognition, layout, tables

Parameter counts and accuracy from the official zoo; weight footprints computed at 4 bytes per parameter in fp32

VersionParametersVRAMContextNotes
fast_base (detection, ocr_predictor default)16.3M (10.6M after reparameterisation)fp32 weights ~65MB / bf16 ~33MB1024×1024×3 input, B=1Replaced db_resnet50 as the default detector in 0.9.0. FUNSD Recall 84.95 / Precision 86.73, CORD Recall 94.39. The speed/accuracy sweet spot — use it unless you have a reason not to.
db_resnet50 (detection, differentiable binarization)25.4Mfp32 weights ~102MB / bf16 ~51MB1024×1024×3 input, B=1The long-standing workhorse: FUNSD Recall 83.56 / Precision 86.68, CORD Recall 92.61. Higher ceiling when you have fine-tuning data, and it is the architecture used in the references/detection/train.py examples. For something lighter, db_mobilenet_v3_large is only 4.2M params.
crnn_vgg16_bn (recognition, default)15.8Mfp32 weights ~63MB / bf16 ~32MB32×128×3 input, benchmarked at B=64FUNSD exact match 88.21, CORD 95.47, and only 0.6 sec/it at batch 64 even on CPU. 1.0.0 shipped a fresh crnn_vgg16_bn checkpoint. Need cheaper? crnn_mobilenet_v3_small is 2.1M params at 0.05 sec/it.
parseq (recognition, permuted autoregressive)23.8Mfp32 weights ~95MB / bf16 ~48MB32×128×3 input, B=64FUNSD 88.53 / CORD 95.56 — the best all-round accuracy in the PyTorch zoo, at 2.2 sec/it on the CPU benchmark. The community multilingual checkpoint Felix92/doctr-torch-parseq-multilingual-v1 uses this architecture; pull it with from_hub().
viptr_tiny (recognition, added in 0.12.0)3.2Mfp32 weights ~13MB / bf16 ~7MB32×128×3 input, B=64Vision Permutable Extractor. FUNSD 86.03 / CORD 93.08 at 0.08 sec/it — built for edge deployment and high-concurrency serving, and only about two points behind CRNN.
lw_detr_s + tablecenternet (1.1.0 layout & tables)15.1M + 7.1Mfp32 weights ~89MB combinedboth 1024×1024×3 input, B=1detect_layout=True enables layout analysis, detect_tables=True enables table structure recognition. With everything on you hold four models in VRAM at once — the only docTR configuration that genuinely needs headroom.

02 —

Picking a GPU for self-hosted docTR

Weights are negligible; the card is chosen by det_bs, page concurrency, and whether you are training a non-Latin vocab

  • Batch document OCR inference, default fast_base + crnn_vgg16_bn, bf16

    RTX 3090 24GB$0.193/GPU-hour

    Ampere, compute capability 8.0+, so the officially recommended .cuda().bfloat16() path works natively; 24GB lets you push det_bs and reco_bs freely — and it is the cheapest card on our list.

  • Online serving / high throughput with all four models on (detection + recognition + layout + tables)

    RTX 4090 24GB$0.540/GPU-hour

    lw_detr_s and tablecenternet both consume 1024×1024 inputs, so compute becomes the bottleneck before memory does; Ada gets the most out of the torch.compile support added in 0.11.0, which lowers cost per page.

  • Fine-tuning detection on your own document layouts at input_size 1024, raising the default batch_size=2

    RTX A6000 48GB$0.817/GPU-hour

    references/detection/train.py defaults to batch_size 2 precisely because 1024×1024 segmentation feature maps are memory-hungry; 48GB gets you to batch 8–16, and with --amp it converges overnight.

  • Training a Simplified Chinese recognition model from scratch, --vocab simplified_chinese, multi-GPU torchrun

    A100 SXM4 80GB$1.088/GPU-hour

    The Simplified Chinese vocab runs to twenty-thousand-plus characters, and output-layer plus decoder memory scales directly with vocab size; 80GB with NCCL across cards is the only comfortable setup, and a node here takes up to 14 GPUs.

03 —

Empty instance to Markdown output in four steps

A PyTorch image boots ready; the whole thing takes under ten minutes

  1. 01

    Spin up an instance and install python-doctr

    Pick an RTX 3090 24GB at console.nexgpu.net and use a prebuilt PyTorch image (there are 2,000+, including vLLM, ComfyUI, Whisper ASR and plain Ubuntu CLI). Note that 1.1.0 requires Python ≥ 3.11 and torch >=2.0,<3.0. The official Docker images are built on CUDA 12.2, so your host CUDA must be 12.2 or newer.

    pip install "python-doctr[viz,html]"
  2. 02

    Turn a PDF into table-aware Markdown with one command

    The doctr-cli added in 1.1.0 needs no Python at all. --detect_layout runs LW-DETR layout analysis, --detect_tables runs TableCenterNet, and output is linearised in reading order; --format covers json / txt / md / xml / html, and --ignore_regions can mask out picture regions entirely.

    doctr-cli --input_path doc.pdf --detect_layout --detect_tables --device cuda:0 --output doc.md
  3. 03

    Move the Python API onto the GPU and enable half precision

    docTR only supports half-precision inference on GPU devices. Use bfloat16() on Ampere and newer (compute capability 8.0+ — 3090, 4090, A6000, A100, H100) and fall back to half() on older cards. Swapping the recognition branch is a one-word change: parseq for accuracy, viptr_tiny for speed. det_bs and reco_bs are the two knobs that saturate the card.

    from doctr.models import ocr_predictor
    predictor = ocr_predictor("fast_base", "parseq", pretrained=True, detect_tables=True).cuda().bfloat16()
  4. 04

    For non-Latin scripts, you must train the recognition branch yourself

    This is docTR's biggest surprise: --vocab in references/recognition/train.py defaults to "french", and every official pretrained recognition checkpoint uses a Latin character set. No amount of tuning will make it emit a Chinese character — the output layer has no such class. Train with simplified_chinese or traditional_chinese, or start from from_hub("Felix92/doctr-torch-parseq-multilingual-v1") and fine-tune. The detection branch usually transfers as-is.

    torchrun --nproc_per_node=4 references/recognition/train.py crnn_mobilenet_v3_large --vocab simplified_chinese --train_path /data/train --val_path /data/val -b 64 --amp --backend nccl

What 100,000 scanned pages actually costs

Take a realistic workload: 100,000 PDF pages through the default fast_base + crnn_vgg16_bn pipeline in bf16. OnnxTR reports about 0.05 s/page on FUNSD with GPU float16; being conservative for the PyTorch backend at 0.1 s/page, that is 100,000 × 0.1 s = 10,000 seconds ≈ 2.78 hours. On an RTX 4090 24GB: 2.78 × $0.540 ≈ $1.50. On an RTX 3090 24GB, even assuming it runs 40% slower at 3.9 hours: 3.9 × $0.193 ≈ $0.75 — the GPU bill for a hundred thousand pages costs less than a coffee. Training is a different order of magnitude: a Simplified Chinese crnn_mobilenet_v3_large from scratch at, say, 40 hours on one A100 SXM4 80GB is 40 × $1.088 = $43.52; run it across 4 GPUs with torchrun and finish in 10 hours for 4 × 10 × $1.088 = $43.52 — identical, because we bill per GPU-hour, so parallelism costs nothing extra and just removes three quarters of the wall-clock. Storage is separate at a $0.414/GB-month median (50GB of source PDFs ≈ $20.70/month) with egress at a $0.0081/GB median. Compute billing stops the moment the instance stops; storage runs until you destroy it. No minimum, no setup fee, no quota request.

04 —

FAQ

How much VRAM does DocTR need? Is an 8GB card enough?

The weights are almost free: the default fast_base (16.3M) plus crnn_vgg16_bn (15.8M) is 32.1M parameters, under 130MB in fp32 and half that in bf16. What actually sets VRAM is det_bs × 1024×1024×3 detection input, reco_bs word crops at 32×128, and whether the 1.1.0 layout and table models are resident too. 8GB handles single-page inference fine, but you will hit a batch ceiling long before you hit a throughput target. A NexGPU RTX 3090 24GB is $0.193/GPU-hour — cheaper than the time you would spend tuning batch sizes on a small card.

Can docTR read Chinese? Why is my Chinese document coming out as garbage?

Because the pretrained recognition checkpoints use a Latin character set. --vocab in references/recognition/train.py defaults to "french", so the model's output layer has no Chinese classes at all — detection boxes may look perfect while the decode is nonsense. vocabs.py does define simplified_chinese, traditional_chinese, japanese, korean and multilingual, but you have to train those yourself. For a twenty-thousand-plus character output layer, use an A100 SXM4 80GB at $1.088/GPU-hour on NexGPU — nodes take up to 14 GPUs, so torchrun scales out immediately.

How does docTR compare to PaddleOCR or EasyOCR?

docTR's case is a clean Apache 2.0 licence, a pure PyTorch implementation, fully decoupled detection and recognition stages you can mix freely (9 detection × 9 recognition architectures), and — since 1.1.0 — built-in layout analysis and table structure recognition that export straight to Markdown, XML or hOCR. The OnnxTR benchmarks on FUNSD put it in the same speed class as PaddleOCR and clearly ahead of EasyOCR. The honest answer is to run all three over your own sample set; on NexGPU, metered per second, an afternoon of head-to-head evaluation costs single-digit dollars.

Can I still use the TensorFlow backend? What breaks when upgrading to 1.1.0?

No. 1.0.0 was the cutover: the TensorFlow backend was removed outright and PyTorch became the only framework — the README subtitle now reads "powered by PyTorch". 1.1.0 then raised minimum Python from 3.10 to 3.11 and relaxed the opencv-python bound to <6.0.0. If you are pinned to Python 3.10 or still hold TF weights, this is a real migration, not a pip install -U. Bring up a clean NexGPU instance to validate the new version in parallel, then stop it — your existing environment stays untouched.

Does docTR run on CPU? Why does the official speed table look so slow?

It runs on CPU, and that table is a CPU table — explicitly measured on an 11th Gen Intel Core i7-11800H @ 2.30GHz. So master at 17.6 sec/it for batch 64, sar_resnet31 at 4.9 sec, db_resnet50 detection at 1.1 sec per page are all CPU figures. OnnxTR's comparable numbers are roughly 0.38 s/page on CPU 8-bit versus roughly 0.05 s/page on GPU float16 — close to an 8× gap. And half-precision inference is GPU-only, so the CPU path cannot even use the bf16 optimisation. For anything batch-sized, renting a card beats waiting on CPU.

How do I turn tables in a scan into structured data?

Use TableCenterNet, added in 1.1.0 (7.1M params, StarNet backbone, F1 88.64, structure accuracy 77.53). Pass detect_tables=True to ocr_predictor, or add --detect_tables on the CLI; the output is a cell grid with logical rows and columns that converts directly to a pandas DataFrame. Combine with detect_layout=True and lw_detr_s to split out titles, headers and footers and export Markdown in correct reading order. With all four models resident, an RTX 4090 24GB at $0.540/GPU-hour is the right card — and NexGPU gives you SSH, Jupyter, a web terminal, REST API and CLI, with bilingual support over Telegram and no ticket queue.

Start building on NexGPU

Enterprise R&D team or solo developer — either way, your first job can be running in minutes.

Sign up to browse live network pricing. No payment method required.