TesseractRecognizer
Reads exactly the regions a detector found, straightening each one first. This is the stage that connects a detector to recognition.
- Import
import { TesseractRecognizer } from '@stabrise/scaledp/ocr'- Group
- Recognise
- Reads
- image, boxes
- Writes
- document
- Needs
tesseract-wasm
PaddleTextRecognizer detects and recognises in a single pass, so boxes from a
separate detector never reach it. This stage does the opposite: it reads exactly
the boxes it is handed, cropping and straightening each one.
PaddleRecognizer is the same idea
with PP-OCR doing the reading.
import { Pipeline } from '@stabrise/scaledp'
import { PdfToImage } from '@stabrise/scaledp/pdf'
import { DbnetOnnxDetector, TesseractRecognizer } from '@stabrise/scaledp/ocr'
const rows = await new Pipeline([
new PdfToImage(),
new DbnetOnnxDetector({ outputCol: 'boxes' }),
new TesseractRecognizer({ inputCols: ['image', 'boxes'] }),
]).transform(file)Document.type is 'tesseract-recognizer'. A missing box column produces a
helpful OcrError in exception rather than an empty result.
boxLevel decides how fine the output boxes are
'word' is the default: Tesseract's own word boxes, mapped back through the crop
— padding, scaleFactor and the rotation included — so a word inside a skewed
line comes back skewed the same way. Python has no equivalent; the words were
always in the response, only their geometry was being discarded.
'region' restores ScaleDP's behaviour: one box per region the detector found,
carrying everything read inside it. Since the detectors here are line-level, so
are those boxes.
PaddleRecognizer takes the same
parameter with the same default, so swapping the engine does not change how
finely the page comes back.
scoreThreshold gates the region in both modes, so switching boxLevel
changes how finely the result is cut up and nothing else.
Gating each word separately would also change what was read: a word scoring 0.3
between two at 0.9 rides out on the region's mean and would vanish on its own, so
the same page would yield different text depending on the box size asked for.
Each word still carries its own confidence in score, to filter on downstream.
onlyRotated defaults the other way from Python
ScaleDP defaults it to true, because there the stage refines an OCR pass that
already ran and skipping upright boxes is the whole point. Standalone it is the
primary recognizer, and that default would return an empty document for the
ordinary detector-then-recognize pipeline.
Set it to true to use the stage as a fix-up pass over boxes that already carry
text.
Straightening
The crop is a perspective warp onto the box's own axes, verified readable end to end at 0, +25 and −18 degrees. Recognition quality on skewed text is then bounded by the detector: a box whose reported angle does not match the text's produces a crop that is still skewed.
padding defaults to 5, which is what ScaleDP hardcodes. scaleFactor resizes
the page before cropping — useful for small text — and coordinates are divided
back out, so the boxes stay in the page's own space.
detectLineOrientation classifies each crop 0°/180° and turns the inverted ones
before reading, using the same ~9 MB model as
LineOrientationDetector.
A Python bug not reproduced
ScaleDP sets b.conf but filters on b.score, so its scoreThreshold is
applied to the detector's score rather than the recognizer's. Here it gates
the recognition confidence, as the name says.
Parameters
| Parameter | Type | Default | Meaning |
|---|---|---|---|
inputCols | string[] (2) | ['image', 'boxes'] | The page image, then the detector output whose regions to read. |
lang | string[] | ['eng'] | Tesseract language codes, e.g. eng or eng, deu. Each needs its traineddata file. |
boxLevel | 'word' | 'region' | 'word' | Word boxes are Tesseract’s own. Pick “region” to get one box per region the detector found instead, which is what Python ScaleDP returns. |
scaleFactor | number 0.1–8 | 1 | Resize the page by this factor before cropping. |
padding | number | 5 | Grow each box before cropping. ScaleDP hardcodes 5. |
endPadding | number 0–2 | 0.3 | Extend each region along its line by this fraction of its height, stopping at the next region -- recovers a handwritten capital or flourish the detector left off. 0 reads regions as detected. |
dropNested | boolean | true | Skip a region lying mostly inside a larger one, such as a loose stroke of a handwritten capital, since the larger region already reads it. |
scoreThreshold | number 0–1 | 0.5 | Drop words below this confidence. |
keepFormatting | boolean | false | Rebuild the original layout with spaces and blank lines. |
lineTolerance | number | 0 | Line-grouping tolerance in pixels; 0 derives it from character height. |
detectLineOrientation | boolean | true | Classify each crop 0°/180° and turn the inverted ones. |
onlyRotated | boolean | false | Read only rotated or inverted boxes. On, an ordinary page returns nothing. |