问题描述
我在识别文本片段中的下标和上标时遇到问题。
示例图片:
我将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是否可以...?
解决方法
按照该主题的其他问题/答案中的建议处理图像质量并没有真正改变。
首先遵循tesseract-google-newsgroup的以下两个链接,实际上似乎是一个培训问题: link1和link2。
但是经过一些实验后,我发现所使用的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来检测单个字母。