A powerful onnxruntime-node based, pure JavaScript OCR library that works directly in Node.js - no Python dependencies required! Extract text from images with industry-leading accuracy using PaddleOCR models.
- π Multilingual Support: English, Chinese, Japanese, Korean, and Latin languages
- π― High Accuracy: Based on PaddleOCR v3/v4 models
- π¦ Zero Python Dependencies: 100% JavaScript/Node.js implementation
- π§ ONNX Runtime Node: Efficient, high-performance model inference directly in Node.js
- π§ Highly Customizable: Configure detection, recognition, and grouping parameters
- π¨ Smart Text Grouping: Automatically groups text into paragraphs
- π Bring Your Own Models: Use custom ONNX models
- β‘ Production Ready: Built with performance and reliability in mind
- π Plug and Play: All models and dictionaries included - just install and run!
npm install multilingual-purejs-ocr
import Ocr from 'multilingual-purejs-ocr';
// Create OCR instance with default settings (English)
const ocr = await Ocr.create();
// Detect text in an image
const result = await ocr.detect('./image.jpg');
console.log('Total elements:', result.totalElements);
console.log('Paragraphs:', result.paragraphs);
console.log('Individual elements:', result.data);
// English (default)
const ocrEn = await Ocr.create({ language: 'en' });
const resultEn = await ocrEn.detect('./english.jpg');
// Chinese
const ocrCh = await Ocr.create({ language: 'ch' });
const resultCh = await ocrCh.detect('./chinese.jpg');
// Japanese
const ocrJa = await Ocr.create({ language: 'ja' });
const resultJa = await ocrJa.detect('./japanese.jpg');
// Korean
const ocrKo = await Ocr.create({ language: 'ko' });
const resultKo = await ocrKo.detect('./korean.jpg');
// Latin languages (Portuguese, Spanish, French, etc.)
const ocrLatin = await Ocr.create({ language: 'latin' });
const resultLatin = await ocrLatin.detect('./latin.jpg');
const ocr = await Ocr.create({
// Language selection
language: 'en',
// Detection parameters
detectionThreshold: 0.1, // Lower = more sensitive (0-1)
minBoxSize: 3, // Minimum text box size in pixels
maxBoxSize: 2000, // Maximum text box size in pixels
unclipRatio: 1.5, // Box expansion ratio
// Recognition parameters
confidenceThreshold: 0.5, // Minimum confidence to accept text (0-1)
imageHeight: 48, // Recognition model input height
removeDuplicateChars: true, // Remove duplicate characters
// Text grouping configuration
grouping: {
verticalThresholdRatio: 1.2,
horizontalThresholdRatio: 2.5,
minOverlapRatio: 0.3,
maxVerticalOffsetRatio: 0.5
}
});
const result = await ocr.detect('./image.jpg');
const ocr = await Ocr.create({
language: 'en',
detectionModelPath: './my-models/custom_detection.onnx',
recognitionModelPath: './my-models/custom_recognition.onnx',
dictionaryPath: './my-models/custom_dict.txt'
});
const ocr = await Ocr.create({
language: 'en',
// Detection model ONNX options
detectionOnnxOptions: {
executionProviders: ['cpu'],
intraOpNumThreads: 4, // Use 4 CPU threads
graphOptimizationLevel: 'all',
enableCpuMemArena: true
},
// Recognition model ONNX options
recognitionOnnxOptions: {
executionProviders: ['cpu'],
intraOpNumThreads: 2,
executionMode: 'sequential'
}
});
const ocr = await Ocr.create({ language: 'en' });
// Get only individual text elements (no paragraph grouping)
const result = await ocr.detect('./image.jpg', { grouped: false });
console.log(result.data); // Array of individual text elements
// result.paragraphs will not be present
const ocr = await Ocr.create({ language: 'en' });
// Update grouping configuration at runtime
ocr.setGroupingConfig({
verticalThresholdRatio: 1.5,
horizontalThresholdRatio: 3.0
});
// Get current configuration
const config = ocr.getGroupingConfig();
console.log(config);
{
totalElements: 31, // Total text elements detected
totalParagraphs: 9, // Number of grouped paragraphs
// Grouped paragraphs (when grouped: true)
paragraphs: [
{
text: "BECAUSE OF YOU,",
confidence: 0.923,
boundingBox: {
left: 485,
top: 61,
width: 84,
height: 43
},
elements: [ // Individual elements in this paragraph
{
text: "BECAUSE",
confidence: 0.96,
frame: { left: 485, top: 61, width: 84, height: 20 }
},
{
text: "OF YOU,",
confidence: 0.86,
frame: { left: 489, top: 81, width: 75, height: 23 }
}
]
}
],
// Individual text elements
data: [
{
text: "BECAUSE",
confidence: 0.9598,
frame: {
left: 485,
top: 61,
width: 84,
height: 20
},
box: [[485, 61], [569, 61], [569, 81], [485, 81]] // 4-point polygon
}
]
}
Option | Type | Default | Description |
---|---|---|---|
detectionThreshold |
number | 0.1 | Text detection sensitivity (0-1, lower = more sensitive) |
minBoxSize |
number | 3 | Minimum text box size in pixels |
maxBoxSize |
number | 2000 | Maximum text box size in pixels |
unclipRatio |
number | 1.5 | Box expansion ratio for better text capture |
baseSize |
number | 32 | Image size base unit (must be multiple of 32) |
maxImageSize |
number | 960 | Maximum image dimension |
Option | Type | Default | Description |
---|---|---|---|
language |
string | 'en' | Language code: en, ch, ja, ko, latin |
confidenceThreshold |
number | 0.5 | Minimum confidence to accept text (0-1) |
imageHeight |
number | 48 | Recognition model input height |
removeDuplicateChars |
boolean | true | Remove consecutive duplicate characters |
Option | Type | Default | Description |
---|---|---|---|
verticalThresholdRatio |
number | 1.2 | Max vertical gap ratio for grouping |
horizontalThresholdRatio |
number | 2.5 | Max horizontal gap ratio for same line |
minOverlapRatio |
number | 0.3 | Minimum vertical overlap for same line |
maxVerticalOffsetRatio |
number | 0.5 | Max vertical offset ratio for same line |
// Get list of available languages
const languages = Ocr.getAvailableLanguages();
console.log(languages);
Code | Language | Model |
---|---|---|
en |
English | PP-OCRv4 |
ch |
Chinese | PP-OCRv4 |
ja |
Japanese | PP-OCRv3 |
ko |
Korean | PP-OCRv4 (Korean dict) |
latin |
Latin (PT, ES, FR, etc.) | PP-OCRv3 |
The package ships with all required models and dictionaries for plug-and-play usage:
models/
βββ ch_PP-OCRv4_det_infer.onnx # Detection model (shared)
βββ en_PP-OCRv4_rec_infer.onnx # English recognition
βββ en_dict.txt # English dictionary
βββ ch_PP-OCRv4_rec_infer.onnx # Chinese recognition
βββ ch_dict.txt # Chinese dictionary
βββ japan_PP-OCRv3_rec_infer.onnx # Japanese recognition
βββ japan_dict.txt # Japanese dictionary
βββ korean_dict.txt # Korean dictionary
βββ latin_PP-OCRv3_rec_infer.onnx # Latin recognition
βββ latin_dict.txt # Latin dictionary
No additional setup required - everything is ready to use out of the box!
You can use your own ONNX models:
const ocr = await Ocr.create({
detectionModelPath: './path/to/detection.onnx',
recognitionModelPath: './path/to/recognition.onnx',
dictionaryPath: './path/to/dictionary.txt'
});
- Detection Model: ONNX format, input shape [1, 3, H, W], output: binary mask
- Recognition Model: ONNX format, input shape [1, 3, 48, W], output: character probabilities
- Dictionary: Text file with one character per line
- πΈ Document Scanning: Extract text from scanned documents
- π« Receipt Processing: Parse receipts and invoices
- π License Plate Recognition: Read vehicle plates
- π Form Processing: Extract data from forms
- π Translation Apps: Detect and translate text in images
- π± Screenshot OCR: Extract text from screenshots
- π·οΈ Label Reading: Read product labels and barcodes
- Adjust Detection Threshold: Lower for harder-to-read text, higher for cleaner images
- Use Appropriate Language Model: Select the correct language for better accuracy
- Optimize Image Size: Resize very large images before processing
- Tune ONNX Threads: Adjust
intraOpNumThreads
based on your CPU cores - Disable Grouping: Use
grouped: false
if you only need individual elements
- Adjust
detectionThreshold
(try 0.05 for harder images) - Increase
unclipRatio
(try 1.8 or 2.0) - Ensure correct language model is selected
- Preprocess image (increase contrast, remove noise)
- Lower
detectionThreshold
- Reduce
minBoxSize
- Increase
unclipRatio
- Reduce
maxImageSize
- Adjust ONNX thread settings
- Process images in batches
- Adjust grouping ratios in configuration
- Use
grouped: false
and implement custom grouping
Creates a new OCR instance with the specified configuration.
Parameters:
options
(Object): Configuration options
Returns: Promise<Ocr>
- OCR instance
Detects and recognizes text in an image.
Parameters:
imagePath
(string): Path to image fileoptions
(Object): Detection optionsgrouped
(boolean): Return grouped paragraphs (default: true)onnxOptions
(Object): Runtime ONNX options
Returns: Promise<Object>
- Detection results
Updates the text grouping configuration.
Parameters:
config
(Object): New grouping configuration
Returns the current grouping configuration.
Returns: Object
- Current grouping configuration
Static method that returns available languages.
Returns: Object
- Language configurations
Contributions are welcome! Please feel free to submit issues or pull requests.
ISC
- Built on PaddleOCR models
- Uses ONNX Runtime Node for efficient model inference in Node.js
- Powered by Sharp for image processing
For issues and questions, please open an issue on GitHub.
Made with β€οΈ for the JavaScript community