Compare commits
6 Commits
master
...
RED-5381-T
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
254f59e330 | ||
|
|
c0e354d2d4 | ||
|
|
dbc2e8e2f8 | ||
|
|
4616420e8f | ||
|
|
29f47fb17a | ||
|
|
dafc140f11 |
@ -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;
|
||||
@ -14,4 +17,115 @@ public class Rectangle {
|
||||
private float height;
|
||||
|
||||
private int page;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getX1(int dir, float pageWidth, float pageHeight) {
|
||||
|
||||
if (dir == 90) {
|
||||
return topLeft.getY();
|
||||
}
|
||||
else if (dir == 180) {
|
||||
return 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.getY() + height;
|
||||
}
|
||||
|
||||
else if (dir == 180) {
|
||||
return 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.getX();
|
||||
}
|
||||
|
||||
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.getX() + width;
|
||||
}
|
||||
|
||||
else if (dir == 180 ) {
|
||||
|
||||
return pageHeight - topLeft.getY();
|
||||
}
|
||||
|
||||
else if (dir == 270 ) {
|
||||
return pageHeight -topLeft.getX() - width;
|
||||
}
|
||||
|
||||
else {
|
||||
return topLeft.getY() + height;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +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;
|
||||
@ -10,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 {
|
||||
@ -32,6 +34,7 @@ public class Page {
|
||||
private StringFrequencyCounter fontStyleCounter = new StringFrequencyCounter();
|
||||
|
||||
private double cropBoxArea;
|
||||
private PDRectangle cropBox;
|
||||
|
||||
|
||||
public boolean isRotated() {
|
||||
|
||||
@ -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 minY;
|
||||
}
|
||||
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 maxY;
|
||||
}
|
||||
|
||||
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 minX;
|
||||
}
|
||||
|
||||
else if (getDir().getDegrees() == 180) {
|
||||
return maxY;
|
||||
|
||||
}
|
||||
|
||||
else if (getDir().getDegrees() == 270) {
|
||||
return getPageHeight() - maxX;
|
||||
|
||||
}
|
||||
else {
|
||||
return getPageHeight() - maxY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getY2() {
|
||||
|
||||
if (getDir().getDegrees() == 90) {
|
||||
return maxX;
|
||||
}
|
||||
|
||||
else if (getDir().getDegrees() == 180 ) {
|
||||
|
||||
return minY;
|
||||
}
|
||||
|
||||
else if (getDir().getDegrees() == 270 ) {
|
||||
return getPageHeight() - minX;
|
||||
}
|
||||
|
||||
else {
|
||||
return getPageHeight() - minY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public TextBlock(float minX, float maxX, float minY, float maxY, List<TextPositionSequence> sequences, int rotation) {
|
||||
this.minX = minX;
|
||||
this.maxX = maxX;
|
||||
|
||||
@ -2,13 +2,18 @@ package com.iqser.red.service.redaction.v1.server.classification.service;
|
||||
|
||||
import static java.util.stream.Collectors.toSet;
|
||||
|
||||
import java.awt.geom.Line2D;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
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 +23,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;
|
||||
|
||||
@ -30,9 +34,9 @@ public class BlockificationService {
|
||||
|
||||
|
||||
public Page blockify(List<TextPositionSequence> textPositions, List<Ruling> horizontalRulingLines,
|
||||
List<Ruling> verticalRulingLines) {
|
||||
List<Ruling> verticalRulingLines, int rotation, PDRectangle cropbox) {
|
||||
|
||||
sortRotatedSequences(textPositions);
|
||||
// sortRotatedSequences(textPositions);
|
||||
|
||||
List<TextPositionSequence> chunkWords = new ArrayList<>();
|
||||
List<AbstractTextContainer> chunkBlockList1 = new ArrayList<>();
|
||||
@ -44,18 +48,20 @@ public class BlockificationService {
|
||||
Float splitX1 = null;
|
||||
for (TextPositionSequence word : textPositions) {
|
||||
|
||||
boolean lineSeparation = minY - word.getY2() > word.getHeight() * 1.25;
|
||||
boolean startFromTop = word.getY1() > maxY + word.getHeight();
|
||||
boolean lineSeparation = word.getY1() - maxY > word.getHeight() * 1.25;
|
||||
boolean startFromTop = prev != null && word.getY1() < prev.getY1() - prev.getTextHeight();
|
||||
boolean splitByX = prev != null && maxX + 50 < word.getX1() && prev.getY1() == word.getY1();
|
||||
boolean xIsBeforeFirstX = prev != null && word.getX1() < minX;
|
||||
boolean newLineAfterSplit = prev != null && word.getY1() != prev.getY1() && wasSplitted && splitX1 != word.getX1();
|
||||
boolean splittedByRuling =
|
||||
isSplittedByRuling(maxX, minY, word.getX1(), word.getY1(), verticalRulingLines) ||
|
||||
isSplittedByRuling(minX, minY, word.getX1(), word.getY2(), horizontalRulingLines)
|
||||
isSplittedByRuling(maxX, minY, word.getX1(), word.getY1(), verticalRulingLines, word.getDir().getDegrees(), cropbox.getWidth(), cropbox.getHeight()) ||
|
||||
isSplittedByRuling(minX, minY, word.getX1(), word.getY2(), horizontalRulingLines, word.getDir().getDegrees(), cropbox.getWidth(), cropbox.getHeight())
|
||||
|
||||
|| isSplittedByRuling(maxX, minY, word.getX1(), word.getY1(), horizontalRulingLines)
|
||||
|| isSplittedByRuling(minX, minY, word.getX1(), word.getY2(), verticalRulingLines);
|
||||
|| isSplittedByRuling(maxX, minY, word.getX1(), word.getY1(), horizontalRulingLines, word.getDir().getDegrees(), cropbox.getWidth(), cropbox.getHeight())
|
||||
|| isSplittedByRuling(minX, minY, word.getX1(), word.getY2(), verticalRulingLines, word.getDir().getDegrees(), cropbox.getWidth(), cropbox.getHeight());
|
||||
boolean splitByDir = prev != null && !prev.getDir().equals(word.getDir());
|
||||
|
||||
if (prev != null && (lineSeparation || startFromTop || splitByX || newLineAfterSplit || splittedByRuling)) {
|
||||
if (prev != null && (lineSeparation || startFromTop || xIsBeforeFirstX || splitByX || splitByDir || splittedByRuling)) {
|
||||
|
||||
Orientation prevOrientation = null;
|
||||
if (!chunkBlockList1.isEmpty()) {
|
||||
@ -216,10 +222,11 @@ public class BlockificationService {
|
||||
|
||||
|
||||
private boolean isSplittedByRuling(float previousX2, float previousY1, float currentX1, float currentY1,
|
||||
List<Ruling> rulingLines) {
|
||||
List<Ruling> rulingLines, float rotation, float pageWidth, float pageHeight) {
|
||||
|
||||
for (Ruling ruling : rulingLines) {
|
||||
if (ruling.intersectsLine(previousX2, previousY1, currentX1, currentY1)) {
|
||||
var line = convertToJavaCoord(ruling, rotation, pageWidth, pageHeight);
|
||||
if (line.intersectsLine(previousX2, previousY1, currentX1, currentY1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -227,6 +234,74 @@ public class BlockificationService {
|
||||
}
|
||||
|
||||
|
||||
private Line2D.Float convertToJavaCoord(Ruling ruling, float rotation, float pageWidth, float pageHeight){
|
||||
|
||||
|
||||
return new Line2D.Float(convertPoint(ruling.x1, ruling.y1, rotation, pageWidth, pageHeight), convertPoint(ruling.x2, ruling.y2, rotation, pageWidth, pageHeight));
|
||||
|
||||
|
||||
}
|
||||
|
||||
private Point2D convertPoint(float x, float y, float rotation, float pageWidth, float pageHeight){
|
||||
var xAdj = getXRot(x,y,rotation, pageWidth, pageHeight);
|
||||
var yAdj = 0f;
|
||||
if (rotation == 0 || rotation == 180)
|
||||
{
|
||||
yAdj = pageHeight - getYLowerLeftRot(x,y,rotation, pageWidth, pageHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
yAdj = pageWidth - getYLowerLeftRot(x,y,rotation, pageWidth, pageHeight);
|
||||
}
|
||||
return new Point2D.Float(xAdj, yAdj);
|
||||
}
|
||||
|
||||
private float getXRot(float x, float y, float rotation, float pageWidth, float pageHeight)
|
||||
{
|
||||
if (rotation == 0)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
else if (rotation == 90)
|
||||
{
|
||||
return y;
|
||||
}
|
||||
else if (rotation == 180)
|
||||
{
|
||||
return pageWidth - x;
|
||||
}
|
||||
else if (rotation == 270)
|
||||
{
|
||||
return pageHeight - y;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private float getYLowerLeftRot(float x, float y, float rotation, float pageWidth, float pageHeight)
|
||||
{
|
||||
if (rotation == 0)
|
||||
{
|
||||
return y;
|
||||
}
|
||||
else if (rotation == 90)
|
||||
{
|
||||
return pageWidth - x;
|
||||
}
|
||||
else if (rotation == 180)
|
||||
{
|
||||
return pageHeight - y;
|
||||
}
|
||||
else if (rotation == 270)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public Rectangle calculateBodyTextFrame(List<Page> pages, FloatFrequencyCounter documentFontSizeCounter,
|
||||
boolean landscape) {
|
||||
|
||||
@ -257,19 +332,33 @@ public class BlockificationService {
|
||||
if (documentFontSizeCounter.getMostPopular() != null) {
|
||||
if (textBlock.getMostPopularWordFontSize() >= documentFontSizeCounter.getMostPopular()) {
|
||||
|
||||
if (textBlock.getMinX() < minX) {
|
||||
minX = textBlock.getMinX();
|
||||
if(page.getCropBox().getWidth() > page.getCropBox().getHeight()){
|
||||
if (textBlock.getY1() < minX) {
|
||||
minX = textBlock.getY1();
|
||||
}
|
||||
if (textBlock.getMaxX() > maxX) {
|
||||
maxX = textBlock.getMaxX();
|
||||
if (textBlock.getY2() > maxX) {
|
||||
maxX = textBlock.getY2();
|
||||
}
|
||||
if (textBlock.getMinY() < minY) {
|
||||
minY = textBlock.getMinY();
|
||||
if (textBlock.getX1() < minY) {
|
||||
minY = textBlock.getX1();
|
||||
}
|
||||
if (textBlock.getX2() > maxY) {
|
||||
maxY = textBlock.getX2();
|
||||
}
|
||||
} else {
|
||||
if (textBlock.getX1() < minX) {
|
||||
minX = textBlock.getX1();
|
||||
}
|
||||
if (textBlock.getX2() > maxX) {
|
||||
maxX = textBlock.getX2();
|
||||
}
|
||||
if (textBlock.getY1() < minY) {
|
||||
minY = textBlock.getY1();
|
||||
}
|
||||
if (textBlock.getY2() > maxY) {
|
||||
maxY = textBlock.getY2();
|
||||
}
|
||||
if (textBlock.getMaxY() > maxY) {
|
||||
maxY = textBlock.getMaxY();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -283,46 +372,46 @@ public class BlockificationService {
|
||||
continue;
|
||||
}
|
||||
for (TextBlock textBlock : cell.getTextBlocks()) {
|
||||
if (textBlock.getMinX() < minX) {
|
||||
minX = textBlock.getMinX();
|
||||
if(page.getCropBox().getWidth() > page.getCropBox().getHeight()){
|
||||
if (textBlock.getY1() < minX) {
|
||||
minX = textBlock.getMinY();
|
||||
}
|
||||
if (textBlock.getMaxX() > maxX) {
|
||||
maxX = textBlock.getMaxX();
|
||||
if (textBlock.getY2() > maxX) {
|
||||
maxX = textBlock.getY2();
|
||||
}
|
||||
if (textBlock.getMinY() < minY) {
|
||||
minY = textBlock.getMinY();
|
||||
if (textBlock.getX1() < minY) {
|
||||
minY = textBlock.getX1();
|
||||
}
|
||||
if (textBlock.getMaxY() > maxY) {
|
||||
maxY = textBlock.getMaxY();
|
||||
if (textBlock.getX2() > maxY) {
|
||||
maxY = textBlock.getX2();
|
||||
}
|
||||
} else {
|
||||
if (textBlock.getX1() < minX) {
|
||||
minX = textBlock.getX1();
|
||||
}
|
||||
if (textBlock.getX2() > maxX) {
|
||||
maxX = textBlock.getX2();
|
||||
}
|
||||
if (textBlock.getY1() < minY) {
|
||||
minY = textBlock.getY1();
|
||||
}
|
||||
if (textBlock.getY2() > maxY) {
|
||||
maxY = textBlock.getY2();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("Page: " + page.getPageNumber() + " Landscape: " + page.isLandscape()+ " MinX: " + minX + " MaxX: " + maxX + " MinY: " +minY + " MaxY: " + maxY);
|
||||
|
||||
}
|
||||
return new Rectangle(minY, minX, maxX - minX, maxY - minY);
|
||||
return new Rectangle(new Point(minX, minY), maxX - minX, maxY - minY, 0);
|
||||
}
|
||||
|
||||
|
||||
private void sortRotatedSequences(List<TextPositionSequence> sequences) {
|
||||
|
||||
List<TextPositionSequence> rotatedWords = new ArrayList<>();
|
||||
Iterator<TextPositionSequence> itty = sequences.iterator();
|
||||
while (itty.hasNext()) {
|
||||
var pos = itty.next();
|
||||
if (pos.getTextPositions().get(0).getDir() == 270) {
|
||||
rotatedWords.add(pos);
|
||||
itty.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (!rotatedWords.isEmpty() && !sequences.isEmpty()) {
|
||||
rotatedWords.sort(Comparator.comparing(TextPositionSequence::getX1));
|
||||
}
|
||||
sequences.addAll(rotatedWords);
|
||||
}
|
||||
|
||||
|
||||
private double round(float value, int decimalPoints) {
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
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;
|
||||
@ -32,7 +33,29 @@ public class ClassificationService {
|
||||
|
||||
for (Page page : document.getPages()) {
|
||||
Rectangle btf = page.isLandscape() ? landscapeBodyTextFrame : bodyTextFrame;
|
||||
|
||||
|
||||
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());
|
||||
|
||||
if(page.getCropBox().getWidth() > page.getCropBox().getHeight() && page.getRotation() == 270) {
|
||||
page.setBodyTextFrame(new Rectangle(new Point(btf.getTopLeft().getY(),page.getCropBox().getHeight() - btf.getTopLeft().getX()), btf.getHeight(), -btf.getWidth(), 0));
|
||||
}
|
||||
else if(page.getCropBox().getWidth() > page.getCropBox().getHeight()) {
|
||||
page.setBodyTextFrame(new Rectangle(new Point(btf.getTopLeft().getY(), btf.getTopLeft().getX()), btf.getHeight(), btf.getWidth(), 0));
|
||||
} else if(page.getRotation() == 180){
|
||||
page.setBodyTextFrame(new Rectangle(new Point( btf.getTopLeft().getX(), page.getCropBox().getHeight() - btf.getTopLeft().getY()), btf.getWidth(), -btf.getHeight(), 0));
|
||||
}
|
||||
else {
|
||||
page.setBodyTextFrame(btf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
classifyPage(btf, page, document, headlineFontSizes);
|
||||
}
|
||||
}
|
||||
@ -51,6 +74,8 @@ public class ClassificationService {
|
||||
public void classifyBlock(TextBlock textBlock, Rectangle bodyTextFrame, Page page, Document document,
|
||||
List<Float> headlineFontSizes) {
|
||||
|
||||
System.out.println("Page: " + page.getPageNumber() + " rotation " + page.getRotation() +" B " + textBlock.getSequences().get(0).getDir());
|
||||
|
||||
if (document.getFontSizeCounter().getMostPopular() == null) {
|
||||
textBlock.setClassification("Other");
|
||||
return;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
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
|
||||
@ -19,10 +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;
|
||||
@ -37,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;
|
||||
@ -57,7 +57,7 @@ public class PositionUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (textBlock.getMaxY() < btf.getY()) {
|
||||
if (textBlock.getMaxY() < btf.getTopLeft().getY()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -74,7 +74,7 @@ public class PositionUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (textBlock.getMinY() < btf.getY()) {
|
||||
if (textBlock.getMinY() < btf.getTopLeft().getY()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@ -147,29 +147,6 @@ public class TextPositionSequence implements CharSequence {
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getX1() {
|
||||
|
||||
if (rotation == 90) {
|
||||
return textPositions.get(0).getYDirAdj() - getTextHeight();
|
||||
} else {
|
||||
return textPositions.get(0).getXDirAdj();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getX2() {
|
||||
|
||||
if (rotation == 90) {
|
||||
return textPositions.get(0).getYDirAdj();
|
||||
} else {
|
||||
return textPositions.get(textPositions.size() - 1).getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidthDirAdj() + HEIGHT_PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
@ -179,15 +156,40 @@ public class TextPositionSequence implements CharSequence {
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getX1() {
|
||||
|
||||
|
||||
return textPositions.get(0).getXDirAdj();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getX2() {
|
||||
|
||||
|
||||
return textPositions.get(textPositions.size() - 1).getXDirAdj() + textPositions.get(textPositions.size() - 1).getWidthDirAdj() + HEIGHT_PADDING;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getY1() {
|
||||
|
||||
if (rotation == 90) {
|
||||
return textPositions.get(0).getXDirAdj();
|
||||
} else {
|
||||
return pageHeight - textPositions.get(0).getYDirAdj();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
return textPositions.get(0).getYDirAdj() - getTextHeight();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -195,14 +197,15 @@ public class TextPositionSequence implements CharSequence {
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getY2() {
|
||||
|
||||
if (rotation == 90) {
|
||||
return textPositions.get(textPositions.size() - 1).getXDirAdj() + getTextHeight() - HEIGHT_PADDING;
|
||||
} else {
|
||||
return pageHeight - textPositions.get(0).getYDirAdj() + getTextHeight();
|
||||
}
|
||||
|
||||
|
||||
|
||||
return textPositions.get(0).getYDirAdj();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@JsonIgnore
|
||||
@JsonAttribute(ignore = true)
|
||||
public float getTextHeight() {
|
||||
|
||||
@ -99,21 +99,23 @@ 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;
|
||||
|
||||
CleanRulings cleanRulings = rulingCleaningService.getCleanRulings(pdfTableCells.get(pageNumber), stripper.getRulings(), stripper.getMinCharWidth(), stripper.getMaxCharHeight());
|
||||
Page page = blockificationService.blockify(stripper.getTextPositionSequences(), cleanRulings.getHorizontal(), cleanRulings.getVertical());
|
||||
boolean isLandscape = pdr.getWidth() > pdr.getHeight() && (rotation == 0 || rotation == 180) ||
|
||||
pdr.getHeight() > pdr.getWidth() && (rotation == 90 || rotation == 270);
|
||||
|
||||
PDRectangle cropbox = pdPage.getCropBox();
|
||||
CleanRulings cleanRulings = rulingCleaningService.getCleanRulings(pdfTableCells.get(pageNumber), stripper.getRulings(), stripper.getMinCharWidth(), stripper.getMaxCharHeight());
|
||||
Page page = blockificationService.blockify(stripper.getTextPositionSequences(), cleanRulings.getHorizontal(), cleanRulings.getVertical(), rotation, cropbox);
|
||||
|
||||
|
||||
float cropboxArea = cropbox.getHeight() * cropbox.getWidth();
|
||||
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);
|
||||
|
||||
@ -4,6 +4,8 @@ import com.dslplatform.json.JsonAttribute;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.iqser.red.service.redaction.v1.model.Rectangle;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Orientation;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@ -31,6 +33,12 @@ public abstract class AbstractTextContainer {
|
||||
|
||||
public abstract String getText();
|
||||
|
||||
|
||||
public boolean containsBlock(TextBlock other) {
|
||||
return this.minX <= other.getX1() && this.maxX >= other.getX2() && this.minY >= other.getY1() && this.maxY <= other.getY2();
|
||||
}
|
||||
|
||||
|
||||
public boolean contains(AbstractTextContainer other) {
|
||||
return this.minX <= other.minX && this.maxX >= other.maxX && this.minY >= other.minY && this.maxY <= other.maxY;
|
||||
}
|
||||
|
||||
@ -31,6 +31,10 @@ public class Rectangle extends Rectangle2D.Float {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public Rectangle() {
|
||||
super();
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ public class TableExtractionService {
|
||||
for (AbstractTextContainer abstractTextContainer : page.getTextBlocks()) {
|
||||
TextBlock textBlock = (TextBlock) abstractTextContainer;
|
||||
for (Cell cell : cells) {
|
||||
if (cell.intersects(textBlock.getMinX(), textBlock.getMinY(), textBlock.getWidth(), textBlock.getHeight())) {
|
||||
if (cell.intersects(textBlock.getX1(), textBlock.getY1(), textBlock.getX2() - textBlock.getX1(), textBlock.getY2() - textBlock.getY1())) {
|
||||
cell.addTextBlock(textBlock);
|
||||
toBeRemoved.add(textBlock);
|
||||
break;
|
||||
@ -94,7 +94,7 @@ public class TableExtractionService {
|
||||
Iterator<AbstractTextContainer> itty = page.getTextBlocks().iterator();
|
||||
while (itty.hasNext()) {
|
||||
AbstractTextContainer textBlock = itty.next();
|
||||
if (table.contains(textBlock) && position == -1) {
|
||||
if (textBlock instanceof TextBlock ? table.containsBlock((TextBlock) textBlock) : table.contains(textBlock) && position == -1) {
|
||||
position = page.getTextBlocks().indexOf(textBlock);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,13 @@ 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 width = 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().getX1(pdPage.getRotation(), pdPage.getCropBox().getWidth(), pdPage.getCropBox().getHeight()), analyzedPage.getBodyTextFrame().getY1(pdPage.getRotation(), pdPage.getCropBox().getWidth(), pdPage.getCropBox().getHeight()), width, height);
|
||||
|
||||
contentStream.addRect(analyzedPage.getBodyTextFrame().getTopLeft().getX(), analyzedPage.getBodyTextFrame().getTopLeft().getY(), analyzedPage.getBodyTextFrame().getWidth(), analyzedPage.getBodyTextFrame().getHeight());
|
||||
|
||||
contentStream.stroke();
|
||||
|
||||
contentStream.close();
|
||||
@ -91,20 +97,44 @@ 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.setNonStrokingColor(Color.BLUE);
|
||||
contentStream.setFont(PDType1Font.TIMES_ROMAN, 12f);
|
||||
contentStream.setFont(PDType1Font.TIMES_ROMAN, 9f);
|
||||
|
||||
contentStream.newLineAtOffset(textBlock.getMinX(), textBlock.getMaxY());
|
||||
|
||||
contentStream.showText(textBlock.getClassification() + textBlock.getOrientation());
|
||||
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.beginText();
|
||||
// contentStream.newLineAtOffset(textBlock.getX1(), textBlock.getY1());
|
||||
// contentStream.showText("MinX,MinY(" + textBlock.getX1() + "," + textBlock.getY1() + ")");
|
||||
// contentStream.endText();
|
||||
// contentStream.beginText();
|
||||
// contentStream.newLineAtOffset(textBlock.getX2(), textBlock.getY1());
|
||||
// contentStream.showText("MaxX,MinY(" + textBlock.getX2() + "," + textBlock.getY1() + ")");
|
||||
// contentStream.endText();
|
||||
// contentStream.beginText();
|
||||
// contentStream.newLineAtOffset(textBlock.getX1(), textBlock.getY2());
|
||||
// contentStream.showText("MinX,MaxY(" + textBlock.getX1() + "," + textBlock.getY2() + ")");
|
||||
// contentStream.endText();
|
||||
// contentStream.beginText();
|
||||
// contentStream.newLineAtOffset(textBlock.getX2(), textBlock.getY2());
|
||||
// contentStream.showText("MaxX,MaxY(" + textBlock.getX2() + "," + textBlock.getY2() + ")");
|
||||
//
|
||||
//
|
||||
// contentStream.endText();
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +150,7 @@ public class PdfVisualisationService {
|
||||
|
||||
contentStream.setStrokingColor(Color.GREEN);
|
||||
for (TextBlock textBlock : cell.getTextBlocks()) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1168,7 +1168,7 @@ public class RedactionIntegrationTest {
|
||||
|
||||
System.out.println("classificationTest");
|
||||
|
||||
AnalyzeRequest request = prepareStorage("files/Metolachlor/S-Metolachlor_RAR_01_Volume_1_2018-09-06.pdf");
|
||||
AnalyzeRequest request = prepareStorage("files/new/RotateTestFile.pdf");
|
||||
|
||||
RedactionRequest redactionRequest = RedactionRequest.builder()
|
||||
.dossierId(request.getDossierId())
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user