Tesseract JS Problems Recognising Numbers

Viewed 513

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.:

enter image description here

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 rectangle to 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();
}
0 Answers
Related