Ultralytics YOLO27: Join the waitlist.
Get Started

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:

Scene Text OCR using Ultralytics YOLO26
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:

ArgumentTypeDefaultDescription
modelstrNonePath to an Ultralytics YOLO model file.
recognizerstr or Callable'paddleocr'Text-recognition backend or callable accepting a BGR crop and returning (text, confidence).
line_widthint2Line thickness for the boxes, keypoints and counts the solution draws.
verboseboolTrueEnables 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:

ArgumentTypeDefaultDescription
showboolFalseIf True, displays the annotated images or videos in a window. Useful for immediate visual feedback during development or testing.
show_confboolTrueDisplays the confidence score for each detection alongside the label. Gives insight into the model's certainty for each detection.
show_labelsboolTrueDisplays labels for each detection in the visual output. Provides immediate understanding of detected objects.

How Scene Text OCR Works#

  1. Detect text: YOLO26 produces axis-aligned boxes, oriented boxes, or segmentation polygons.
  2. 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.
  3. Recognize text: PaddleOCR processes all crops in batches of 16. Custom recognizers receive one crop at a time.
  4. 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 itemAccepted typeDescription
textstrDecoded text for this crop. Return "" when no text is recognized.
confidencefloat, int, or numpy.floatingNumeric 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:

KeyTypeDescription
textstrRecognized text.
confidencefloatRecognition confidence, kept separate from detection confidence.
detection_confidencefloatYOLO detector confidence.
detection_indexintSource detection index before reading-order sorting.
polygonlist[list[float]]Original-image polygon: four corners for box and OBB detections, or the mask outline.

Dependencies and Licenses#

ComponentRequiredRoleLicense
UltralyticsYesYOLO detection, crop geometry, and result orchestrationAGPL-3.0
PaddlePaddleOnly for recognizer="paddleocr"Recognition runtimeApache-2.0
PaddleOCR 3.xOnly for recognizer="paddleocr"Text-line recognition models and inference adapterApache-2.0
Custom callableNoUser-owned recognition integrationDefined 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 recognizer and 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.

Contributors

Comments

Ask a question, share your results, or help someone else.