From 515e2a3d56eec3b324147495e16e624e4a29aabc Mon Sep 17 00:00:00 2001 From: Yuliia Buchko Date: Tue, 5 May 2020 17:45:28 +0200 Subject: [PATCH 01/13] Add AutoDetectTextExtractor --- build.gradle | 2 + gradle/wrapper/gradle-wrapper.properties | 5 +- .../configuration/TesseractConfiguration.kt | 17 +++++++ .../services/AutoDetectTextExtractor.kt | 46 ++++++++++++++++++ .../ksi/mordor/services/FileEntryCreator.kt | 11 +++-- .../ksi/mordor/services/ImageTextExtractor.kt | 43 ++++++++++++++++ .../ksi/mordor/services/PDFTextExtractor.kt | 45 +++++++++++++++++ src/main/resources/tessdata/eng.traineddata | Bin 0 -> 23466654 bytes src/main/resources/tessdata/pol.traineddata | Bin 0 -> 19344135 bytes 9 files changed, 162 insertions(+), 7 deletions(-) create mode 100644 src/main/kotlin/pl/edu/uj/ii/ksi/mordor/configuration/TesseractConfiguration.kt create mode 100644 src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/AutoDetectTextExtractor.kt create mode 100644 src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/ImageTextExtractor.kt create mode 100644 src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/PDFTextExtractor.kt create mode 100644 src/main/resources/tessdata/eng.traineddata create mode 100644 src/main/resources/tessdata/pol.traineddata diff --git a/build.gradle b/build.gradle index 470d9b5..80b99d1 100644 --- a/build.gradle +++ b/build.gradle @@ -71,6 +71,8 @@ dependencies { compile("org.glassfish.jaxb:jaxb-runtime:2.3.2") compile("commons-io:commons-io:2.6") compile("org.apache.tika:tika-parsers:1.24") + compile("org.apache.pdfbox:pdfbox:2.0.1") + compile("net.sourceforge.tess4j:tess4j:3.4.0") // Remove devtools for release runtime('org.springframework.boot:spring-boot-devtools') diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e0b3fb8..6b37cba 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ +#Mon May 04 21:03:43 CEST 2020 +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/configuration/TesseractConfiguration.kt b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/configuration/TesseractConfiguration.kt new file mode 100644 index 0000000..c7e8b32 --- /dev/null +++ b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/configuration/TesseractConfiguration.kt @@ -0,0 +1,17 @@ +package pl.edu.uj.ii.ksi.mordor.configuration + +import net.sourceforge.tess4j.Tesseract +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class TesseractConfiguration { + @Bean + fun tesseract(): Tesseract { + val tesseract = Tesseract() + tesseract.setDatapath("./src/main/resources/") + tesseract.setLanguage("pol+eng") + return tesseract + } +} + diff --git a/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/AutoDetectTextExtractor.kt b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/AutoDetectTextExtractor.kt new file mode 100644 index 0000000..79f0275 --- /dev/null +++ b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/AutoDetectTextExtractor.kt @@ -0,0 +1,46 @@ +package pl.edu.uj.ii.ksi.mordor.services + +import java.io.File +import java.io.IOException +import net.sourceforge.tess4j.Tesseract +import net.sourceforge.tess4j.TesseractException +import org.apache.tika.Tika +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +import pl.edu.uj.ii.ksi.mordor.services.repository.RepositoryService + +@Service +class AutoDetectTextExtractor(private val tika: Tika, + private val tesseract: Tesseract) : FileTextExtractor{ + + companion object { + private val logger = LoggerFactory.getLogger(RepositoryService::class.java) + } + + override fun extract(file: File, maxLength: Int): String? { + try { + val tikaContent = TikaFileTextExtractor(tika).extract(file) + if (!isScanned(tikaContent)) + return tikaContent + val type = tika.detect(file) + if (type == "application/pdf") { + return PDFTextExtractor(tesseract).extract(file) + } + if (type.startsWith("image")) { + return ImageTextExtractor(tesseract).extract(file) + } + } catch (e: TesseractException) { + logger.error("Tesseract is unable do process OCR", e) + } catch (e: IOException) { + logger.error("File can not be read", e) + } + return null + } + + private fun isScanned(content: String?): Boolean { + if (content == null) + return true + return content.trim().isEmpty() + } + +} \ No newline at end of file diff --git a/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/FileEntryCreator.kt b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/FileEntryCreator.kt index b45e50c..5ed090c 100644 --- a/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/FileEntryCreator.kt +++ b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/FileEntryCreator.kt @@ -1,5 +1,6 @@ package pl.edu.uj.ii.ksi.mordor.services +import org.springframework.beans.factory.annotation.Qualifier import java.io.File import javax.persistence.EntityManager import org.springframework.stereotype.Service @@ -12,11 +13,11 @@ import pl.edu.uj.ii.ksi.mordor.services.hash.FileHashProvider @Service class FileEntryCreator( - private val metadataExtractor: MetadataExtractor, - private val entityManager: EntityManager, - private val fileTextExtractor: FileTextExtractor, - private val hashProvider: FileHashProvider, - private val metadataRepository: FileMetadataRepository + private val metadataExtractor: MetadataExtractor, + private val entityManager: EntityManager, + @Qualifier("autoDetectTextExtractor") private val fileTextExtractor: FileTextExtractor, + private val hashProvider: FileHashProvider, + private val metadataRepository: FileMetadataRepository ) { companion object { diff --git a/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/ImageTextExtractor.kt b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/ImageTextExtractor.kt new file mode 100644 index 0000000..2e2a5be --- /dev/null +++ b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/ImageTextExtractor.kt @@ -0,0 +1,43 @@ +package pl.edu.uj.ii.ksi.mordor.services + +import com.recognition.software.jdeskew.ImageDeskew +import java.awt.image.BufferedImage +import java.io.File +import javax.imageio.ImageIO +import net.sourceforge.tess4j.Tesseract +import net.sourceforge.tess4j.TesseractException +import net.sourceforge.tess4j.util.ImageHelper +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service + +@Service +class ImageTextExtractor(private val tesseract: Tesseract) : FileTextExtractor { + + val maxSkewAngle = 0.05 + + override fun extract(file: File, maxLength: Int): String? { + return extractTextFromBufferedImage(ImageIO.read(file)) + } + + private fun correctTwisted(image: BufferedImage?): BufferedImage? { + val imageSkewAngle = ImageDeskew(image).skewAngle + if (kotlin.math.abs(imageSkewAngle) > maxSkewAngle) { + return ImageHelper.rotateImage(ImageHelper.convertImageToGrayscale(image), -imageSkewAngle) + } + return ImageHelper.convertImageToGrayscale(image) + } + + fun extractTextFromBufferedImage(image: BufferedImage?): String? { + try { + return tesseract.doOCR(correctTwisted(image)) + .replace("\\n{2,}", "\n") + .trim { c -> c <= ' ' } + } catch (e: TesseractException) { + LoggerFactory.getLogger(this.javaClass).error("Tesseract is unable do process OCR on image", e) + } + return null + } +} + + + diff --git a/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/PDFTextExtractor.kt b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/PDFTextExtractor.kt new file mode 100644 index 0000000..972b6e4 --- /dev/null +++ b/src/main/kotlin/pl/edu/uj/ii/ksi/mordor/services/PDFTextExtractor.kt @@ -0,0 +1,45 @@ +package pl.edu.uj.ii.ksi.mordor.services + +import java.awt.image.BufferedImage +import java.io.File +import java.util.LinkedList +import net.sourceforge.tess4j.Tesseract +import org.apache.pdfbox.pdmodel.PDDocument +import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject +import org.springframework.stereotype.Service + +@Service +class PDFTextExtractor(private val tesseract: Tesseract) : FileTextExtractor { + + override fun extract(file: File, maxLength: Int): String? { + val extracted = StringBuilder() + val bufferedImages = formatPDF(file) + + if (!bufferedImages.isEmpty()) { + for (image in bufferedImages) { + val text: String? = ImageTextExtractor(tesseract).extractTextFromBufferedImage(image) + if (text != null) { + extracted.append(text) + } + } + } + return extracted.toString() + } + + private fun formatPDF(pdfFile: File): LinkedList { + val bufferedImages = LinkedList() + val doc: PDDocument = PDDocument.load(pdfFile) + for (page in doc.pages) { + val resources = page.resources + for (xObjectName in resources.xObjectNames) { + val xObject = resources.getXObject(xObjectName) + if (xObject is PDImageXObject) { + bufferedImages.add(xObject.image) + } + } + } + doc.close() + return bufferedImages + } +} + diff --git a/src/main/resources/tessdata/eng.traineddata b/src/main/resources/tessdata/eng.traineddata new file mode 100644 index 0000000000000000000000000000000000000000..f4744c201359d02ced6914c77f0de68ee9bbdd74 GIT binary patch literal 23466654 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