1

我们正在尝试使用 Tesseract 和 Tess4j 进行 OCR 文本提取。

在一段时间内连续使用 tesseract 时,我们注意到应用程序使用的 RAM 逐渐增加,在此期间,堆内存仍然空闲。我们使用 jconsole 监控堆外内存。堆外内存似乎也很正常。但是 RAM RSS 内存对于应用程序来说是不断增加的

我猜的问题是在 OCR 的内存分配期间 tesseract 的内存泄漏,我不确定。任何进一步接近的想法,请分享

在此处输入图像描述

在此处输入图像描述

在此处输入图像描述

4

1 回答 1

1

自最近几天以来,我遇到了同样的问题。我通过删除 tess4j 并使用 Tika 1.27 + tesseract 来解决。我使用 Executor 服务一次运行 3 个线程,这将内存保持在限制范围内。

    byte fileBytes[] ; // image bytes
    Future<String> future = executorService.submit(() -> {
    TesseractOCRConfig config = new TesseractOCRConfig();
    config.setLanguage("kor+eng");
    config.setEnableImageProcessing(1);
    config.setPreserveInterwordSpacing(true);
    ParseContext context = new ParseContext();
    context.set(TesseractOCRConfig.class, config);

    Parser parser = new AutoDetectParser();
    BodyContentHandler handler = new BodyContentHandler();
    Metadata metadata = new Metadata();
    parser.parse(new ByteArrayInputStream(fileBytes), handler, metadata, context);
    return handler.toString();
});

fileBody = future.get(120, TimeUnit.SECONDS);

虽然上面给出的代码有效,但后来我通过生成一个直接调用 tesseract 的进程使其变得更简单。

protected String doOcr(byte[] fileBytes, int timeout, String language) {
        String text = null;
        File inputFile = null;
        File outputFile = null;
        try {
            inputFile = File.createTempFile("tesseract-input", ".png");
            String outputPath = inputFile.getAbsolutePath() + "-output";
            outputFile = new File(outputPath + ".txt");
            try (FileOutputStream fos = new FileOutputStream(inputFile)) {
                fos.write(fileBytes);
            }

            String commandCreate[] = { "tesseract", inputFile.getAbsolutePath(), outputPath, "-l", language, "--psm", "1" ,"-c", "preserve_interword_spaces=1"};

            runCommand(commandCreate, timeout);
            if (outputFile.exists()) {
                try (FileInputStream fis = new FileInputStream(outputFile)) {
                    text = IOUtils.toString(fis, Constants.UTF_8);
                }
            }
        } catch (InterruptedException e) {
            logger.warn("timeout trying to read image file body");          
        } catch (Exception e) {
            logger.error(String.format("Cannot read image file body, error : %s", e.getMessage()), e);          
        } finally {
            if (null != inputFile && inputFile.exists()) {
                inputFile.delete();
            }
            if (null != outputFile && outputFile.exists()) {
                outputFile.delete();
            }
        }       
        return text;
    }

protected void runCommand(String command[], int timeout) throws IOException, InterruptedException {
        logger.info("command : " + StringUtils.join(command, " "));
        ProcessBuilder builder = new ProcessBuilder(command);
        builder.inheritIO();
        builder.environment().put("OMP_THREAD_LIMIT", "1"); /* default tesseract uses 4 threads per image. set to 1 */
        Process p = builder.start();
        boolean finished = p.waitFor(timeout, TimeUnit.SECONDS);
        if (!finished) {
            logger.warn("task not finished");
        }
        p.destroyForcibly();
    }
于 2021-08-19T21:00:01.483 回答