PP-OCRv6 - Text Detection & Recognition¶
PP-OCRv6 is the latest generation of PaddlePaddle's ultra-lightweight OCR system. It ships as two independent models — a DBNet-based text detector and a CTC-based text recognizer — that chain into a complete two-stage OCR pipeline.
Overview¶
Resources: PaddleOCR GitHub Repository, PP-OCRv6 models on Hugging Face
Key features:
- Ultra-lightweight -
tiny/small/mediumvariants, from a few MB up - Two-stage pipeline - Independent detection and recognition stages
- Dynamic input shapes - Detector accepts arbitrary image sizes; recognizer adapts its width to the text-line aspect ratio
- ONNX backend - Runs through ONNX Runtime with IO binding on CUDA devices
Models¶
Pre-trained Model IDs¶
Pre-trained PP-OCRv6 models are registered on the Roboflow platform and require a Roboflow API key.
Getting a Roboflow API Key
To use PP-OCRv6 models, you'll need a Roboflow account (free) and API key.
| Model ID | Task | Description |
|---|---|---|
pp-ocrv6-det/tiny |
object-detection |
Smallest, fastest text detector |
pp-ocrv6-det/small |
object-detection |
Balanced text detector (pipeline default) |
pp-ocrv6-det/medium |
object-detection |
Most accurate text detector |
pp-ocrv6-rec/tiny |
text-only-ocr |
Smallest, fastest text recognizer |
pp-ocrv6-rec/small |
text-only-ocr |
Balanced text recognizer (pipeline default) |
pp-ocrv6-rec/medium |
text-only-ocr |
Most accurate text recognizer |
pp-ocrv6 |
pipeline | Two-stage OCR pipeline (defaults to small detection + recognition) |
Text Detection (pp-ocrv6-det)¶
Task: object-detection. Detects text regions with a DBNet probability map. Returns axis-aligned bounding boxes; the tight four-point quadrilateral of each region is preserved in Detections.bboxes_metadata["polygon"] so downstream recognition can crop rotated text lines accurately.
Text Recognition (pp-ocrv6-rec)¶
Task: text-only-ocr. Reads text from cropped single text-line images and returns one string per crop. Inputs should be crops produced by a text detector — the model does not localize text by itself.
When to Use PP-OCRv6¶
- ✅ Printed text - Documents, labels, signs, rendered text
- ✅ Resource-constrained deployments - Smallest variants run comfortably on CPU
- ✅ Custom OCR pipelines - Detection and recognition compose freely with your own cropping / ordering logic
When to Use Other OCR Models¶
- DocTR: Better for structured documents (invoices, forms, scanned pages)
- EasyOCR: Broader multi-language scene-text support out of the box
- TrOCR: Transformer-based recognition of pre-cropped text lines
Performance¶
End-to-end latency (pre-processing + inference + post-processing), mean over 50 runs after warmup, on NVIDIA L4 (24 GB, ONNX Runtime CUDAExecutionProvider) and an Apple Silicon MacBook (arm64, CPUExecutionProvider):
| Model | Input | L4 (CUDA) | MacBook (CPU) |
|---|---|---|---|
pp-ocrv6-det tiny |
640×480 image | 19.5 ms | 63.4 ms |
pp-ocrv6-det small |
640×480 image | 23.0 ms | 103.9 ms |
pp-ocrv6-det medium |
640×480 image | 44.0 ms | 445.8 ms |
pp-ocrv6-rec tiny |
batch of 8 line crops | 3.7 ms | 17.6 ms |
pp-ocrv6-rec small |
batch of 8 line crops | 26.7 ms | 96.7 ms |
pp-ocrv6-rec medium |
batch of 8 line crops | 33.0 ms | 417.5 ms |
Predictions match the original PaddlePaddle implementation of the same weights — verified on the L4 against native Paddle inference (paddlex), with identical detections and exact-string recognition across all three variants. On L4 the GPU forward is the minor cost; end-to-end latency is dominated by CPU-side pre-processing (detection image resize/normalize) and CTC decoding (recognition, scaling with the ~18.7k-character vocabulary of the small/medium variants).
License¶
Apache 2.0
Open Source License
PP-OCRv6 code and weights are released by PaddlePaddle under Apache 2.0, making them free for both commercial and non-commercial use without restrictions.
Learn more: Apache 2.0 License
Usage¶
Both detection (pp-ocrv6-det) and recognition (pp-ocrv6-rec) are registered in tiny / small / medium variants and load via AutoModel.from_pretrained.
Input contract¶
Both models accept np.ndarray (bgr assumed), torch.Tensor (rgb assumed, CHW / BCHW), or lists of either. Integer images are read as [0, 255]; floating-point images are assumed to already be on the [0, 255] scale. This matches the input-scale convention of the other ONNX models in this package.
Pipeline class (recommended)¶
PPOCRv6Pipeline bundles detection, perspective-cropping, reading-order grouping, and recognition behind a single call. It is registered as the pp-ocrv6 model pipeline and loads via AutoModelPipeline (defaulting to the small variant of both stages). It returns one PPOCRv6PipelineResult per input image, with text (all lines joined in reading order), line_texts (one per kept detection), and the reordered detections (None when the detection stage is disabled).
import cv2
from inference_models import AutoModelPipeline
pipeline = AutoModelPipeline.from_pretrained("pp-ocrv6", api_key="your_roboflow_api_key")
image = cv2.imread("document.png")
result = pipeline(image)[0]
print(result.text)
Override stage variants through models_parameters (order: [detection, recognition]):
pipeline = AutoModelPipeline.from_pretrained(
"pp-ocrv6",
models_parameters=["pp-ocrv6-det/medium", "pp-ocrv6-rec/medium"],
api_key="your_roboflow_api_key",
)
To reuse already-loaded models, construct the pipeline directly with PPOCRv6Pipeline(det_model=detector, rec_model=recognizer).
Two-stage composition¶
For full control over cropping and ordering, load the two models with AutoModel and compose them yourself:
import cv2
from inference_models import AutoModel
det = AutoModel.from_pretrained("pp-ocrv6-det/small", api_key="your_roboflow_api_key")
rec = AutoModel.from_pretrained("pp-ocrv6-rec/small", api_key="your_roboflow_api_key")
image = cv2.imread("document.png")
detections = det(image)[0]
crops = [
image[int(y1):int(y2), int(x1):int(x2)]
for x1, y1, x2, y2 in sorted(detections.xyxy.tolist(), key=lambda b: (b[1], b[0]))
]
texts = rec(crops)
print("\n".join(texts))
from_pretrained also accepts a local package directory containing inference.onnx and inference.yml.
Either stage is optional when constructing PPOCRv6Pipeline directly (passing None for the other model skips it; passing neither raises ValueError):
- Detect-only (recognition skipped) — construct with
rec_model=None. Each result carries reading-orderdetectionswith emptyline_textsandtext=""; recognition is never invoked. - Recognize-only (detection skipped) — construct with
det_model=None. Each input image is treated as a single text-line crop and passed straight to recognition; each result hastextset to the recognized string,line_texts=[text], anddetections=None.