Spring 引导应用程序中的 Tesseract 为日语提供了无意义的结果

Tesseract in Spring Boot Application gives nonsense results for Japanese

我正在编写一个 Spring 引导应用程序,它使用 Bytedeco's Java Wrapper for Tesseract OCR 来解析日语文本。当 运行 在 Spring Boot 之外时,我设法让 Tesseract 正常工作,但是当我在 Spring Boot 应用程序中使用它时,它给了我无意义的结果。

例如,给定下图:

如果我运行下面的函数,结果是合理的:

fun main() {
    val api = tesseract.TessBaseAPI()
    api.Init("src/main/resources/tessdata", "jpn_vert")
    api.SetPageSegMode(tesseract.PSM_SINGLE_BLOCK_VERT_TEXT)
    val pixImage = lept.pixRead("src/main/resources/image.png")
    api.SetImage(pixImage)
    val result = api.GetUTF8Text()
    System.out.println("Parsed text: " + result?.string)
}

打印:

Parsed text:
坊っちゃん
夏目 滞 石

如果我 运行 它来自 Spring 引导 Web 套接字,但是,结果不是:

@SpringBootApplication
open class BootApplication

fun main(args: Array<String>) {
    runApplication<BootApplication>(*args)
}

@Configuration
@EnableWebSocket
open class WebSocketConfiguration: WebSocketConfigurer {
    @Bean
    open fun createWebSocketContainer(): ServletServerContainerFactoryBean {
        val container = ServletServerContainerFactoryBean()
        container.maxBinaryMessageBufferSize = 1024000
        return container
    }

    override fun registerWebSocketHandlers(registry: WebSocketHandlerRegistry) {
        registry.addHandler(Endpoint(), "/parse").setAllowedOrigins("*")
    }
}

class Endpoint: AbstractWebSocketHandler() {
    @Throws(IOException::class)
    override fun handleBinaryMessage(session: WebSocketSession?, message: BinaryMessage?) {
        // Same code as above:
        val api = tesseract.TessBaseAPI()
        api.Init("src/main/resources/tessdata", "jpn_vert")
        api.SetPageSegMode(tesseract.PSM_SINGLE_BLOCK_VERT_TEXT)
        val pixImage = lept.pixRead("src/main/resources/image.png")
        api.SetImage(pixImage)
        val result = api.GetUTF8Text()
        System.out.println("Parsed text:\n" + result?.string)
    }
}

调用 handleBinaryMessage 时打印以下内容:

Parsed text:
蝮翫▲縺。繧?繧?
螟冗岼 貊? 遏ウ

我 运行 对一些英文文本进行了快速测试并且效果很好,所以我认为这个问题是 language-specific。

我正在 运行使用启动 Apache Tomcat 服务的 Spring Boot Gradle 插件中的 bootRun 任务来启动 Boot 应用程序。我的第一个想法是,这与以下事实有关:Tesseract 包装器是一个 JNI 库,并且它在 运行ning (Tomcat) 中的环境不一样。如果是这样,是否需要进行一些额外的配置才能让 Tesseract 与 Spring Boot 和 Tomcat 一起工作?

供参考,我的build.gradle如下:

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.3.10'
    id("org.springframework.boot") version "2.1.0.RELEASE"
}

repositories {
    mavenCentral()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    implementation group: "org.bytedeco.javacpp-presets", name: "tesseract", version: "4.0.0-rc2-1.4.3"
    implementation group: "org.bytedeco.javacpp-presets", name: "tesseract", version: "4.0.0-rc2-1.4.3", classifier: "windows-x86_64"
    implementation group: "org.bytedeco.javacpp-presets", name: "leptonica", version: "1.76.0-1.4.3", classifier: "windows-x86_64"
    implementation group: "org.springframework.boot", name: "spring-boot", version: "2.1.0.RELEASE"
    implementation group: "org.springframework.boot", name: "spring-boot-starter-web", version: "2.1.0.RELEASE"
    implementation group: "org.springframework", name: "spring-websocket", version: "5.1.2.RELEASE"
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}

编辑

看起来是编码问题。 Java 的 file.encoding 系统 属性 在 运行 从引导外部设置为 UTF-8,但在引导时设置为 windows-31j。将 result?.string 切换为 result?.getString("UTF-8") 修复了它。


我将把这归因于 Bytedeco 的 Tesseract 包装器的错误。我用 tess4j 做了等效测试,没有问题:

val imageFile = File("src/main/resources/image.png")
val tess = Tesseract()
tess.setPageSegMode(PSM_SINGLE_BLOCK_VERT_TEXT)
tess.setLanguage("jpn_vert")
System.out.println("Parsed text:\n" + tess.doOCR(imageFile))

给我:

坊っちゃん
夏目 滞 石

符合预期。

我已经提交了 ticket on their github,所以希望不久之后就能解决这个问题。