RED-7082: getBBox() Performance Improvement
This commit is contained in:
parent
ce66d9104d
commit
4d00b01514
@ -465,7 +465,7 @@ public interface SemanticNode {
|
||||
private Map<Page, Rectangle2D> getBBoxFromLeafTextBlock(Map<Page, Rectangle2D> bBoxPerPage) {
|
||||
|
||||
Map<Page, List<AtomicTextBlock>> atomicTextBlockPerPage = getTextBlock().getAtomicTextBlocks().stream().collect(Collectors.groupingBy(AtomicTextBlock::getPage));
|
||||
atomicTextBlockPerPage.forEach((page, atbs) -> bBoxPerPage.put(page, RectangleTransformations.bBoxUnionAtomicTextBlock(atbs)));
|
||||
atomicTextBlockPerPage.forEach((page, atbs) -> bBoxPerPage.put(page, RectangleTransformations.atomicTextBlockBBox(atbs)));
|
||||
return bBoxPerPage;
|
||||
}
|
||||
|
||||
|
||||
@ -191,7 +191,7 @@ public class AtomicTextBlock implements TextBlock {
|
||||
List<Rectangle2D> rectanglesPerLine = stringBoundary.split(getAllLineBreaksInBoundary(stringBoundary))
|
||||
.stream()
|
||||
.map(this::getPositions)
|
||||
.map(RectangleTransformations::rectangleUnionWithGaps)
|
||||
.map(RectangleTransformations::rectangleBBoxWithGaps)
|
||||
.flatMap(Collection::stream)
|
||||
.toList();
|
||||
Map<Page, List<Rectangle2D>> rectanglePerLinePerPage = new HashMap<>();
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
package com.iqser.red.service.redaction.v1.server.layoutparsing.document.utils;
|
||||
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RectangularShape;
|
||||
import java.util.Collections;
|
||||
@ -19,11 +18,14 @@ import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlo
|
||||
import com.iqser.red.service.persistence.service.v1.api.shared.model.redactionlog.Rectangle;
|
||||
import com.iqser.red.service.redaction.v1.server.layoutparsing.document.graph.textblock.AtomicTextBlock;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
public class RectangleTransformations {
|
||||
|
||||
public static PDRectangle toPDRectangleUnion(List<Rectangle> rectangles) {
|
||||
public static PDRectangle toPDRectangleBBox(List<Rectangle> rectangles) {
|
||||
|
||||
Rectangle2D rectangle2D = RectangleTransformations.bBoxUnionRectangle(rectangles);
|
||||
Rectangle2D rectangle2D = RectangleTransformations.rectangleBBox(rectangles);
|
||||
|
||||
PDRectangle annotationPosition = new PDRectangle();
|
||||
annotationPosition.setLowerLeftX((float) rectangle2D.getMinX());
|
||||
@ -34,15 +36,15 @@ public class RectangleTransformations {
|
||||
}
|
||||
|
||||
|
||||
public static Rectangle2D bBoxUnionAtomicTextBlock(List<AtomicTextBlock> atomicTextBlocks) {
|
||||
public static Rectangle2D atomicTextBlockBBox(List<AtomicTextBlock> atomicTextBlocks) {
|
||||
|
||||
return atomicTextBlocks.stream().flatMap(atomicTextBlock -> atomicTextBlock.getPositions().stream()).collect(new Rectangle2DUnion());
|
||||
return atomicTextBlocks.stream().flatMap(atomicTextBlock -> atomicTextBlock.getPositions().stream()).collect(new Rectangle2DBBoxCollector());
|
||||
}
|
||||
|
||||
|
||||
public static Rectangle2D bBoxUnionRectangle(List<Rectangle> rectangles) {
|
||||
public static Rectangle2D rectangleBBox(List<Rectangle> rectangles) {
|
||||
|
||||
return rectangles.stream().map(RectangleTransformations::toRectangle2D).collect(new Rectangle2DUnion());
|
||||
return rectangles.stream().map(RectangleTransformations::toRectangle2D).collect(new Rectangle2DBBoxCollector());
|
||||
}
|
||||
|
||||
|
||||
@ -64,9 +66,9 @@ public class RectangleTransformations {
|
||||
}
|
||||
|
||||
|
||||
public static Rectangle2D rectangleUnion(List<Rectangle2D> rectangle2DList) {
|
||||
public static Rectangle2D rectangle2DBBox(List<Rectangle2D> rectangle2DList) {
|
||||
|
||||
return rectangle2DList.stream().collect(new Rectangle2DUnion());
|
||||
return rectangle2DList.stream().collect(new Rectangle2DBBoxCollector());
|
||||
}
|
||||
|
||||
|
||||
@ -76,7 +78,7 @@ public class RectangleTransformations {
|
||||
* @param rectangle2DList A list of rectangles to combine
|
||||
* @return A list of rectangles which are combined if they are closer than the split threshold
|
||||
*/
|
||||
public static List<Rectangle2D> rectangleUnionWithGaps(List<Rectangle2D> rectangle2DList) {
|
||||
public static List<Rectangle2D> rectangleBBoxWithGaps(List<Rectangle2D> rectangle2DList) {
|
||||
|
||||
if (rectangle2DList.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
@ -98,47 +100,85 @@ public class RectangleTransformations {
|
||||
previousRectangle = currentRectangle;
|
||||
}
|
||||
}
|
||||
return rectangleListsWithGaps.stream().map(RectangleTransformations::rectangleUnion).toList();
|
||||
return rectangleListsWithGaps.stream().map(RectangleTransformations::rectangle2DBBox).toList();
|
||||
}
|
||||
|
||||
|
||||
private static class Rectangle2DUnion implements Collector<Rectangle2D, Area, Rectangle2D> {
|
||||
private static class Rectangle2DBBoxCollector implements Collector<Rectangle2D, Rectangle2DBBoxCollector.BBox, Rectangle2D> {
|
||||
|
||||
@Override
|
||||
public Supplier<Area> supplier() {
|
||||
public Supplier<BBox> supplier() {
|
||||
|
||||
return Area::new;
|
||||
return BBox::new;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BiConsumer<Area, Rectangle2D> accumulator() {
|
||||
public BiConsumer<BBox, Rectangle2D> accumulator() {
|
||||
|
||||
return (area, rectangle2D) -> area.add(new Area(rectangle2D));
|
||||
return (bb, rect) -> bb.addRectangle(rect.getMinX(), rect.getMinY(), rect.getMaxX(), rect.getMaxY());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BinaryOperator<Area> combiner() {
|
||||
public BinaryOperator<BBox> combiner() {
|
||||
|
||||
return (area1, area2) -> {
|
||||
area1.add(area2);
|
||||
return area1;
|
||||
};
|
||||
return (b1, b2) -> new BBox(Math.min(b1.lowerLeftX, b2.lowerLeftX),
|
||||
Math.min(b1.lowerLeftY, b2.lowerLeftY),
|
||||
Math.max(b1.upperRightX, b2.upperRightX),
|
||||
Math.max(b1.upperRightY, b2.upperRightY));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Function<Area, Rectangle2D> finisher() {
|
||||
public Function<BBox, Rectangle2D> finisher() {
|
||||
|
||||
return Area::getBounds2D;
|
||||
return bb -> new Rectangle2D.Double(bb.lowerLeftX, bb.lowerLeftY, bb.upperRightX - bb.lowerLeftX, bb.upperRightY - bb.lowerLeftY);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<Characteristics> characteristics() {
|
||||
|
||||
return Set.of(Characteristics.CONCURRENT, Characteristics.UNORDERED);
|
||||
return Set.of(Characteristics.UNORDERED);
|
||||
}
|
||||
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
private static class BBox {
|
||||
|
||||
Double lowerLeftX;
|
||||
Double lowerLeftY;
|
||||
Double upperRightX;
|
||||
Double upperRightY;
|
||||
|
||||
|
||||
public void addRectangle(double lowerLeftX, double lowerLeftY, double upperRightX, double upperRightY) {
|
||||
|
||||
if (this.lowerLeftX == null) {
|
||||
this.lowerLeftX = lowerLeftX;
|
||||
} else if (this.lowerLeftX > lowerLeftX) {
|
||||
this.lowerLeftX = lowerLeftX;
|
||||
}
|
||||
if (this.lowerLeftY == null) {
|
||||
this.lowerLeftY = lowerLeftY;
|
||||
} else if (this.lowerLeftY > lowerLeftY) {
|
||||
this.lowerLeftY = lowerLeftY;
|
||||
}
|
||||
if (this.upperRightX == null) {
|
||||
this.upperRightX = upperRightX;
|
||||
} else if (this.upperRightX < upperRightX) {
|
||||
this.upperRightX = upperRightX;
|
||||
}
|
||||
if (this.upperRightY == null) {
|
||||
this.upperRightY = upperRightY;
|
||||
} else if (this.upperRightY < upperRightY) {
|
||||
this.upperRightY = upperRightY;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package com.iqser.red.service.redaction.v1.server.annotate;
|
||||
|
||||
import static com.iqser.red.service.redaction.v1.server.layoutparsing.document.utils.RectangleTransformations.toPDRectangleUnion;
|
||||
import static com.iqser.red.service.redaction.v1.server.layoutparsing.document.utils.RectangleTransformations.toPDRectangleBBox;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
@ -136,7 +136,7 @@ public class AnnotationService {
|
||||
|
||||
PDAnnotationTextMarkup annotation = new PDAnnotationTextMarkup(PDAnnotationTextMarkup.SUB_TYPE_HIGHLIGHT);
|
||||
annotation.constructAppearances();
|
||||
PDRectangle pdRectangle = toPDRectangleUnion(rectangles);
|
||||
PDRectangle pdRectangle = toPDRectangleBBox(rectangles);
|
||||
annotation.setRectangle(pdRectangle);
|
||||
annotation.setQuadPoints(Floats.toArray(toQuadPoints(rectangles)));
|
||||
if (!redactionLogEntry.isHint()) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user