How Recognition Works
How Recognition Works
This page walks through what AsposeOcr.Recognize() actually does internally, from input
validation to the final RecognitionResult. Calling AsposeOcr.Recognize(OcrInput) runs a
fixed, eight-step pipeline. Every step below is grounded in the library’s own
implementation — there are no configurable stages.
1. Input Validation
Before any model is loaded, Recognize() validates the OcrInput: it rejects a null
input (ArgumentNullException), an unsupported InputType (NotSupportedException), and
any queued path that does not exist on disk (FileNotFoundException). No ONNX session is
created until every input passes.
2. PDF Rendering or Raster Loading
For InputType.PDF, each page is rendered to a 24-bit RGB image at 150 DPI using
Aspose.PDF.FOSS. For InputType.SingleImage, the raster file is loaded directly. The
150 DPI rendering resolution is fixed and not configurable.
3. Detector Preprocessing
The image is converted to grayscale using Rec. 709 luma weights, which preserve perceived brightness more accurately than a simple channel average. If the image’s longest side exceeds 1000 pixels, it is downscaled with a separable Lanczos-8 filter (two one-dimensional passes) to match the detector model’s training-time preprocessing. A 32-pixel white strip is appended to the bottom of the image for the same reason.
4. Region Detection
The preprocessed image is passed through the first embedded ONNX model, which produces
text-probability maps and intermediate visual features. A second ONNX model — the
refinement model — strengthens the links between adjacent characters so that a full text
line is detected as one region rather than several fragments. Both models run on the CPU
with Microsoft.ML.OnnxRuntime configured for 8 intra-operation worker threads.
5. Region Post-Processing
The detector’s text and link probability maps are thresholded, then grouped with a
four-connected breadth-first flood fill. Each resulting region is dilated, fitted with a
minimum-area rectangle, scaled back to source-image coordinates, and reduced to
non-nested, axis-aligned line rectangles. These rectangles are what RecognitionResult.LinesResult.Line
ultimately returns.
6. Line Recognition
Each detected rectangle is padded by two pixels, cropped out of the source image, and resized — preserving its aspect ratio — onto a fixed 1200×32 white canvas. The result is converted to an NHWC grayscale tensor and passed to the recognition model.
7. CTC Decoding
The recognition model’s raw output is decoded with greedy CTC (Connectionist Temporal Classification) decoding: repeated predicted classes are collapsed, the blank class is removed, and the remaining classes are mapped through the model’s embedded Latin alphabet to produce the line’s recognized text.
8. Result Assembly
Recognized lines are paired with their source-image rectangles to build each
RecognitionResult.LinesResult. All non-empty lines are joined with platform line breaks
to produce RecognitionResult.RecognitionText.
Sequential vs. Parallel Work
Input files and, for PDFs, individual pages are processed sequentially — there is no
input-level multithreading API. Parallelism exists only inside each ONNX inference call,
where Microsoft.ML.OnnxRuntime parallelizes graph execution across its 8 configured
intra-operation threads.