【问题标题】:Tesseract / Tess4j memory leakTesseract / Tess4j 内存泄漏
【发布时间】:2020-05-13 17:36:59
【问题描述】:

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

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

我猜的问题是 tesseract 在 OCR 的内存分配期间内存泄漏,我不确定。有什么更进一步的想法,请分享

【问题讨论】:

  • 在 python 中我们看到了类似的效果,但基本上认为这不是泄漏,尽管 tesseract 似乎消耗越来越多。当python(或者在你的情况下是JVM)决定释放内存时,取决于具体的实现,而不是“任务完成——现在释放内存”。您的应用程序是否因内存限制而崩溃?
  • 在ubuntu服务器上遇到同样的问题,用python,最后我的磁盘空间用完了,请帮忙
  • 嘿阿拉文斯。你能解决这个问题吗?
  • @IanaMykhailenko 抱歉,我们不能,但是当我们转移到物理机而不是虚拟机时,问题就停止了

标签: java memory-leaks tesseract tess4j java-memory-leaks


【解决方案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();
    }

【讨论】:

  • 感谢您提供此信息。这可以处理字体属性等文本样式属性吗?
  • Tesseract 只是转换为文本。您可以使用命令行测试您的字体图像。如果它在命令行上工作,它也可以在 Java 中工作。如果您必须传递任何额外的命令行参数,请查看是否可以在 TesseractOCRConfig 中找到它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-08
  • 2013-01-20
  • 2011-10-31
  • 2019-08-10
  • 2013-06-24
  • 2011-03-22
相关资源
最近更新 更多