我们正在尝试使用 Tesseract 和 Tess4j 进行 OCR 文本提取。
在一段时间内连续使用 tesseract 时,我们注意到应用程序使用的 RAM 逐渐增加,在此期间,堆内存仍然空闲。我们使用 jconsole 监控堆外内存。堆外内存似乎也很正常。但是 RAM RSS 内存对于应用程序来说是不断增加的
我猜的问题是在 OCR 的内存分配期间 tesseract 的内存泄漏,我不确定。任何进一步接近的想法,请分享
我们正在尝试使用 Tesseract 和 Tess4j 进行 OCR 文本提取。
在一段时间内连续使用 tesseract 时,我们注意到应用程序使用的 RAM 逐渐增加,在此期间,堆内存仍然空闲。我们使用 jconsole 监控堆外内存。堆外内存似乎也很正常。但是 RAM RSS 内存对于应用程序来说是不断增加的
我猜的问题是在 OCR 的内存分配期间 tesseract 的内存泄漏,我不确定。任何进一步接近的想法,请分享
自最近几天以来,我遇到了同样的问题。我通过删除 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();
}