Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaa6973a1f | ||
|
|
74d5f8d8e0 |
+4
@@ -28,6 +28,8 @@ import com.knecon.fforesight.service.ocr.processor.service.scriptdetection.FontS
|
||||
import com.knecon.fforesight.service.ocr.processor.service.threads.OCRThread;
|
||||
import com.knecon.fforesight.service.ocr.processor.settings.OcrServiceSettings;
|
||||
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.observation.annotation.Observed;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
@@ -48,6 +50,7 @@ public class OCRService {
|
||||
OcrResultWriter ocrResultWriter;
|
||||
GhostScriptService ghostScriptService;
|
||||
FontStyleDetector boldDetector;
|
||||
ObservationRegistry registry;
|
||||
|
||||
|
||||
/**
|
||||
@@ -59,6 +62,7 @@ public class OCRService {
|
||||
* @param fileId Id of file
|
||||
* @param out OutputStream where to write to
|
||||
*/
|
||||
@Observed(name = "OCRService", contextualName = "run-ocr-on-document")
|
||||
@SneakyThrows
|
||||
public void runOcrOnDocument(String dossierId, String fileId, OutputStream out) {
|
||||
|
||||
|
||||
-1
@@ -109,7 +109,6 @@ public class GhostScriptOutputHandler extends Thread {
|
||||
if (imageFile == null) {
|
||||
throw new IllegalArgumentException(String.format("Page number %d does not exist in this thread. It only has pagenumbers %s", pageNumber, pagesToProcess.keySet()));
|
||||
}
|
||||
assert new File(imageFile.absoluteFilePath()).isFile();
|
||||
renderedPageImageFileOutput.add(imageFile);
|
||||
}
|
||||
|
||||
|
||||
+5
-6
@@ -198,8 +198,10 @@ public class ImageProcessingThread extends Thread {
|
||||
grayScale = pix;
|
||||
} else if (pix.d == 32) {
|
||||
grayScale = Leptonica1.pixConvertRGBToGrayFast(pix);
|
||||
LeptUtils.disposePix(pix);
|
||||
} else if (pix.d == 1) {
|
||||
grayScale = Leptonica1.pixConvert1To8(null, pix, (byte) 0, (byte) 255);
|
||||
LeptUtils.disposePix(pix);
|
||||
} else {
|
||||
throw new UnsupportedOperationException(String.format("Unknown pix format with bpp of %d", pix.d));
|
||||
}
|
||||
@@ -208,36 +210,33 @@ public class ImageProcessingThread extends Thread {
|
||||
float targetFactor = targetDpi / imageDpi;
|
||||
if (targetFactor > 2.1) {
|
||||
scaledUp = Leptonica1.pixScaleGray4xLI(grayScale);
|
||||
LeptUtils.disposePix(grayScale);
|
||||
} else if (targetFactor > 1.1) {
|
||||
scaledUp = Leptonica1.pixScaleGray2xLI(grayScale);
|
||||
LeptUtils.disposePix(grayScale);
|
||||
} else {
|
||||
scaledUp = grayScale;
|
||||
}
|
||||
|
||||
// remove noise and prep for Otsu
|
||||
gaussian = Leptonica1.pixConvolve(scaledUp, gaussianKernel, 8, 1);
|
||||
LeptUtils.disposePix(scaledUp);
|
||||
|
||||
// Threshold to binary
|
||||
if (pix.w < 100 || pix.h < 100) {
|
||||
binarized = Leptonica1.pixThresholdToBinary(gaussian, 170);
|
||||
} else {
|
||||
binarized = Leptonica1.pixOtsuThreshOnBackgroundNorm(gaussian, null, 50, 50, 165, 10, 100, 5, 5, 0.2f, null);
|
||||
|
||||
if (binarized == null) { // Sometimes Otsu just fails, then we binarize directly
|
||||
binarized = Leptonica1.pixThresholdToBinary(gaussian, 170);
|
||||
}
|
||||
}
|
||||
|
||||
LeptUtils.disposePix(pix);
|
||||
LeptUtils.disposePix(grayScale);
|
||||
LeptUtils.disposePix(scaledUp);
|
||||
LeptUtils.disposePix(gaussian);
|
||||
|
||||
return binarized;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static ITessAPI.TessBaseAPI initDetectionScriptHandle() {
|
||||
|
||||
ITessAPI.TessBaseAPI handle = TessAPI1.TessBaseAPICreate();
|
||||
|
||||
+10
-37
@@ -1,25 +1,5 @@
|
||||
package com.knecon.fforesight.service.ocr.processor.utils;
|
||||
|
||||
import static net.sourceforge.tess4j.ITessAPI.TRUE;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessBaseAPIDelete;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessBaseAPIEnd;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessBaseAPIGetIterator;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessBaseAPIGetStringVariable;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessBaseAPIMeanTextConf;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessBaseAPIProcessPage;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessDeleteResultRenderer;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessHOcrRendererCreate;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessPageIteratorBegin;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessPageIteratorBoundingBox;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessPageIteratorNext;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessResultIteratorConfidence;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessResultIteratorDelete;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessResultIteratorGetPageIterator;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessResultIteratorGetUTF8Text;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessResultRendererBeginDocument;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessResultRendererEndDocument;
|
||||
import static net.sourceforge.tess4j.TessAPI1.TessResultRendererInsert;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
@@ -29,19 +9,20 @@ import com.sun.jna.Pointer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sourceforge.lept4j.Pix;
|
||||
import net.sourceforge.tess4j.ITessAPI;
|
||||
import net.sourceforge.tess4j.OCRResult;
|
||||
import net.sourceforge.tess4j.TessAPI1;
|
||||
import net.sourceforge.tess4j.Tesseract;
|
||||
import net.sourceforge.tess4j.Tesseract1;
|
||||
import net.sourceforge.tess4j.TesseractException;
|
||||
import net.sourceforge.tess4j.Word;
|
||||
|
||||
@Slf4j
|
||||
/**
|
||||
* Overriden version only so I can use Tesseract1 with Pixs instead of BufferedImages. All Functions are copied and then the BufferedImage -> Pix conversion deleted.
|
||||
*/ public class Tesseract2 extends Tesseract {
|
||||
*/
|
||||
public class Tesseract2 extends Tesseract1 {
|
||||
|
||||
private int createDocuments(Pix pix, String filename, ITessAPI.TessResultRenderer renderer) {
|
||||
|
||||
private int createDocuments(Pix pix, String filename, TessResultRenderer renderer) {
|
||||
|
||||
String title = TessBaseAPIGetStringVariable(getHandle(), DOCUMENT_TITLE);
|
||||
TessResultRendererBeginDocument(renderer, title);
|
||||
@@ -81,7 +62,7 @@ import net.sourceforge.tess4j.Word;
|
||||
try {
|
||||
for (int i = 0; i < pixs.length; i++) {
|
||||
try {
|
||||
ITessAPI.TessResultRenderer renderer = createRenderers(outputbases[i], formats);
|
||||
TessResultRenderer renderer = createRenderers(outputbases[i], formats);
|
||||
int meanTextConfidence = createDocuments(pixs[i], filenames[i], renderer);
|
||||
TessDeleteResultRenderer(renderer);
|
||||
List<Word> words = meanTextConfidence > 0 ? getRecognizedWords(pageIteratorLevel) : new ArrayList<Word>();
|
||||
@@ -104,8 +85,8 @@ import net.sourceforge.tess4j.Word;
|
||||
List<Word> words = new ArrayList<>();
|
||||
|
||||
try {
|
||||
ITessAPI.TessResultIterator ri = TessBaseAPIGetIterator(getHandle());
|
||||
ITessAPI.TessPageIterator pi = TessResultIteratorGetPageIterator(ri);
|
||||
TessResultIterator ri = TessBaseAPIGetIterator(getHandle());
|
||||
TessPageIterator pi = TessResultIteratorGetPageIterator(ri);
|
||||
TessPageIteratorBegin(pi);
|
||||
|
||||
do {
|
||||
@@ -138,9 +119,9 @@ import net.sourceforge.tess4j.Word;
|
||||
}
|
||||
|
||||
|
||||
private ITessAPI.TessResultRenderer createRenderers(String outputbase, List<RenderedFormat> formats) {
|
||||
private TessResultRenderer createRenderers(String outputbase, List<RenderedFormat> formats) {
|
||||
|
||||
ITessAPI.TessResultRenderer renderer = null;
|
||||
TessResultRenderer renderer = null;
|
||||
|
||||
for (RenderedFormat format : formats) {
|
||||
switch (format) {
|
||||
@@ -157,12 +138,4 @@ import net.sourceforge.tess4j.Word;
|
||||
return renderer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void dispose() {
|
||||
|
||||
TessBaseAPIEnd(getHandle());
|
||||
TessBaseAPIDelete(getHandle());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
@@ -21,6 +21,7 @@ import com.knecon.fforesight.service.ocr.v1.api.model.DocumentRequest;
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileErrorInfo;
|
||||
|
||||
import feign.FeignException;
|
||||
import io.micrometer.observation.annotation.Observed;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.FieldDefaults;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"overrides": [
|
||||
{
|
||||
"name": "tesseract",
|
||||
"version": "5.3.2"
|
||||
"version": "5.3.3"
|
||||
},
|
||||
{
|
||||
"name": "leptonica",
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ public class OcrServiceIntegrationTest extends AbstractTest {
|
||||
@SneakyThrows
|
||||
public void testOcr() {
|
||||
|
||||
String text = testOCR("files/402Study.pdf");
|
||||
String text = testOCR("files/UNAPPROVED_VV-331155 (1).pdf");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user