【问题标题】:How to detect text blocks and columns in pdf with tess4j如何使用 tess4j 检测 pdf 中的文本块和列
【发布时间】:2017-02-23 14:14:11
【问题描述】:

我是 Tesseract (tess4j) 的新手,设法使用了主要功能,例如阅读文本或从图像或 pdf 中获取单词位置、旋转等。

我找不到,也不确定是否可以轻松检测文本块(段落或列)。 另外,如果pdf中还有一些其他的块,比如图像或其他东西,是否有可能以某种方式得到它,或者至少可以得到块(框)的位置。

【问题讨论】:

  • PDF 是否只包含文本?只有黑/白吗?
  • 可以是任何PDF。我需要检测里面是否有图像,如果有图像,我需要检测位置。
  • 如果 PDF 类似于广告传单,Tesseract 无法满足您的要求。神经网络有一个权衡,这是一般的与普通的。准确性。如果您的 PDF 中有一些模式,您可以手动选择文本块或编写一段代码。
  • 例如可以是书。很多文字和图像在这里和那里。可能吗?还是和传单一样?
  • OpenCV 可能是您正在寻找的用于检测文本块的库。这个post 可能会有所帮助。

标签: java ocr tesseract tess4j


【解决方案1】:

您可以使用TessBaseAPIGetComponentImages API 方法,如下:

Boxa boxes = api.TessBaseAPIGetComponentImages(handle, TessPageIteratorLevel.RIL_BLOCK, TRUE, null, null);

查看 Tess4J unit tests 以获取完整示例。

【讨论】:

  • 啊,你为我节省了很多时间!!好东西。看来这就是我需要的,我会用它玩一下......谢谢! (我会尽快接受答案)
  • 如果我设置 TessPageIteratorLevel.RIL_BLOCK 它总是只返回一个框,即使我有更多的文本块。对于 TEXT_LINE 它返回正确的行。我什至尝试使用 RIL_PARA,结果相同,只有一个盒子。知道如何改进吗?
  • 好的,我通过添加 api.TessBaseAPISetPageSegMode(handle, TessPageSegMode.PSM_AUTO_OSD); 修复了它你能告诉我参数 text_only 是什么意思吗?如果设置为false,是否会返回包含图片的blocks?
  • 如果我将它设置为false,它会将图像识别为一个盒子,但不确定如何从盒子中获取图像......
【解决方案2】:

我已经接受了答案,但这是该答案的结果:

public Page recognizeTextBlocks(Path path) {
        log.info("TessBaseAPIGetComponentImages");
        File image = new File(path.toString());
        Leptonica leptInstance = Leptonica.INSTANCE;
        Pix pix = leptInstance.pixRead(image.getPath());
        Page blocks = new Page(pix.w,pix.h);        
        api.TessBaseAPIInit3(handle, datapath, language);
        api.TessBaseAPISetImage2(handle, pix);
        api.TessBaseAPISetPageSegMode(handle, TessPageSegMode.PSM_AUTO_OSD);
        PointerByReference pixa = null;
        PointerByReference blockids = null;
        Boxa boxes = api.TessBaseAPIGetComponentImages(handle, TessPageIteratorLevel.RIL_BLOCK, FALSE, pixa, blockids);
        int boxCount = leptInstance.boxaGetCount(boxes);
        for (int i = 0; i < boxCount; i++) {
            Box box = leptInstance.boxaGetBox(boxes, i, L_CLONE);
            if (box == null) {
                continue;
            }
            api.TessBaseAPISetRectangle(handle, box.x, box.y, box.w, box.h);
            Pointer utf8Text = api.TessBaseAPIGetUTF8Text(handle);
            String ocrResult = utf8Text.getString(0);
            Block block = null;
            if(ocrResult == null || (ocrResult.replace("\n", "").replace(" ","")).length() == 0){
                block = new ImageBlock(new Rectangle(box.x, box.y, box.w, box.h));
            }else{
                block = new TextBlock(new Rectangle(box.x, box.y, box.w, box.h), ocrResult); 
            }
            blocks.add(block);
            api.TessDeleteText(utf8Text);
            int conf = api.TessBaseAPIMeanTextConf(handle);
            log.debug(String.format("Box[%d]: x=%d, y=%d, w=%d, h=%d, confidence: %d, text: %s", i, box.x, box.y, box.w, box.h, conf, ocrResult));
        }

        //release Pix resource
        PointerByReference pRef = new PointerByReference();
        pRef.setValue(pix.getPointer());
        leptInstance.pixDestroy(pRef);

        return blocks;
    }

注意:类 Block、ImageBlock 和 TextBlock 来自我的项目,不是 tess4j 或 tesseract 的一部分

【讨论】:

  • 除了PixBoxBoxa 对象也需要妥善处理,我刚刚注意到。为此目的使用LeptUtils.dispose 方法。
猜你喜欢
  • 1970-01-01
  • 2012-07-16
  • 1970-01-01
  • 2023-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-02
相关资源
最近更新 更多