RSS-83: More improvements for section detection
This commit is contained in:
parent
65daab4372
commit
d7d2bfff6b
@ -1,5 +1,6 @@
|
||||
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.server.classification.model.Document;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Orientation;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.Page;
|
||||
@ -12,6 +13,8 @@ import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.regex.Matcher;
|
||||
@ -36,12 +39,49 @@ public class ClassificationService {
|
||||
|
||||
for (Page page : document.getPages()) {
|
||||
Rectangle btf = page.isLandscape() ? landscapeBodyTextFrame : bodyTextFrame;
|
||||
|
||||
// if (page.getRotation() == 180 || page.getRotation() == 270){
|
||||
// var nBtf = getRectangle(btf.x, btf.y, btf.width, btf.height, page.getRotation(),((TextBlock) page.getTextBlocks().get(0)).getSequences().get(0).getPageWidth(),((TextBlock) page.getTextBlocks().get(0)).getSequences().get(0).getPageHeight());
|
||||
// btf = new Rectangle(nBtf.getTopLeft().getX(), nBtf.getTopLeft().getY(), nBtf.getWidth(), nBtf.getHeight());
|
||||
// }
|
||||
|
||||
page.setBodyTextFrame(btf);
|
||||
classifyPage(btf, page, document, headlineFontSizes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public com.iqser.red.service.redaction.v1.model.Rectangle getRectangle(float x, float y, float width, float height, int rotation, float pageWidth, float pageHeight) {
|
||||
|
||||
|
||||
Point2D bottomLeft = new Point2D.Double(x, pageHeight - y);
|
||||
Point2D topRight = new Point2D.Double(x + width,pageHeight - y - height);
|
||||
|
||||
AffineTransform transform = new AffineTransform();
|
||||
if (rotation == 0 || rotation == 180) {
|
||||
transform.rotate(Math.toRadians(rotation), pageWidth / 2f, pageHeight / 2f);
|
||||
transform.translate(0f, pageHeight);
|
||||
transform.scale(1., -1.);
|
||||
} else if (rotation == 90) {
|
||||
transform.rotate(Math.toRadians(rotation), pageWidth / 2f, pageWidth / 2f);
|
||||
transform.translate(0f, pageWidth);
|
||||
transform.scale(1., -1.);
|
||||
} else {
|
||||
transform.rotate(Math.toRadians(rotation), pageHeight / 2f, pageHeight / 2f);
|
||||
transform.translate(0f, pageWidth);
|
||||
transform.scale(1., -1.);
|
||||
}
|
||||
|
||||
bottomLeft = transform.transform(bottomLeft, null);
|
||||
topRight = transform.transform(topRight, null);
|
||||
|
||||
return new com.iqser.red.service.redaction.v1.model.Rectangle( //
|
||||
new Point((float) bottomLeft.getX(), (float) bottomLeft.getY()), (float) (topRight.getX() - bottomLeft.getX()), (float) (topRight.getY() - bottomLeft.getY()), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void classifyPage(Rectangle bodyTextFrame, Page page, Document document, List<Float> headlineFontSizes) {
|
||||
|
||||
for (AbstractTextContainer textBlock : page.getTextBlocks()) {
|
||||
@ -92,7 +132,7 @@ public class ClassificationService {
|
||||
document.setHeadlines(true);
|
||||
}
|
||||
|
||||
else if (PositionUtils.isOverBodyTextFrame(bodyTextFrame, textBlock, page.isRotated()) && (document.getFontSizeCounter()
|
||||
else if (PositionUtils.isOverBodyTextFrame(bodyTextFrame, textBlock) && (document.getFontSizeCounter()
|
||||
.getMostPopular() == null || textBlock.getHighestFontSize() <= document.getFontSizeCounter()
|
||||
.getMostPopular())) {
|
||||
textBlock.setClassification("Header");
|
||||
|
||||
@ -31,16 +31,16 @@ public class PositionUtils {
|
||||
}
|
||||
|
||||
|
||||
public boolean isOverBodyTextFrame(Rectangle btf, TextBlock textBlock, boolean rotated) {
|
||||
public boolean isOverBodyTextFrame(Rectangle btf, TextBlock textBlock) {
|
||||
|
||||
if (btf == null || textBlock == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rotated && textBlock.getMinX() < btf.getX()) {
|
||||
if ((textBlock.getRotation() == 0 || textBlock.getRotation() == 180) && textBlock.getMinX() < btf.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 ((textBlock.getRotation() == 90 || textBlock.getRotation() == 270) && textBlock.getMinY() > btf.getY() + btf.getHeight()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -89,6 +89,9 @@ public class PositionUtils {
|
||||
|
||||
|
||||
public Float getApproxLineCount(TextBlock textBlock) {
|
||||
|
||||
// float height = textBlock.getRotation() == 0 || textBlock.getRotation() == 180 ? textBlock.getHeight() : textBlock.getWidth();
|
||||
|
||||
return textBlock.getHeight() / textBlock.getMostPopularWordHeight();
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,9 +93,11 @@ public class PdfSegmentationService {
|
||||
stripper.getText(pdDocument);
|
||||
|
||||
PDRectangle pdr = pdPage.getMediaBox();
|
||||
boolean isLandscape = pdr.getWidth() > pdr.getHeight();
|
||||
|
||||
int rotation = pdPage.getRotation();
|
||||
boolean isLandscape = pdr.getWidth() > pdr.getHeight() && (rotation == 0 || rotation == 180) ||
|
||||
pdr.getHeight() > pdr.getWidth() && (rotation == 90 || rotation == 270);
|
||||
|
||||
|
||||
|
||||
System.out.println("PageNr: " + pageNumber + " rotation: "+rotation);
|
||||
|
||||
@ -125,7 +127,7 @@ public class PdfSegmentationService {
|
||||
page.setCropBoxArea(cropboxArea);
|
||||
|
||||
page.setRotation(rotation);
|
||||
page.setLandscape(isLandscape || isRotated);
|
||||
page.setLandscape(isLandscape);
|
||||
page.setPageNumber(pageNumber);
|
||||
|
||||
|
||||
|
||||
@ -1,9 +1,13 @@
|
||||
package com.iqser.red.service.redaction.v1.server.visualization.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.Paragraph;
|
||||
import com.iqser.red.service.redaction.v1.server.classification.model.TextBlock;
|
||||
import com.iqser.red.service.redaction.v1.server.parsing.model.RedTextPosition;
|
||||
import com.iqser.red.service.redaction.v1.server.parsing.model.TextDirection;
|
||||
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;
|
||||
@ -16,6 +20,8 @@ import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@ -85,7 +91,11 @@ 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 rect = getRectangle((float) analyzedPage.getBodyTextFrame().getX(),(float) analyzedPage.getBodyTextFrame().getY(),(float) analyzedPage.getBodyTextFrame().getWidth(), (float) analyzedPage.getBodyTextFrame().getHeight(), pdPage.getRotation(), pdPage.getCropBox().getWidth(), pdPage.getCropBox().getHeight());
|
||||
|
||||
contentStream.addRect(rect.getTopLeft().getX(), rect.getTopLeft().getY(), rect.getWidth(), rect.getHeight());
|
||||
|
||||
contentStream.stroke();
|
||||
|
||||
contentStream.close();
|
||||
@ -97,7 +107,9 @@ public class PdfVisualisationService {
|
||||
|
||||
contentStream.setStrokingColor(Color.RED);
|
||||
|
||||
contentStream.addRect(textBlock.getMinX(), textBlock.getMinY(), textBlock.getWidth(), textBlock.getHeight());
|
||||
var rect = getRectangle(textBlock.getMinX(), textBlock.getMinY(), textBlock.getWidth(), textBlock.getHeight(), textBlock.getRotation(), textBlock.getSequences().get(0).getPageWidth(), textBlock.getSequences().get(0).getPageHeight());
|
||||
|
||||
contentStream.addRect(rect.getTopLeft().getX(), rect.getTopLeft().getY(), rect.getWidth(), rect.getHeight());
|
||||
contentStream.stroke();
|
||||
|
||||
if (textBlock.getClassification() != null) {
|
||||
@ -106,7 +118,7 @@ public class PdfVisualisationService {
|
||||
contentStream.setNonStrokingColor(Color.BLUE);
|
||||
contentStream.setFont(PDType1Font.TIMES_ROMAN, 6f);
|
||||
|
||||
contentStream.newLineAtOffset(textBlock.getMinX(), textBlock.getMaxY());
|
||||
contentStream.newLineAtOffset(rect.getTopLeft().getX(), rect.getTopLeft().getY());
|
||||
|
||||
contentStream.showText(textBlock.getClassification() /*" textBlock.getOrientation() + "--> "*/ + number);
|
||||
|
||||
@ -115,6 +127,39 @@ public class PdfVisualisationService {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Rectangle getRectangle(float x, float y, float width, float height, int rotation, float pageWidth, float pageHeight) {
|
||||
|
||||
|
||||
Point2D bottomLeft = new Point2D.Double(x, pageHeight - y);
|
||||
Point2D topRight = new Point2D.Double(x + width,pageHeight - y - height);
|
||||
|
||||
AffineTransform transform = new AffineTransform();
|
||||
if (rotation == 0 || rotation == 180) {
|
||||
transform.rotate(Math.toRadians(rotation), pageWidth / 2f, pageHeight / 2f);
|
||||
transform.translate(0f, pageHeight);
|
||||
transform.scale(1., -1.);
|
||||
} else if (rotation == 90) {
|
||||
transform.rotate(Math.toRadians(rotation), pageWidth / 2f, pageWidth / 2f);
|
||||
transform.translate(0f, pageWidth);
|
||||
transform.scale(1., -1.);
|
||||
} else {
|
||||
transform.rotate(Math.toRadians(rotation), pageHeight / 2f, pageHeight / 2f);
|
||||
transform.translate(0f, pageWidth);
|
||||
transform.scale(1., -1.);
|
||||
}
|
||||
|
||||
bottomLeft = transform.transform(bottomLeft, null);
|
||||
topRight = transform.transform(topRight, null);
|
||||
|
||||
return new Rectangle( //
|
||||
new Point((float) bottomLeft.getX(), (float) bottomLeft.getY()), (float) (topRight.getX() - bottomLeft.getX()), (float) (topRight.getY() - bottomLeft.getY()), 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private void visualizeTable(Table table, PDPageContentStream contentStream) throws IOException {
|
||||
for (List<Cell> row : table.getRows()) {
|
||||
for (Cell cell : row) {
|
||||
|
||||
@ -336,7 +336,7 @@ public class RedactionIntegrationTest {
|
||||
|
||||
System.out.println("Detailed quantitative and qualitative information on the composition of the plant ".length());
|
||||
|
||||
ClassPathResource pdfFileResource = new ClassPathResource("files/Trinexapac/91 Trinexapac-ethyl_RAR_01_Volume_1_2018-02-23.pdf");
|
||||
ClassPathResource pdfFileResource = new ClassPathResource("files/Metolachlor/S-Metolachlor_RAR_02_Volume_2_2018-09-06.pdf");
|
||||
AnalyzeRequest request = prepareStorage(pdfFileResource.getInputStream());
|
||||
|
||||
analyzeService.analyzeDocumentStructure(new StructureAnalyzeRequest(request.getDossierId(), request.getFileId()));
|
||||
@ -1096,7 +1096,7 @@ public class RedactionIntegrationTest {
|
||||
public void classificationTest() throws IOException {
|
||||
|
||||
System.out.println("classificationTest");
|
||||
ClassPathResource pdfFileResource = new ClassPathResource("files/Trinexapac/91 Trinexapac-ethyl_RAR_01_Volume_1_2018-02-23.pdf");
|
||||
ClassPathResource pdfFileResource = new ClassPathResource("files/RSS/02 - A22833B - Acute Oral (Up and Down) - Final Report.pdf");
|
||||
|
||||
AnalyzeRequest request = prepareStorage(pdfFileResource.getInputStream());
|
||||
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user