From b4e5f2da2f7667b366402a1cb3447b84d6e9ef63 Mon Sep 17 00:00:00 2001 From: yhampe Date: Wed, 17 Jan 2024 16:58:53 +0100 Subject: [PATCH] RED-7375 table extractor prototype added label changed colour of bounding boxes --- .../processor/LayoutParsingPipeline.java | 6 ++++-- .../TableExtractorResponseAdapter.java | 15 +++++++------ .../model/table/TableExtractorCells.java | 21 +++++++++++++++++++ .../visualization/ViewerDocumentService.java | 16 ++++++++------ 4 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/python_api/model/table/TableExtractorCells.java diff --git a/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/LayoutParsingPipeline.java b/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/LayoutParsingPipeline.java index 686b383..e644516 100644 --- a/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/LayoutParsingPipeline.java +++ b/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/LayoutParsingPipeline.java @@ -33,6 +33,7 @@ import com.knecon.fforesight.service.layoutparser.processor.python_api.adapter.I import com.knecon.fforesight.service.layoutparser.processor.python_api.adapter.TableExtractorResponseAdapter; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.image.ImageServiceResponse; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableCells; +import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableExtractorCells; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableExtractorResponse; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableServiceResponse; import com.knecon.fforesight.service.layoutparser.processor.services.BodyTextFrameService; @@ -92,6 +93,7 @@ public class LayoutParsingPipeline { TableExtractorResponse tableExtractorResponse = new TableExtractorResponse(); if (layoutParsingRequest.tableExtractorFileId().isPresent()) { + log.info("TABLEEXTRACTORRESPONSE:"+tableExtractorResponse); tableExtractorResponse = layoutParsingStorageService.getExtractedTableFile(layoutParsingRequest.tableExtractorFileId().get()); } @@ -112,7 +114,7 @@ public class LayoutParsingPipeline { layoutParsingStorageService.storeDocumentData(layoutParsingRequest, DocumentDataMapper.toDocumentData(documentGraph)); layoutParsingStorageService.storeSimplifiedText(layoutParsingRequest, simplifiedSectionTextService.toSimplifiedText(documentGraph)); - Map> extractedTableCells = tableExtractorResponseAdapter.buildExtractedTablesPerPage(tableExtractorResponse); + Map> extractedTableCells = tableExtractorResponseAdapter.buildExtractedTablesPerPage(tableExtractorResponse); try (var out = new ByteArrayOutputStream()) { viewerDocumentService.createViewerDocument(originDocument, documentGraph, out,extractedTableCells ,false); layoutParsingStorageService.storeViewerDocument(layoutParsingRequest, out); @@ -175,7 +177,7 @@ public class LayoutParsingPipeline { Map> pdfTableCells = cvTableParsingAdapter.buildCvParsedTablesPerPage(tableServiceResponse); Map> pdfImages = imageServiceResponseAdapter.buildClassifiedImagesPerPage(imageServiceResponse); - Map> extractedTableCells = tableExtractorResponseAdapter.buildExtractedTablesPerPage(tableExtractorResponse); + Map> extractedTableCells = tableExtractorResponseAdapter.buildExtractedTablesPerPage(tableExtractorResponse); ClassificationDocument classificationDocument = new ClassificationDocument(); List classificationPages = new ArrayList<>(); diff --git a/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/python_api/adapter/TableExtractorResponseAdapter.java b/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/python_api/adapter/TableExtractorResponseAdapter.java index e6c74d2..9115e42 100644 --- a/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/python_api/adapter/TableExtractorResponseAdapter.java +++ b/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/python_api/adapter/TableExtractorResponseAdapter.java @@ -16,6 +16,7 @@ import com.knecon.fforesight.service.layoutparser.processor.python_api.model.tab import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.ExtractedTableData; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableCells; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableData; +import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableExtractorCells; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableExtractorResponse; import lombok.RequiredArgsConstructor; @@ -24,8 +25,8 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor public class TableExtractorResponseAdapter { - public Map> buildExtractedTablesPerPage(TableExtractorResponse tableExtractorResponse) { - Map> tableCells = new HashMap<>(); + public Map> buildExtractedTablesPerPage(TableExtractorResponse tableExtractorResponse) { + Map> tableCells = new HashMap<>(); tableExtractorResponse.getData() .forEach(tableData -> tableCells.computeIfAbsent(tableData.getPage_number(), tableCell -> new ArrayList<>()) .addAll(convertTableCells(tableData.getTables()))); @@ -34,27 +35,29 @@ public class TableExtractorResponseAdapter { } - public List convertTableCells(List tableObjects) { + public List convertTableCells(List tableObjects) { - List parsedTableCells = new ArrayList<>(); + List parsedTableCells = new ArrayList<>(); tableObjects.stream().forEach(t -> { - TableCells tableCells = new TableCells(); + TableExtractorCells tableCells = new TableExtractorCells(); tableCells.setX0(t.getTable().getBbox().get(0)); tableCells.setX1(t.getTable().getBbox().get(2)); tableCells.setY0(t.getTable().getBbox().get(1)); tableCells.setY1(t.getTable().getBbox().get(3)); tableCells.setWidth(tableCells.getX1()- tableCells.getX0()); tableCells.setHeight(tableCells.getY1()- tableCells.getY0()); + tableCells.setLabel(t.getTable().getLabel()); parsedTableCells.add(tableCells); t.getObjects().forEach(o -> { - TableCells objectCell = new TableCells(); + TableExtractorCells objectCell = new TableExtractorCells(); objectCell.setX0(t.getTable().getBbox().get(0)); objectCell.setX1(t.getTable().getBbox().get(2)); objectCell.setY0(t.getTable().getBbox().get(1)); objectCell.setY1(t.getTable().getBbox().get(3)); objectCell.setWidth(objectCell.getX1()- objectCell.getX0()); objectCell.setHeight(objectCell.getY1()- objectCell.getY0()); + objectCell.setLabel(o.getLabel()); parsedTableCells.add(objectCell); }); }); diff --git a/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/python_api/model/table/TableExtractorCells.java b/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/python_api/model/table/TableExtractorCells.java new file mode 100644 index 0000000..6c58b73 --- /dev/null +++ b/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/python_api/model/table/TableExtractorCells.java @@ -0,0 +1,21 @@ +package com.knecon.fforesight.service.layoutparser.processor.python_api.model.table; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class TableExtractorCells { + private float x0; + private float y0; + private float x1; + private float y1; + private float width; + private float height; + private String label; + +} diff --git a/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/services/visualization/ViewerDocumentService.java b/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/services/visualization/ViewerDocumentService.java index 8e5134a..f22bb12 100644 --- a/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/services/visualization/ViewerDocumentService.java +++ b/layoutparser-service/layoutparser-service-processor/src/main/java/com/knecon/fforesight/service/layoutparser/processor/services/visualization/ViewerDocumentService.java @@ -38,6 +38,7 @@ import com.knecon.fforesight.service.layoutparser.processor.model.visualization. import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.ExtractedTable; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.ExtractedTableData; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableCells; +import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableExtractorCells; import com.knecon.fforesight.service.layoutparser.processor.python_api.model.table.TableExtractorData; import com.knecon.fforesight.service.layoutparser.processor.utils.PdfVisualisationUtility; @@ -59,14 +60,16 @@ public class ViewerDocumentService { @SneakyThrows - public void createViewerDocument(PDDocument pdDocument, Document document, OutputStream outputStream, Map> extractedTableCells, boolean layerVisibilityDefaultValue) { + public void createViewerDocument(PDDocument pdDocument, Document document, OutputStream outputStream, Map> extractedTableCells, boolean layerVisibilityDefaultValue) { LayoutGrid layoutGrid = layoutGridService.createLayoutGrid(document); // PDDocument.save() is very slow, since it actually traverses the entire pdf and writes a new one. // If we collect all COSDictionaries we changed and tell it explicitly to only add the changed ones by using saveIncremental it's very fast. Set dictionariesToUpdate = new HashSet<>(); PDOptionalContentGroup layer = addLayerToDocument(pdDocument, dictionariesToUpdate, layerVisibilityDefaultValue); + PDOptionalContentGroup tableExtractorLayer = addLayerToDocument(pdDocument, dictionariesToUpdate, true); + PDFont font = new PDType1Font(Standard14Fonts.FontName.HELVETICA); for (int pageNumber = 0; pageNumber < pdDocument.getNumberOfPages(); pageNumber++) { @@ -125,12 +128,13 @@ public class ViewerDocumentService { } contentStream.restoreGraphicsState(); contentStream.endMarkedContent(); + contentStream.beginMarkedContent(COSName.OC, tableExtractorLayer); contentStream.saveGraphicsState(); contentStream.setLineWidth(LINE_WIDTH); - for (TableCells tableCells : extractedTableCells.get(pageNumber)) { - contentStream.setStrokingColor(new Color(0xFF0000)); + for (TableExtractorCells tableCells : extractedTableCells.get(pageNumber)) { + contentStream.setStrokingColor(new Color(0xB700FF)); contentStream.addRect((float) tableCells.getX0(), (float) tableCells.getY0(), (float) tableCells.getWidth(), (float) tableCells.getHeight()); contentStream.stroke(); contentStream.setFont(font, FONT_SIZE); @@ -141,9 +145,9 @@ public class ViewerDocumentService { (float) textDeRotationMatrix.getScaleY(), tableCells.getX0() , tableCells.getY0()); - // textMatrix.translate(-((font.getStringWidth(tableCells.getLabel()) / 1000) * FONT_SIZE + (2 * LINE_WIDTH) + 4), -FONT_SIZE); - // contentStream.setTextMatrix(textMatrix); - // contentStream.showText(tableCells.getLabel()); + textMatrix.translate(-((font.getStringWidth(tableCells.getLabel()) / 1000) * FONT_SIZE + (2 * LINE_WIDTH) + 4), -FONT_SIZE); + contentStream.setTextMatrix(textMatrix); + contentStream.showText(tableCells.getLabel()); contentStream.endText(); } contentStream.restoreGraphicsState();