【问题标题】:Tess4j on Windows 64-bit: exception on multiple threadsWindows 64 位上的 Tess4j:多线程异常
【发布时间】:2014-09-08 01:25:02
【问题描述】:

我在 Windows 64 位上使用带有 Java 8 的 tesseract 3 来 OCR 扫描的 PDF。我遵循instructions on the Tess4j page 并使用了所需 DLL 的 64 位版本,并安装了 64 位 Ghostscript。

当我使用普通的@Test(无参数)运行单元测试时,代码运行正确,所以我想我已经正确安装了所有东西。

当我用 2 个线程并行运行它时(见下文),我得到一个异常。

我已阅读相关主题here,但建议使用我正在使用的 Tesseract1(我都尝试过)。

有什么想法吗?

这是代码:

//  @Test // works
@Test(invocationCount = 2, threadPoolSize = 2)
public void testOcr() throws OcrException, TesseractException {
    File scannedPdf = new File(this.getClass().getClassLoader().getResource("scanned.pdf").getFile());
//  Tesseract instance = Tesseract.getInstance();  // JNA Interface Mapping
    Tesseract1 instance = new Tesseract1(); // JNA Direct Mapping
    String str = instance.doOCR(scannedPdf);
    System.out.println("OCR Result: " + str);
}

这是个例外:

log4j:WARN No appenders could be found for logger (org.ghost4j.Ghostscript).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Ιουλ 16, 2014 6:22:23 ΜΜ net.sourceforge.vietocr.PdfUtilities convertPdf2Png
SEVERE: Cannot initialize Ghostscript interpreter. Error code is -21
org.ghost4j.GhostscriptException: Cannot initialize Ghostscript interpreter. Error code is -21
    at org.ghost4j.Ghostscript.initialize(Ghostscript.java:365)
    at net.sourceforge.vietocr.PdfUtilities.convertPdf2Png(Unknown Source)
    at net.sourceforge.vietocr.PdfUtilities.convertPdf2Tiff(Unknown Source)
    at net.sourceforge.vietocr.ImageIOHelper.getIIOImageList(Unknown Source)
    at net.sourceforge.tess4j.Tesseract1.doOCR(Unknown Source)
    at net.sourceforge.tess4j.Tesseract1.doOCR(Unknown Source)
    at OcrUtilsTest.testOcr(OcrUtilsTest.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.internal.thread.ThreadUtil$2.call(ThreadUtil.java:64)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

java.lang.Error: Invalid memory access
    at com.sun.jna.Native.invokeInt(Native Method)
    at com.sun.jna.Function.invoke(Function.java:383)
    at com.sun.jna.Function.invoke(Function.java:315)
    at com.sun.jna.Library$Handler.invoke(Library.java:212)
    at com.sun.proxy.$Proxy3.gsapi_init_with_args(Unknown Source)
    at org.ghost4j.Ghostscript.initialize(Ghostscript.java:350)
    at net.sourceforge.vietocr.PdfUtilities.convertPdf2Png(Unknown Source)
    at net.sourceforge.vietocr.PdfUtilities.convertPdf2Tiff(Unknown Source)
    at net.sourceforge.vietocr.ImageIOHelper.getIIOImageList(Unknown Source)
    at net.sourceforge.tess4j.Tesseract1.doOCR(Unknown Source)
    at net.sourceforge.tess4j.Tesseract1.doOCR(Unknown Source)
    at OcrUtilsTest.testOcr(OcrUtilsTest.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.internal.thread.ThreadUtil$2.call(ThreadUtil.java:64)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
net.sourceforge.tess4j.TesseractException: javax.imageio.IIOException: I/O error reading header!
    at net.sourceforge.tess4j.Tesseract1.doOCR(Unknown Source)
    at net.sourceforge.tess4j.Tesseract1.doOCR(Unknown Source)
    at OcrUtilsTest.testOcr(OcrUtilsTest.java:19)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
    at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
    at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
    at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
    at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
    at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
    at org.testng.internal.thread.ThreadUtil$2.call(ThreadUtil.java:64)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javax.imageio.IIOException: I/O error reading header!
    at com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:224)
    at com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader.locateImage(TIFFImageReader.java:231)
    at com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader.getNumImages(TIFFImageReader.java:279)
    at net.sourceforge.vietocr.ImageIOHelper.getIIOImageList(Unknown Source)
    ... 18 more
Caused by: java.io.EOFException
    at javax.imageio.stream.ImageInputStreamImpl.readShort(ImageInputStreamImpl.java:229)
    at javax.imageio.stream.ImageInputStreamImpl.readUnsignedShort(ImageInputStreamImpl.java:242)
    at com.sun.media.imageioimpl.plugins.tiff.TIFFImageReader.readHeader(TIFFImageReader.java:199)
    ... 21 more

更新:似乎与this有关。

【问题讨论】:

    标签: java multithreading tesseract ghost4j tess4j


    【解决方案1】:

    Tesseract 本身只能将图像转换为文本,而不是 PDF,即使 PDF 已被扫描。

    在底层,Tess4j 使用 Ghostscript(通过 ghost4j)将每个页面转换为单个图像文件,然后将其提供给 Tesseract 进行 OCR。它将生成的字符串连接成一个字符串,然后返回。

    异常的原因是 Tess4j 使用 Ghost4j 的方式不支持多线程。如here 所述,ghost4j 确实 从其高级 API 提供了多线程支持(实际上它运行不同的 Ghostscript 实例,每个实例分别从不同的 JVM 调用)。然而,Tess4j 使用其低级 API,其中可以使用单个 Ghostscript 实例。

    【讨论】:

    • 我今天开始遇到这个问题......是的......这是因为我使用了多个线程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-16
    • 1970-01-01
    相关资源
    最近更新 更多