I am using Tesseract JS (v2.1.0 with Tesseract v4.1.1) to recognise numbers (one or more digits) in a scanned image which is heavily pre-processed (Noise reduction, Black/White) and that knows where the numbers are.
However, when I run the recognition, very often two-digit numbers are not recognised correctly, e.g.:
In this example, the "11" is recognised as "1".
In the picture, you can see
- The image passed to Tesseract (black/white)
- Colored rectangles that are passed as
rectangleto Tesseract to recognise only in that rectangle (but are added after recognition) - The recognised numbers in the lower-left corner in cyan
What I tried so far:
- At first the image was white on black which I changed by inverting the image. That drastically improved the accuracy.
- Then I read, that Tesseract needs a border around the text, so I added a black border at the same place where the colored rectangles are but that didn't change anything.
- A also switched to the old engine mode as this is supposed to work better.
- I added character white-listing
Is there anything a could change in the options ore the pre-processing to improve that?
This is the code (parts of it):
const scheduler = Tesseract.createScheduler();
const workers = createWorkers(16);
const canvasElement = document.getElementById('detected-numbers');
await recognizeNumbers(scheduler, workers, canvasElement, rowSpecNumbers, colSpecNumbers);
async function recognizeNumbers(scheduler, workers, canvasElement, rowSpecNumbers, colSpecNumbers) {
for (const worker of workers) {
await worker.load();
await worker.loadLanguage('eng');
await worker.initialize('eng');
await worker.setParameters({
tessedit_ocr_engine_mode: Tesseract.TESSERACT_ONLY,
tessedit_char_whitelist: '0123456789',
tessedit_pageseg_mode: Tesseract.SINGLE_WORD
})
scheduler.addWorker(worker);
}
await Promise.all(rowSpecNumbers
.flat()
.map(number => scheduler.addJob('recognize', canvasElement, {
rectangle: {
left: number.boundingRect.x,
top: number.boundingRect.y,
width: number.boundingRect.width,
height: number.boundingRect.height
}
}).then(result => number.data = result.data)
));
await Promise.all(colSpecNumbers
.flat()
.map(number => scheduler.addJob('recognize', canvasElement, {
rectangle: {
left: number.boundingRect.x,
top: number.boundingRect.y,
width: number.boundingRect.width,
height: number.boundingRect.height
}
}).then(result => number.data = result.data)
));
await scheduler.terminate();
}
