@mrbilit/mrz-ocr
v2.0.2
Published
MRZ character recognition using ONNX CNN model
Downloads
140
Readme
@mrbilit/mrz-ocr
MRZ character recognition using a small ONNX CNN. Replaces the HOG+SVM
pipeline in the original mrz-detection project. Runs on onnxruntime-web
(WASM) in the browser and can use onnxruntime-node in Node.js.
This package is part of mrbilit/mrz-scanner, a fork of alsenet-labs/mrz-scanner.
Install
For browser applications:
npm install @mrbilit/mrz-ocrFor Node.js applications, also install the native ONNX Runtime:
npm install @mrbilit/mrz-ocr onnxruntime-nodeUsage (Browser)
import { decode } from 'image-js';
import { MrzOcr } from '@mrbilit/mrz-ocr';
const ocr = new MrzOcr({
modelPath: '/mrz-cnn.onnx', // served as a static asset
});
await ocr.init();
const image = decode(bytes);
const { lines, confidence } = await ocr.recognize(image);Usage (Node.js)
import { MrzOcr } from '@mrbilit/mrz-ocr';
import * as ort from 'onnxruntime-node';
const ocr = new MrzOcr({
modelPath: './models/mrz-cnn.onnx',
ort, // required in Node.js; browser builds default to onnxruntime-web
});
await ocr.init();Recognition pipeline
recognize(image) assumes the input is a tight crop of the MRZ band (what
@mrbilit/mrz-detection produces):
- Greyscale + Otsu threshold on the crop.
- Connected-component ROIs; try black-pixel ROIs first, fall back to white.
- Filter by aspect ratio (0.3–3.0), cluster into lines by center-Y
(line height ≈
image.height / 6). - Drop short lines (
minCharsPerLine, default 5) and keep the lastmaxLines(default 3) — covers TD1 (3 lines) and TD2/TD3 (2 lines). - Sort each line left-to-right, resize each character to 20×20, normalize
to
[0, 1], and batch into a single(N, 1, 20, 20)tensor. - Run the ONNX session; apply softmax over the 37 output logits; emit the argmax character and its probability as confidence.
Model
- Architecture:
Conv(1→32, 3×3)→ReLU→MaxPool→Conv(32→64, 3×3)→ReLU→MaxPool→ Flatten→Dense(128)→ReLU→Dropout(0.3)→Dense(37). - ≈75 K parameters, ≈917 KB ONNX (opset 17).
- 37 classes:
0-9,A-Z,<. - Shipped at
models/mrz-cnn.onnxwith amodels/mrz-cnn.jsonsidecar recording the symbol table and last test accuracy.
Retraining
From packages/mrz-ocr/training:
cd packages/mrz-ocr/training
pip install -r requirements.txt
python extract_ocrb.py
python train_cnn.py --data-dir ./ocrb_chars --output ../models/mrz-cnn.onnx
# Or synthetic data only:
python train_cnn.py --generate --output ../models/mrz-cnn.onnxAfter retraining, rebuild any consumer that bundles the model asset.
Exports
interface MrzOcrOptions {
modelPath?: string; // default 'mrz-cnn.onnx'
minCharsPerLine?: number; // default 5
maxLines?: number; // default 3
ort?: OrtModule; // pass onnxruntime-node in Node.js
}
interface MrzOcrResult {
lines: string[];
confidence: number[][]; // per-character softmax probabilities
}
class MrzOcr {
constructor(options?: MrzOcrOptions);
init(): Promise<void>;
recognize(image: Image): Promise<MrzOcrResult>;
}
const MRZ_SYMBOLS: readonly string[];Security
Constructor inputs are validated:
modelPathmust end in.onnx;..is rejected; onlyhttp(s)://URLs and local paths are allowed (nofile://,data:,ftp://).recognize()refuses images above 20 megapixels to bound memory.
Development
From the monorepo root:
yarn install
yarn workspace @mrbilit/mrz-ocr build
yarn workspace @mrbilit/mrz-ocr typecheckLicense
This project is distributed under the GNU Affero General Public License, version 3 or later (AGPL-3.0-or-later).
The original project and source code are Copyright © 2018-2025 ALSENET SA.
See LICENSE for the full license text.
