Tesseract OCR是否可以识别下标和上标?

问题描述

我在识别文本片段中的下标和上标时遇到问题。

示例图片

example-image with subscript and superscript

我将Tesseract 4.1.1与https://github.com/tesseract-ocr/tessdata_best下提供的训练数据结合使用。众多选项具有认值,除了:

  • tessedit_create_hocr = 1(以HOCR形式获得结果)
  • hocr_font_info = 1(以获取其他字体信息,例如字体大小)
  • hocr_char_Boxes = 1(获取基于字符的结果)

该语言设置为英语。在页面分割模式3(PSM_AUTO_OSD),11(PSM_SPARSE_TEXT)或12(PSM_SPARSE_TEXT_OSD)下,都无法正确识别下标/上标。

输出中,sub / sup-fragments或多或少是错误的:

  • “ Subtext Sub ”被识别为“ Subtextsu”,
  • “ Suptext Sub ”被识别为“ Suptexts?”
  • “ P 0 ”被识别为“ Po”
  • “ P 100 ”被识别为“ P1go”
  • “ a 2 + b 2 ”被识别为“ a + b?”

将Tesseract用于OCR是否可以...?

  1. 优化下标/上标处理
  2. 获取有关已识别下标/上标的信息(在hocr输出中-理想情况下是每个字符)

解决方法

按照该主题的其他问题/答案中的建议处理图像质量并没有真正改变。

首先遵循tesseract-google-newsgroup的以下两个链接,实际上似乎是一个培训问题: link1link2

但是经过一些实验后,我发现所使用的OEM_DEFAULT-OCR引擎模式不会显示所需的信息。我找到了部分解决问题的办法。部分原因是因为我现在可以获得有关sub / sup的大多数信息,而且在大多数情况下识别的字符都是正确的,但并非对所有字符都是正确的。

使用OEM_TESSERACT_ONLY-OCR引擎模式(=传统模式)和Tess4J提供的一些API方法,我想到了以下Java测试类:

public class SubSupEvaluator {
    public void determineSubSupCharacters(BufferedImage image) {
        //1. initialize Tesseract and set image infos
        TessBaseAPI handle = TessAPI1.TessBaseAPICreate();
        try {
            int bpp = image.getColorModel().getPixelSize();
            int bytespp = bpp / 8;
            int bytespl = (int) Math.ceil(image.getWidth() * bpp / 8.0);
            TessBaseAPIInit2(handle,new File("./tessdata/").getAbsolutePath(),"eng",TessOcrEngineMode.OEM_TESSERACT_ONLY);
            TessBaseAPISetPageSegMode(handle,TessPageSegMode.PSM_AUTO_OSD);
            TessBaseAPISetImage(handle,ImageIOHelper.convertImageData(image),image.getWidth(),image.getHeight(),bytespp,bytespl);

            //2. start actual OCR run
            TessBaseAPIRecognize(handle,null);

            //3. iterate over the result character-wise
            TessResultIterator ri = TessBaseAPIGetIterator(handle);
            TessPageIterator pi = TessResultIteratorGetPageIterator(ri);
            TessPageIteratorBegin(pi);
            do {
                //determine character
                Pointer ptr = TessResultIteratorGetUTF8Text(ri,TessPageIteratorLevel.RIL_SYMBOL);
                String character = ptr.getString(0);
                TessDeleteText(ptr); //release memory

                //determine position information
                IntBuffer leftB = IntBuffer.allocate(1);
                IntBuffer topB = IntBuffer.allocate(1);
                IntBuffer rightB = IntBuffer.allocate(1);
                IntBuffer bottomB = IntBuffer.allocate(1);
                TessPageIteratorBoundingBox(pi,TessPageIteratorLevel.RIL_SYMBOL,leftB,topB,rightB,bottomB);

                //write info to console
                System.out.println(String.format("%s - position [%d %d %d %d],subscript: %b,superscript: %b",character,leftB.get(),topB.get(),rightB.get(),bottomB.get(),TessAPI1.TessResultIteratorSymbolIsSubscript(ri) == TessAPI1.TRUE,TessAPI1.TessResultIteratorSymbolIsSuperscript(ri) == TessAPI1.TRUE));
            } while (TessPageIteratorNext(pi,TessPageIteratorLevel.RIL_SYMBOL) == TessAPI1.TRUE);
        } finally {
            TessBaseAPIDelete(handle); //release memory
        }
    }
}

旧版模式仅适用于“正常”训练数据。使用“最佳”训练数据会带来错误。

,

关于此主题的信息很少。 增强子/上标字符识别(即使不是位置本身)的一种方法是,例如使用cv2 / pil(也为pillow)对图像进行预处理,然后重新分割。

请参阅 How to detect subscript numbers in an image using OCR?

相关(但不能回答问题)

https://www.mail-archive.com/tesseract-ocr@googlegroups.com/msg19434.html

https://github.com/tesseract-ocr/tesseract/blob/master/src/ccmain/superscript.cpp

,

你们如何考虑让tesseract识别单个字母?

Tesseract does not recognize single characters

我尝试了--psm 10选项

tesseract imTstg.png out5 --psm 10

但是它似乎没有用。我正在考虑只运行yolo来检测单个字母。