diff --git a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/Rectangle.java b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/Rectangle.java index 5a58efc4..0ed06644 100644 --- a/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/Rectangle.java +++ b/redaction-service-v1/redaction-service-api-v1/src/main/java/com/iqser/red/service/redaction/v1/model/Rectangle.java @@ -1,5 +1,8 @@ package com.iqser.red.service.redaction.v1.model; +import com.dslplatform.json.JsonAttribute; +import com.fasterxml.jackson.annotation.JsonIgnore; + import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -15,4 +18,100 @@ public class Rectangle { private int page; + + + @JsonIgnore + @JsonAttribute(ignore = true) + public float getX1(int dir, float pageWidth, float pageHeight) { + + if (dir == 90) { + return topLeft.getX(); + } + else if (dir == 180) { + return pageWidth - topLeft.getX() + width; + + } + else if (dir == 270) { + + return topLeft.getY() + height; + } + else { + return topLeft.getX(); + } + } + + + @JsonIgnore + @JsonAttribute(ignore = true) + public float getX2(int dir, float pageWidth, float pageHeight) { + + if (dir == 90) { + return topLeft.getX() + width; + } + + else if (dir == 180) { + return pageWidth - topLeft.getX(); + } + + else if (dir == 270) { + return topLeft.getY() ; + + } + + else { + return topLeft.getX() + width; + } + } + + + + + + @JsonIgnore + @JsonAttribute(ignore = true) + public float getY1(int dir, float pageWidth, float pageHeight) { + + if (dir == 90 ) { + return topLeft.getY(); + } + + else if (dir == 180) { + return pageHeight - topLeft.getY() + height; + + } + + else if (dir == 270) { + return pageHeight - topLeft.getX() ; + + } + else { + return topLeft.getY(); + } + } + + + @JsonIgnore + @JsonAttribute(ignore = true) + public float getY2(int dir, float pageWidth, float pageHeight) { + + if (dir == 90) { + return topLeft.getY() + height; + } + + else if (dir == 180 ) { + + return pageHeight - topLeft.getY(); + } + + else if (dir == 270 ) { + return pageHeight -topLeft.getX() - width; + } + + else { + return topLeft.getY() + height; + } + } + + + } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/Page.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/Page.java index ec7297eb..f34c0799 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/Page.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/Page.java @@ -1,9 +1,8 @@ package com.iqser.red.service.redaction.v1.server.classification.model; +import com.iqser.red.service.redaction.v1.model.Rectangle; import com.iqser.red.service.redaction.v1.server.redaction.model.PdfImage; import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer; -import com.iqser.red.service.redaction.v1.server.tableextraction.model.Rectangle; - import lombok.Data; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -11,6 +10,8 @@ import lombok.RequiredArgsConstructor; import java.util.ArrayList; import java.util.List; +import org.apache.pdfbox.pdmodel.common.PDRectangle; + @Data @RequiredArgsConstructor public class Page { @@ -33,6 +34,7 @@ public class Page { private StringFrequencyCounter fontStyleCounter = new StringFrequencyCounter(); private double cropBoxArea; + private PDRectangle cropBox; public boolean isRotated() { diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/TextBlock.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/TextBlock.java index d6e14564..49d9fb3c 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/TextBlock.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/model/TextBlock.java @@ -3,6 +3,7 @@ package com.iqser.red.service.redaction.v1.server.classification.model; import com.dslplatform.json.CompiledJson; import com.dslplatform.json.JsonAttribute; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.iqser.red.service.redaction.v1.server.parsing.model.TextDirection; import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSequence; import com.iqser.red.service.redaction.v1.server.redaction.utils.TextNormalizationUtilities; import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer; @@ -50,6 +51,115 @@ public class TextBlock extends AbstractTextContainer { private String classification; + private TextDirection getDir(){ + return sequences.get(0).getDir(); + } + + private float getPageHeight(){ + return sequences.get(0).getPageHeight(); + } + + private float getPageWidth(){ + return sequences.get(0).getPageWidth(); + } + + + @JsonIgnore + @JsonAttribute(ignore = true) + public float getX1() { + + if (getDir().getDegrees() == 90) { + return minX; + } + else if (getDir().getDegrees() == 180) { + return getPageWidth() - maxX; + + } + else if (getDir().getDegrees() == 270) { + + return getPageWidth() - maxY ; + } + else { + return minX; + } + } + + + @JsonIgnore + @JsonAttribute(ignore = true) + public float getX2() { + + if (getDir().getDegrees() == 90) { + return maxX; + } + + else if (getDir().getDegrees() == 180) { + return getPageWidth() - minX; + } + + else if (getDir().getDegrees() == 270) { + return getPageWidth() - minY ; + + } + + else { + return maxX; + } + } + + + + + + @JsonIgnore + @JsonAttribute(ignore = true) + public float getY1() { + + if (getDir().getDegrees() == 90 ) { + return minY; + } + + else if (getDir().getDegrees() == 180) { + return getPageHeight() - maxY; + + } + + else if (getDir().getDegrees() == 270) { + return getPageHeight() - maxX; + + } + else { + return minY; + } + } + + + @JsonIgnore + @JsonAttribute(ignore = true) + public float getY2() { + + if (getDir().getDegrees() == 90) { + return maxY; + } + + else if (getDir().getDegrees() == 180 ) { + + return getPageHeight() - minY; + } + + else if (getDir().getDegrees() == 270 ) { + return getPageHeight() - minX; + } + + else { + return maxY; + } + } + + + + + public TextBlock(float minX, float maxX, float minY, float maxY, List sequences, int rotation) { this.minX = minX; diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BlockificationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BlockificationService.java index 59012bee..e5948c38 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BlockificationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/BlockificationService.java @@ -9,6 +9,8 @@ import java.util.List; import org.springframework.stereotype.Service; +import com.iqser.red.service.redaction.v1.model.Point; +import com.iqser.red.service.redaction.v1.model.Rectangle; import com.iqser.red.service.redaction.v1.server.classification.model.FloatFrequencyCounter; import com.iqser.red.service.redaction.v1.server.classification.model.Orientation; import com.iqser.red.service.redaction.v1.server.classification.model.Page; @@ -18,7 +20,6 @@ import com.iqser.red.service.redaction.v1.server.classification.utils.PositionUt import com.iqser.red.service.redaction.v1.server.parsing.model.TextPositionSequence; import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell; -import com.iqser.red.service.redaction.v1.server.tableextraction.model.Rectangle; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Ruling; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table; @@ -32,7 +33,7 @@ public class BlockificationService { public Page blockify(List textPositions, List horizontalRulingLines, List verticalRulingLines) { - sortRotatedSequences(textPositions); +// sortRotatedSequences(textPositions); List chunkWords = new ArrayList<>(); List chunkBlockList1 = new ArrayList<>(); @@ -108,55 +109,55 @@ public class BlockificationService { chunkBlockList1.add(cb1); } - Iterator itty = chunkBlockList1.iterator(); - - TextBlock previousLeft = null; - TextBlock previousRight = null; - while (itty.hasNext()) { - TextBlock block = (TextBlock) itty.next(); - - if (previousLeft != null && block.getOrientation().equals(Orientation.LEFT)) { - if (previousLeft.getMinY() > block.getMinY() && block.getMaxY() + block.getMostPopularWordHeight() > previousLeft - .getMinY()) { - previousLeft.add(block); - itty.remove(); - continue; - } - } - - if (previousRight != null && block.getOrientation().equals(Orientation.RIGHT)) { - if (previousRight.getMinY() > block.getMinY() && block.getMaxY() + block.getMostPopularWordHeight() > previousRight - .getMinY()) { - previousRight.add(block); - itty.remove(); - continue; - } - } - - if (block.getOrientation().equals(Orientation.LEFT)) { - previousLeft = block; - } else if (block.getOrientation().equals(Orientation.RIGHT)) { - previousRight = block; - } - } - - itty = chunkBlockList1.iterator(); - TextBlock previous = null; - while (itty.hasNext()) { - TextBlock block = (TextBlock) itty.next(); - - if (previous != null && previous.getOrientation().equals(Orientation.LEFT) && block.getOrientation() - .equals(Orientation.LEFT) && equalsWithThreshold(block.getMaxY(), previous.getMaxY()) || previous != null && previous - .getOrientation() - .equals(Orientation.LEFT) && block.getOrientation() - .equals(Orientation.RIGHT) && equalsWithThreshold(block.getMaxY(), previous.getMaxY())) { - previous.add(block); - itty.remove(); - continue; - } - - previous = block; - } +// Iterator itty = chunkBlockList1.iterator(); +// +// TextBlock previousLeft = null; +// TextBlock previousRight = null; +// while (itty.hasNext()) { +// TextBlock block = (TextBlock) itty.next(); +// +// if (previousLeft != null && block.getOrientation().equals(Orientation.LEFT)) { +// if (previousLeft.getMinY() > block.getMinY() && block.getMaxY() + block.getMostPopularWordHeight() > previousLeft +// .getMinY()) { +// previousLeft.add(block); +// itty.remove(); +// continue; +// } +// } +// +// if (previousRight != null && block.getOrientation().equals(Orientation.RIGHT)) { +// if (previousRight.getMinY() > block.getMinY() && block.getMaxY() + block.getMostPopularWordHeight() > previousRight +// .getMinY()) { +// previousRight.add(block); +// itty.remove(); +// continue; +// } +// } +// +// if (block.getOrientation().equals(Orientation.LEFT)) { +// previousLeft = block; +// } else if (block.getOrientation().equals(Orientation.RIGHT)) { +// previousRight = block; +// } +// } +// +// itty = chunkBlockList1.iterator(); +// TextBlock previous = null; +// while (itty.hasNext()) { +// TextBlock block = (TextBlock) itty.next(); +// +// if (previous != null && previous.getOrientation().equals(Orientation.LEFT) && block.getOrientation() +// .equals(Orientation.LEFT) && equalsWithThreshold(block.getMaxY(), previous.getMaxY()) || previous != null && previous +// .getOrientation() +// .equals(Orientation.LEFT) && block.getOrientation() +// .equals(Orientation.RIGHT) && equalsWithThreshold(block.getMaxY(), previous.getMaxY())) { +// previous.add(block); +// itty.remove(); +// continue; +// } +// +// previous = block; +// } return new Page(chunkBlockList1); } @@ -258,17 +259,17 @@ public class BlockificationService { if (documentFontSizeCounter.getMostPopular() != null) { if (textBlock.getMostPopularWordFontSize() >= documentFontSizeCounter.getMostPopular()) { - if (textBlock.getMinX() < minX) { - minX = textBlock.getMinX(); + if (textBlock.getX1() < minX) { + minX = textBlock.getX1(); } - if (textBlock.getMaxX() > maxX) { - maxX = textBlock.getMaxX(); + if (textBlock.getX2() > maxX) { + maxX = textBlock.getX2(); } - if (textBlock.getMinY() < minY) { - minY = textBlock.getMinY(); + if (textBlock.getY1() < minY) { + minY = textBlock.getY1(); } - if (textBlock.getMaxY() > maxY) { - maxY = textBlock.getMaxY(); + if (textBlock.getY2() > maxY) { + maxY = textBlock.getY2(); } } @@ -284,17 +285,17 @@ public class BlockificationService { continue; } for (TextBlock textBlock : cell.getTextBlocks()) { - if (textBlock.getMinX() < minX) { - minX = textBlock.getMinX(); + if (textBlock.getX1() < minX) { + minX = textBlock.getX1(); } - if (textBlock.getMaxX() > maxX) { - maxX = textBlock.getMaxX(); + if (textBlock.getX2() > maxX) { + maxX = textBlock.getX2(); } - if (textBlock.getMinY() < minY) { - minY = textBlock.getMinY(); + if (textBlock.getY1() < minY) { + minY = textBlock.getY1(); } - if (textBlock.getMaxY() > maxY) { - maxY = textBlock.getMaxY(); + if (textBlock.getY2() > maxY) { + maxY = textBlock.getY2(); } } } @@ -303,7 +304,7 @@ public class BlockificationService { } } - return new Rectangle(minY, minX, maxX - minX, maxY - minY); + return new Rectangle(new Point(minX, minY), maxX - minX, maxY - minY, 0); } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/ClassificationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/ClassificationService.java index 1ef01707..190eab04 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/ClassificationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/service/ClassificationService.java @@ -1,15 +1,14 @@ package com.iqser.red.service.redaction.v1.server.classification.service; +import com.iqser.red.service.redaction.v1.model.Point; +import com.iqser.red.service.redaction.v1.model.Rectangle; import com.iqser.red.service.redaction.v1.server.classification.model.Document; import com.iqser.red.service.redaction.v1.server.classification.model.Page; import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock; import com.iqser.red.service.redaction.v1.server.classification.utils.PositionUtils; import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer; -import com.iqser.red.service.redaction.v1.server.tableextraction.model.Rectangle; - import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - import org.springframework.stereotype.Service; import java.util.List; @@ -34,7 +33,23 @@ public class ClassificationService { for (Page page : document.getPages()) { Rectangle btf = page.isLandscape() ? landscapeBodyTextFrame : bodyTextFrame; - page.setBodyTextFrame(btf); + + if (!page.isLandscape() && (page.getRotation() == 90 || page.getRotation() == 270)){ + var width = btf.getX2(page.getRotation(), page.getCropBox().getWidth(), page.getCropBox().getHeight()) - btf.getX1(page.getRotation(), page.getCropBox().getWidth(), page.getCropBox().getHeight()); + var height = btf.getY2(page.getRotation(), page.getCropBox().getWidth(), page.getCropBox().getHeight()) - btf.getY1(page.getRotation(), page.getCropBox().getWidth(), page.getCropBox().getHeight()); + + var x1= btf.getX1(page.getRotation(), page.getCropBox().getWidth(), page.getCropBox().getHeight()); + var y1 = btf.getY1(page.getRotation(), page.getCropBox().getWidth(), page.getCropBox().getHeight()); + + page.setBodyTextFrame(new Rectangle(new Point(x1, y1), width, height,0)); + } else if (page.getRotation() == 180) { + page.setBodyTextFrame(new Rectangle(new Point(btf.getTopLeft().getX(), page.getCropBox().getHeight() - btf.getTopLeft().getY() -btf.getHeight()), btf.getWidth(), btf.getHeight(),0)); + } else { + page.setBodyTextFrame(btf); + } + + + classifyPage(btf, page, document, headlineFontSizes); } } @@ -50,34 +65,37 @@ public class ClassificationService { } - public void classifyBlock(TextBlock textBlock, Rectangle bodyTextFrame, Page page, Document document, List headlineFontSizes) { + public void classifyBlock(TextBlock textBlock, Rectangle bodyTextFrame, Page page, Document document, + List headlineFontSizes) { + + System.out.println("B" + textBlock.getSequences().get(0).getDir()); if (document.getFontSizeCounter().getMostPopular() == null) { textBlock.setClassification("Other"); return; } if (PositionUtils.isOverBodyTextFrame(bodyTextFrame, textBlock, page.isRotated()) && (document.getFontSizeCounter() - .getMostPopular() == null || textBlock.getHighestFontSize() <= document.getFontSizeCounter().getMostPopular())) { + .getMostPopular() == null || textBlock.getHighestFontSize() <= document.getFontSizeCounter() + .getMostPopular())) { textBlock.setClassification("Header"); } else if (PositionUtils.isUnderBodyTextFrame(bodyTextFrame, textBlock) && (document.getFontSizeCounter() - .getMostPopular() == null || textBlock.getHighestFontSize() <= document.getFontSizeCounter().getMostPopular())) { + .getMostPopular() == null || textBlock.getHighestFontSize() <= document.getFontSizeCounter() + .getMostPopular())) { textBlock.setClassification("Footer"); - } else if (page.getPageNumber() == 1 && (!PositionUtils.isTouchingUnderBodyTextFrame(bodyTextFrame, - textBlock) && PositionUtils.getHeightDifferenceBetweenChunkWordAndDocumentWord(textBlock, - document.getTextHeightCounter().getMostPopular()) > 2.5 && textBlock.getHighestFontSize() > document.getFontSizeCounter().getMostPopular() || page.getTextBlocks() - .size() == 1)) { + } else if (page.getPageNumber() == 1 && (!PositionUtils.isTouchingUnderBodyTextFrame(bodyTextFrame, textBlock) && PositionUtils + .getHeightDifferenceBetweenChunkWordAndDocumentWord(textBlock, document.getTextHeightCounter() + .getMostPopular()) > 2.5 && textBlock.getHighestFontSize() > document.getFontSizeCounter() + .getMostPopular() || page.getTextBlocks().size() == 1)) { if (!Pattern.matches("[0-9]+", textBlock.toString())) { textBlock.setClassification("Title"); } - } else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFontSize() > document.getFontSizeCounter() - .getMostPopular() && PositionUtils.getApproxLineCount(textBlock) < 4.9 && (textBlock.getMostPopularWordStyle().equals("bold") || !document.getFontStyleCounter() - .getCountPerValue() - .containsKey("bold") && textBlock.getMostPopularWordFontSize() > document.getFontSizeCounter().getMostPopular() + 1) && textBlock.getSequences() - .get(0) - .getTextPositions() - .get(0) - .getFontSizeInPt() >= textBlock.getMostPopularWordFontSize()) { + } else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFontSize() > document + .getFontSizeCounter() + .getMostPopular() && PositionUtils.getApproxLineCount(textBlock) < 4.9 && (textBlock.getMostPopularWordStyle() + .equals("bold") || !document.getFontStyleCounter().getCountPerValue().containsKey("bold") && textBlock.getMostPopularWordFontSize() > document + .getFontSizeCounter() + .getMostPopular() + 1) && textBlock.getSequences().get(0).getTextPositions().get(0).getFontSizeInPt() >= textBlock.getMostPopularWordFontSize()) { for (int i = 1; i <= headlineFontSizes.size(); i++) { if (textBlock.getMostPopularWordFontSize() == headlineFontSizes.get(i - 1)) { @@ -85,25 +103,28 @@ public class ClassificationService { document.setHeadlines(true); } } - } else if (!textBlock.getText().startsWith("Table ") && !textBlock.getText().startsWith("Figure ") && PositionUtils.isWithinBodyTextFrame(bodyTextFrame, - textBlock) && textBlock.getMostPopularWordStyle().equals("bold") && !document.getFontStyleCounter() + } else if (!textBlock.getText().startsWith("Table ") && !textBlock.getText() + .startsWith("Figure ") && PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordStyle() + .equals("bold") && !document.getFontStyleCounter() .getMostPopular() - .equals("bold") && PositionUtils.getApproxLineCount(textBlock) < 2.9 && textBlock.getSequences() - .get(0) - .getTextPositions() - .get(0) - .getFontSizeInPt() >= textBlock.getMostPopularWordFontSize()) { + .equals("bold") && PositionUtils.getApproxLineCount(textBlock) < 2.9 && textBlock.getSequences().get(0).getTextPositions().get(0).getFontSizeInPt() >= textBlock.getMostPopularWordFontSize()) { textBlock.setClassification("H " + (headlineFontSizes.size() + 1)); document.setHeadlines(true); - } else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFontSize() == document.getFontSizeCounter() - .getMostPopular() && textBlock.getMostPopularWordStyle().equals("bold") && !document.getFontStyleCounter().getMostPopular().equals("bold")) { + } else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFontSize() == document + .getFontSizeCounter() + .getMostPopular() && textBlock.getMostPopularWordStyle() + .equals("bold") && !document.getFontStyleCounter().getMostPopular().equals("bold")) { textBlock.setClassification("TextBlock Bold"); } else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFont() .equals(document.getFontCounter().getMostPopular()) && textBlock.getMostPopularWordStyle() - .equals(document.getFontStyleCounter().getMostPopular()) && textBlock.getMostPopularWordFontSize() == document.getFontSizeCounter().getMostPopular()) { + .equals(document.getFontStyleCounter() + .getMostPopular()) && textBlock.getMostPopularWordFontSize() == document.getFontSizeCounter() + .getMostPopular()) { textBlock.setClassification("TextBlock"); - } else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFontSize() == document.getFontSizeCounter() - .getMostPopular() && textBlock.getMostPopularWordStyle().equals("italic") && !document.getFontStyleCounter() + } else if (PositionUtils.isWithinBodyTextFrame(bodyTextFrame, textBlock) && textBlock.getMostPopularWordFontSize() == document + .getFontSizeCounter() + .getMostPopular() && textBlock.getMostPopularWordStyle() + .equals("italic") && !document.getFontStyleCounter() .getMostPopular() .equals("italic") && PositionUtils.getApproxLineCount(textBlock) < 2.9) { textBlock.setClassification("TextBlock Italic"); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/PositionUtils.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/PositionUtils.java index ce8ee104..7b00b954 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/PositionUtils.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/classification/utils/PositionUtils.java @@ -1,14 +1,14 @@ package com.iqser.red.service.redaction.v1.server.classification.utils; +import com.iqser.red.service.redaction.v1.model.Rectangle; import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock; -import com.iqser.red.service.redaction.v1.server.tableextraction.model.Rectangle; - import lombok.experimental.UtilityClass; @UtilityClass @SuppressWarnings("all") public class PositionUtils { + public boolean isWithinBodyTextFrame(Rectangle btf, TextBlock textBlock) { //TODO Currently this is not working for rotated pages. @@ -19,7 +19,10 @@ public class PositionUtils { double threshold = textBlock.getMostPopularWordHeight() * 3; - if (textBlock.getMinX() + threshold > btf.getX() && textBlock.getMaxX() - threshold < btf.getX() + btf.getWidth() && textBlock.getMinY() + threshold > btf.getY() && textBlock.getMaxY() - threshold < btf.getY() + btf.getHeight()) { + if (textBlock.getMinX() + threshold > btf.getTopLeft().getX() && + textBlock.getMaxX() - threshold < btf.getTopLeft().getX() + btf.getWidth() && + textBlock.getMinY() + threshold > btf.getTopLeft().getY() && + textBlock.getMaxY() - threshold < btf.getTopLeft().getY() + btf.getHeight()) { return true; } else { return false; @@ -34,10 +37,10 @@ public class PositionUtils { return false; } - if (rotated && textBlock.getMinX() < btf.getX()) { + if (rotated && textBlock.getMinX() < btf.getTopLeft().getX()) { // Its very strange, P{0,0} is on top left in this case, instead of lower left. return true; - } else if (!rotated && textBlock.getMinY() > btf.getY() + btf.getHeight()) { + } else if (!rotated && textBlock.getMinY() > btf.getTopLeft().getY() + btf.getHeight()) { return true; } else { return false; @@ -54,7 +57,7 @@ public class PositionUtils { return false; } - if (textBlock.getMaxY() < btf.getY()) { + if (textBlock.getMaxY() < btf.getTopLeft().getY()) { return true; } else { return false; @@ -71,7 +74,7 @@ public class PositionUtils { return false; } - if (textBlock.getMinY() < btf.getY()) { + if (textBlock.getMinY() < btf.getTopLeft().getY()) { return true; } else { return false; @@ -81,14 +84,11 @@ public class PositionUtils { public float getHeightDifferenceBetweenChunkWordAndDocumentWord(TextBlock textBlock, Float documentMostPopularWordHeight) { - return textBlock.getMostPopularWordHeight() - documentMostPopularWordHeight; } public Float getApproxLineCount(TextBlock textBlock) { - return textBlock.getHeight() / textBlock.getMostPopularWordHeight(); } - } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java index a007385e..c2205aee 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/parsing/model/TextPositionSequence.java @@ -163,14 +163,6 @@ public class TextPositionSequence implements CharSequence { if (getDir().getDegrees() == 90) { return textPositions.get(0).getYDirAdj() - getTextHeight(); } - else if (getDir().getDegrees() == 180) { - return pageWidth - textPositions.get(textPositions.size() - 1).getXDirAdj() - textPositions.get(textPositions.size() - 1).getWidthDirAdj() - HEIGHT_PADDING; - - } - else if (getDir().getDegrees() == 270) { - - return pageWidth - textPositions.get(0).getYDirAdj() ; - } else { return textPositions.get(0).getXDirAdj(); } @@ -185,14 +177,6 @@ public class TextPositionSequence implements CharSequence { return textPositions.get(0).getYDirAdj(); } - else if (getDir().getDegrees() == 180) { - return pageWidth - textPositions.get(0).getXDirAdj() ; - } - - else if (getDir().getDegrees() == 270) { - return pageWidth - textPositions.get(0).getYDirAdj() + getTextHeight(); - - } else { return textPositions.get(textPositions.size() - 1).getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidthDirAdj() + HEIGHT_PADDING; @@ -211,16 +195,11 @@ public class TextPositionSequence implements CharSequence { return textPositions.get(0).getXDirAdj(); } - else if (getDir().getDegrees() == 180) { - return textPositions.get(0).getYDirAdj() - getTextHeight(); + if (getDir().getDegrees() == 270) { + return textPositions.get(0).getYDirAdj() - getTextHeight(); } - - else if (getDir().getDegrees() == 270) { - return pageHeight - textPositions.get(textPositions.size() - 1).getXDirAdj() - getTextHeight() + HEIGHT_PADDING; - - } else { return pageHeight - textPositions.get(0).getYDirAdj(); } @@ -235,15 +214,10 @@ public class TextPositionSequence implements CharSequence { return textPositions.get(textPositions.size() - 1).getXDirAdj() + getTextHeight() - HEIGHT_PADDING; } - else if (getDir().getDegrees() == 180 ) { - + if (getDir().getDegrees() == 270) { return textPositions.get(0).getYDirAdj(); } - else if (getDir().getDegrees() == 270 ) { - return pageHeight - textPositions.get(0).getXDirAdj(); - } - else { return pageHeight - textPositions.get(0).getYDirAdj() + getTextHeight(); } diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/segmentation/PdfSegmentationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/segmentation/PdfSegmentationService.java index 1724677c..4eab0cc4 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/segmentation/PdfSegmentationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/segmentation/PdfSegmentationService.java @@ -99,10 +99,10 @@ public class PdfSegmentationService { stripper.getText(pdDocument); PDRectangle pdr = pdPage.getMediaBox(); - boolean isLandscape = pdr.getWidth() > pdr.getHeight(); int rotation = pdPage.getRotation(); - boolean isRotated = rotation != 0 && rotation != 360; + boolean isLandscape = pdr.getWidth() > pdr.getHeight() && (rotation == 0 || rotation == 180) || + pdr.getHeight() > pdr.getWidth() && (rotation == 90 || rotation == 270); CleanRulings cleanRulings = rulingCleaningService.getCleanRulings(pdfTableCells.get(pageNumber), stripper.getRulings(), @@ -115,8 +115,9 @@ public class PdfSegmentationService { page.setCropBoxArea(cropboxArea); page.setRotation(rotation); - page.setLandscape(isLandscape || isRotated); + page.setLandscape(isLandscape); page.setPageNumber(pageNumber); + page.setCropBox(cropbox); tableExtractionService.extractTables(cleanRulings, page); buildPageStatistics(page); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/Rectangle.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/Rectangle.java index 2862e268..37d039ed 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/Rectangle.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/tableextraction/model/Rectangle.java @@ -20,12 +20,11 @@ public class Rectangle extends Rectangle2D.Float { public static final Comparator ILL_DEFINED_ORDER = new Comparator() { @Override public int compare(Rectangle o1, Rectangle o2) { - - if (o1.equals(o2)) { - return 0; - } + if (o1.equals(o2)) return 0; if (o1.verticalOverlap(o2) > VERTICAL_COMPARISON_THRESHOLD) { - return o1.isLtrDominant() == -1 && o2.isLtrDominant() == -1 ? -java.lang.Double.compare(o1.getX(), o2.getX()) : java.lang.Double.compare(o1.getX(), o2.getX()); + return o1.isLtrDominant() == -1 && o2.isLtrDominant() == -1 + ? -java.lang.Double.compare(o1.getX(), o2.getX()) + : java.lang.Double.compare(o1.getX(), o2.getX()); } else { return java.lang.Float.compare(o1.getBottom(), o2.getBottom()); } @@ -33,25 +32,23 @@ public class Rectangle extends Rectangle2D.Float { }; - public Rectangle() { + + + public Rectangle() { super(); } - public Rectangle(float top, float left, float width, float height) { - super(); this.setRect(left, top, width, height); } - /** * @param rectangles * @return minimum bounding box that contains all the rectangles */ public static Rectangle boundingBoxOf(List rectangles) { - float minx = java.lang.Float.MAX_VALUE; float miny = java.lang.Float.MAX_VALUE; float maxx = java.lang.Float.MIN_VALUE; @@ -66,62 +63,50 @@ public class Rectangle extends Rectangle2D.Float { return new Rectangle(miny, minx, maxx - minx, maxy - miny); } - public int compareTo(Rectangle other) { - return ILL_DEFINED_ORDER.compare(this, other); } - // I'm bad at Java and need this for fancy sorting in // technology.tabula.TextChunk. public int isLtrDominant() { - return 0; } - public float getArea() { - return this.width * this.height; } - public float verticalOverlap(Rectangle other) { - return Math.max(0, Math.min(this.getBottom(), other.getBottom()) - Math.max(this.getTop(), other.getTop())); } - public boolean verticallyOverlaps(Rectangle other) { - return verticalOverlap(other) > 0; } - public float horizontalOverlap(Rectangle other) { - return Math.max(0, Math.min(this.getRight(), other.getRight()) - Math.max(this.getLeft(), other.getLeft())); } - public boolean horizontallyOverlaps(Rectangle other) { - return horizontalOverlap(other) > 0; } - public float verticalOverlapRatio(Rectangle other) { - float rv = 0, delta = Math.min(this.getBottom() - this.getTop(), other.getBottom() - other.getTop()); - if (other.getTop() <= this.getTop() && this.getTop() <= other.getBottom() && other.getBottom() <= this.getBottom()) { + if (other.getTop() <= this.getTop() && this.getTop() <= other.getBottom() + && other.getBottom() <= this.getBottom()) { rv = (other.getBottom() - this.getTop()) / delta; - } else if (this.getTop() <= other.getTop() && other.getTop() <= this.getBottom() && this.getBottom() <= other.getBottom()) { + } else if (this.getTop() <= other.getTop() && other.getTop() <= this.getBottom() + && this.getBottom() <= other.getBottom()) { rv = (this.getBottom() - other.getTop()) / delta; - } else if (this.getTop() <= other.getTop() && other.getTop() <= other.getBottom() && other.getBottom() <= this.getBottom()) { + } else if (this.getTop() <= other.getTop() && other.getTop() <= other.getBottom() + && other.getBottom() <= this.getBottom()) { rv = (other.getBottom() - other.getTop()) / delta; - } else if (other.getTop() <= this.getTop() && this.getTop() <= this.getBottom() && this.getBottom() <= other.getBottom()) { + } else if (other.getTop() <= this.getTop() && this.getTop() <= this.getBottom() + && this.getBottom() <= other.getBottom()) { rv = (this.getBottom() - this.getTop()) / delta; } @@ -129,85 +114,64 @@ public class Rectangle extends Rectangle2D.Float { } - public float overlapRatio(Rectangle other) { - - double intersectionWidth = Math.max(0, Math.min(this.getRight(), other.getRight()) - Math.max(this.getLeft(), other.getLeft())); - double intersectionHeight = Math.max(0, Math.min(this.getBottom(), other.getBottom()) - Math.max(this.getTop(), other.getTop())); + double intersectionWidth = Math.max(0, + Math.min(this.getRight(), other.getRight()) - Math.max(this.getLeft(), other.getLeft())); + double intersectionHeight = Math.max(0, + Math.min(this.getBottom(), other.getBottom()) - Math.max(this.getTop(), other.getTop())); double intersectionArea = Math.max(0, intersectionWidth * intersectionHeight); double unionArea = this.getArea() + other.getArea() - intersectionArea; return (float) (intersectionArea / unionArea); } - public Rectangle merge(Rectangle other) { - this.setRect(this.createUnion(other)); return this; } - public float getTop() { - return (float) this.getMinY(); } - public void setTop(float top) { - float deltaHeight = top - this.y; this.setRect(this.x, top, this.width, this.height - deltaHeight); } - public float getRight() { - return (float) this.getMaxX(); } - public void setRight(float right) { - this.setRect(this.x, this.y, right - this.x, this.height); } - public float getLeft() { - return (float) this.getMinX(); } - public void setLeft(float left) { - float deltaWidth = left - this.x; this.setRect(left, this.y, this.width - deltaWidth, this.height); } - public float getBottom() { - return (float) this.getMaxY(); } - public void setBottom(float bottom) { - this.setRect(this.x, this.y, this.width, bottom - this.y); } - public Point2D[] getPoints() { - - return new Point2D[]{new Point2D.Float(this.getLeft(), this.getTop()), new Point2D.Float(this.getRight(), this.getTop()), new Point2D.Float(this.getRight(), - this.getBottom()), new Point2D.Float(this.getLeft(), this.getBottom())}; + return new Point2D[]{new Point2D.Float(this.getLeft(), this.getTop()), + new Point2D.Float(this.getRight(), this.getTop()), new Point2D.Float(this.getRight(), this.getBottom()), + new Point2D.Float(this.getLeft(), this.getBottom())}; } - @Override public String toString() { - StringBuilder sb = new StringBuilder(); String s = super.toString(); sb.append(s.substring(0, s.length() - 1)); diff --git a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/PdfVisualisationService.java b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/PdfVisualisationService.java index 460e17a2..f8af77f1 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/PdfVisualisationService.java +++ b/redaction-service-v1/redaction-service-server-v1/src/main/java/com/iqser/red/service/redaction/v1/server/visualization/service/PdfVisualisationService.java @@ -7,10 +7,8 @@ import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock; import com.iqser.red.service.redaction.v1.server.tableextraction.model.AbstractTextContainer; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Cell; import com.iqser.red.service.redaction.v1.server.tableextraction.model.Table; - import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; - import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.pdmodel.PDPage; import org.apache.pdfbox.pdmodel.PDPageContentStream; @@ -26,6 +24,7 @@ import java.util.List; @RequiredArgsConstructor public class PdfVisualisationService { + public void visualizeParagraphs(Document classifiedDoc, PDDocument document) throws IOException { for (int page = 1; page <= document.getNumberOfPages(); page++) { @@ -67,6 +66,7 @@ public class PdfVisualisationService { PDPage pdPage = document.getPage(page - 1); PDPageContentStream contentStream = new PDPageContentStream(document, pdPage, PDPageContentStream.AppendMode.APPEND, true); + for (AbstractTextContainer textBlock : analyzedPage.getTextBlocks()) { if (textBlock == null) { continue; @@ -79,10 +79,10 @@ public class PdfVisualisationService { } contentStream.setStrokingColor(Color.YELLOW); - contentStream.addRect((float) analyzedPage.getBodyTextFrame().getX(), - (float) analyzedPage.getBodyTextFrame().getY(), - (float) analyzedPage.getBodyTextFrame().getWidth(), - (float) analyzedPage.getBodyTextFrame().getHeight()); +// var widhth = analyzedPage.getBodyTextFrame().getX2(pdPage.getRotation(), pdPage.getCropBox().getWidth(), pdPage.getCropBox().getHeight()) - analyzedPage.getBodyTextFrame().getX1(pdPage.getRotation(), pdPage.getCropBox().getWidth(), pdPage.getCropBox().getHeight()); +// var height = analyzedPage.getBodyTextFrame().getY2(pdPage.getRotation(), pdPage.getCropBox().getWidth(), pdPage.getCropBox().getHeight()) - analyzedPage.getBodyTextFrame().getY1(pdPage.getRotation(), pdPage.getCropBox().getWidth(), pdPage.getCropBox().getHeight()); + + contentStream.addRect(analyzedPage.getBodyTextFrame().getTopLeft().getX(), analyzedPage.getBodyTextFrame().getTopLeft().getY(), analyzedPage.getBodyTextFrame().getWidth(), analyzedPage.getBodyTextFrame().getHeight()); contentStream.stroke(); contentStream.close(); @@ -94,33 +94,40 @@ public class PdfVisualisationService { contentStream.setStrokingColor(Color.RED); - contentStream.addRect(textBlock.getMinX(), textBlock.getMinY(), textBlock.getWidth(), textBlock.getHeight()); + contentStream.addRect(textBlock.getX1(), textBlock.getY1(), textBlock.getX2() - textBlock.getX1(), textBlock.getY2() - textBlock.getY1()); contentStream.stroke(); if (textBlock.getClassification() != null) { contentStream.beginText(); + contentStream.setFont(PDType1Font.TIMES_ROMAN, 6f); + + contentStream.newLineAtOffset(textBlock.getX1(), textBlock.getY2() + 2); + contentStream.showText(textBlock.getClassification() + textBlock.getOrientation() + "-->" + textBlock.getSequences().get(0).getDir()); + + contentStream.endText(); + + contentStream.setNonStrokingColor(Color.BLUE); contentStream.setFont(PDType1Font.TIMES_ROMAN, 2f); - contentStream.newLineAtOffset(textBlock.getMinX(), textBlock.getMaxY() + 10); - contentStream.showText(textBlock.getClassification() + textBlock.getOrientation() + "-->" + textBlock.getSequences().get(0).getDir()); + + + contentStream.beginText(); + contentStream.newLineAtOffset(textBlock.getX1(), textBlock.getY1()); + contentStream.showText("MinX,MinY(" + textBlock.getX1() + "," + textBlock.getY1() + ")"); contentStream.endText(); contentStream.beginText(); - contentStream.newLineAtOffset(textBlock.getMinX(), textBlock.getMinY()); - contentStream.showText("MinX,MinY"); + contentStream.newLineAtOffset(textBlock.getX2(), textBlock.getY1()); + contentStream.showText("MaxX,MinY(" + textBlock.getX2() + "," + textBlock.getY1() + ")"); contentStream.endText(); contentStream.beginText(); - contentStream.newLineAtOffset(textBlock.getMaxX(), textBlock.getMinY()); - contentStream.showText("MaxX,MinY"); + contentStream.newLineAtOffset(textBlock.getX1(), textBlock.getY2()); + contentStream.showText("MinX,MaxY(" + textBlock.getX1() + "," + textBlock.getY2() + ")"); contentStream.endText(); contentStream.beginText(); - contentStream.newLineAtOffset(textBlock.getMinX(), textBlock.getMaxY()); - contentStream.showText("MinX,MaxY"); - contentStream.endText(); - contentStream.beginText(); - contentStream.newLineAtOffset(textBlock.getMaxX(), textBlock.getMaxY()); - contentStream.showText("MaxX,MaxY"); + contentStream.newLineAtOffset(textBlock.getX2(), textBlock.getY2()); + contentStream.showText("MaxX,MaxY(" + textBlock.getX2() + "," + textBlock.getY2() + ")"); contentStream.endText(); @@ -129,7 +136,6 @@ public class PdfVisualisationService { private void visualizeTable(Table table, PDPageContentStream contentStream) throws IOException { - for (List row : table.getRows()) { for (Cell cell : row) { @@ -160,5 +166,4 @@ public class PdfVisualisationService { contentStream.endText(); } } - } diff --git a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java index 5a15bc95..98aa410c 100644 --- a/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java +++ b/redaction-service-v1/redaction-service-server-v1/src/test/java/com/iqser/red/service/redaction/v1/server/RedactionIntegrationTest.java @@ -1098,7 +1098,7 @@ public class RedactionIntegrationTest { System.out.println("classificationTest"); - AnalyzeRequest request = prepareStorage("files/new/RotateTestFile.pdf"); + AnalyzeRequest request = prepareStorage("files/RSS/02 - A22833B - Acute Oral (Up and Down) - Final Report1.pdf"); RedactionRequest redactionRequest = RedactionRequest.builder() .dossierId(request.getDossierId())