Scene Text OCR using Ultralytics YOLO26
What is Scene Text OCR?#
Optical character recognition (OCR) detects and reads text in images. The OCR solution combines an Ultralytics YOLO26 text detector with a text-recognition backend. It supports axis-aligned detection boxes, oriented boxes (OBB), and segmentation polygons, then returns recognized text in reading order.
Detection and recognition remain separate components, so you can pair your scene-text detector with PaddleOCR or your own recognition model.
Why Use Scene Text OCR?#
- Flexible text geometry: Use detection, OBB, or segmentation models for horizontal, rotated, or irregular text.
- Interchangeable recognition: Run PaddleOCR without extra integration code, or pass a callable for another model.
- Structured output: Access recognized text, recognition and detection confidences, source geometry, and an annotated image from one results object.
Run Scene Text OCR with YOLO26#
PaddleOCR is optional and loads when OCR is created with recognizer="paddleocr", installing PaddleOCR 3.x and the
CPU PaddlePaddle build if they are missing. For GPU recognition, install a matching paddlepaddle-gpu build first; no OCR packages are
added to the base Ultralytics dependencies.
Pass an image and a text detector to the OCR solution. The result contains the annotated image and recognized text:
yolo solutions ocr model="scene-text-obb.pt" source="path/to/video.mp4" recognizer="paddleocr"YOLO26-Text Checkpoints#
The public YOLO26-Text family provides n, s, m, l, and x OBB checkpoints. Set ULTRALYTICS_API_KEY to your
own Ultralytics Platform API key, then load a checkpoint by its Platform
URI:
export ULTRALYTICS_API_KEY="your-api-key"ocr = solutions.OCR(model="ul://ultralytics-yolo/yolo26-text/yolo26n-text", recognizer="paddleocr")
result = ocr(im0)Replace yolo26n-text with yolo26s-text, yolo26m-text, yolo26l-text, or yolo26x-text for a larger model.
OCR Arguments#
Here's a table with the OCR arguments:
| Argument | Type | Default | Description |
|---|---|---|---|
model | str | None | Path to an Ultralytics YOLO model file. |
recognizer | str or Callable | 'paddleocr' | Text-recognition backend or callable accepting a BGR crop and returning (text, confidence). |
line_width | int | 2 | Line thickness for the boxes, keypoints and counts the solution draws. |
verbose | bool | True | Enables the solution's per-frame log of input shape, class counts and processing speed. The tracking call itself is always silent. |
Additionally, the following visualization settings are supported:
| Argument | Type | Default | Description |
|---|---|---|---|
show | bool | False | If True, displays the annotated images or videos in a window. Useful for immediate visual feedback during development or testing. |
show_conf | bool | True | Displays the confidence score for each detection alongside the label. Gives insight into the model's certainty for each detection. |
show_labels | bool | True | Displays labels for each detection in the visual output. Provides immediate understanding of detected objects. |
How Scene Text OCR Works#
- Detect text: YOLO26 produces axis-aligned boxes, oriented boxes, or segmentation polygons.
- Create recognition crops: Boxes are clipped to the image. OBBs are affine-rectified along the edge that spans furthest left-to-right, so near-square boxes stay upright and tilted text lines lie horizontally in reading direction. For segmentation polygons, the minimum-area rotated rectangle is rectified while the original polygon is retained. Crops at least 1.5× taller than wide are rotated 90° counter-clockwise, as in PaddleOCR.
- Recognize text: PaddleOCR processes all crops in batches of 16. Custom recognizers receive one crop at a time.
- Order and render results: Text is grouped into horizontal lines and ordered top-to-bottom and left-to-right. The visualization uses a Unicode font for non-ASCII text such as Chinese.
Coordinates always refer to the original image, not the detector input or recognition crop.
Use a Custom Recognizer#
Pass a callable to integrate another recognition model without changing the detection, geometry, or ordering path. The
callable runs once for each nonempty BGR numpy.ndarray crop. Return one (text, confidence) tuple per call, not a
list of batch results:
| Tuple item | Accepted type | Description |
|---|---|---|
text | str | Decoded text for this crop. Return "" when no text is recognized. |
confidence | float, int, or numpy.floating | Numeric recognition confidence, converted to float by the solution. |
def recognize(crop):
# Run your recognition model on the BGR crop and decode its output here.
return "example", 0.95
ocr = solutions.OCR(model="custom-text.pt", recognizer=recognize)
result = ocr(im0)Unsupported backend names raise a ValueError. When no text is detected, result.texts is empty and the recognizer
is not called.
OCR Results#
Each call returns a SolutionResults
object. Use result.plot_im for the annotated image and result.texts for records in deterministic reading order:
| Key | Type | Description |
|---|---|---|
text | str | Recognized text. |
confidence | float | Recognition confidence, kept separate from detection confidence. |
detection_confidence | float | YOLO detector confidence. |
detection_index | int | Source detection index before reading-order sorting. |
polygon | list[list[float]] | Original-image polygon: four corners for box and OBB detections, or the mask outline. |
Dependencies and Licenses#
| Component | Required | Role | License |
|---|---|---|---|
| Ultralytics | Yes | YOLO detection, crop geometry, and result orchestration | AGPL-3.0 |
| PaddlePaddle | Only for recognizer="paddleocr" | Recognition runtime | Apache-2.0 |
| PaddleOCR 3.x | Only for recognizer="paddleocr" | Text-line recognition models and inference adapter | Apache-2.0 |
| Custom callable | No | User-owned recognition integration | Defined by the backend |
PaddleOCR may download recognition weights on first use. Review the selected model's model card and redistribution terms before packaging or deploying those artifacts. Custom checkpoint licenses are separate.
FAQ#
Yes. Pass a callable as
recognizerand return(text, confidence)for each BGR crop. See Use a Custom Recognizer for the input and output contract.No. OCR treats every input image independently, without track IDs or cached recognition. Process each video frame as a separate input when frame-by-frame OCR is required.
You can export the YOLO detector with the normal Export mode, but PaddleOCR or a custom recognizer is not embedded in the ONNX, TensorRT, or other detector artifact. Deploy the exported detector and recognition runtime as separate components, or keep this Python composition layer.
Comments
Ask a question, share your results, or help someone else.