Skip to content

Commit 9c8557f

Browse files
committed
Refactor the code to improve the performance
Get rid of UByteIndexer usages, improve FloatBufferWrapper usages, improve BufferedImageUtil DEVSIX-9803
1 parent ff5fa50 commit 9c8557f

8 files changed

Lines changed: 234 additions & 159 deletions

File tree

pdfocr-onnx-abstract/src/main/java/com/itextpdf/pdfocr/onnx/FloatBufferWrapper.java

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ This file is part of the iText (R) project.
2525
import java.nio.ByteOrder;
2626
import java.nio.FloatBuffer;
2727

28-
2928
/**
3029
* Wrapper class around {@link java.nio.FloatBuffer}.
3130
*/
@@ -45,23 +44,24 @@ public FloatBufferWrapper(FloatBuffer floatBuffer) {
4544
/**
4645
* Returns {@link FloatBuffer} that backs this buffer.
4746
*
48-
* <p> Modifications to this buffer's content will cause the returned
47+
* <p>
48+
* Modifications to this buffer's content will cause the returned
4949
* buffer's content to be modified, and vice versa.
5050
*
51-
* @return The array that backs this buffer
51+
* @return the array that backs this buffer
5252
*/
5353
public FloatBuffer getFloatBuffer() {
5454
return floatBuffer;
5555
}
5656

5757
/**
58-
* Returns the float array that backs this
59-
* buffer.
58+
* Returns the float array that backs this buffer.
6059
*
61-
* <p> Modifications to this buffer's content will cause the returned
60+
* <p>
61+
* Modifications to this buffer's content will cause the returned
6262
* array's content to be modified, and vice versa.
6363
*
64-
* @return The array that backs this buffer
64+
* @return the array that backs this buffer
6565
*/
6666
public float[] array() {
6767
return floatBuffer.array();
@@ -71,10 +71,11 @@ public float[] array() {
7171
* Returns the offset within this buffer's backing array of the first
7272
* element of the buffer.
7373
*
74-
* <p> If this buffer is backed by an array then buffer position
74+
* <p>
75+
* If this buffer is backed by an array then buffer position
7576
* corresponds to array index position.
7677
*
77-
* @return The offset within this buffer's array
78+
* @return the offset within this buffer's array
7879
* of the first element of the buffer
7980
*/
8081
public int arrayOffset() {
@@ -85,7 +86,7 @@ public int arrayOffset() {
8586
* Relative get method. Reads the float at this buffer's
8687
* current position, and then increments the position.
8788
*
88-
* @return The float at the buffer's current position
89+
* @return the float at the buffer's current position
8990
*/
9091
public float get() {
9192
return floatBuffer.get();
@@ -94,24 +95,24 @@ public float get() {
9495
/**
9596
* Absolute get method. Reads the float at the given index.
9697
*
97-
* @param index The index from which the float will be read
98+
* @param index the index from which the float will be read
9899
*
99-
* @return The float at the given index
100+
* @return the float at the given index
100101
*/
101102
public float get(int index) {
102103
return floatBuffer.get(index);
103104
}
104105

105-
106106
/**
107107
* Relative bulk <i>get</i> method.
108108
*
109-
* <p> This method transfers floats from this buffer into the given
109+
* <p>
110+
* This method transfers floats from this buffer into the given
110111
* destination array.
111112
*
112-
* @param dst The destination array
113+
* @param dst the destination array
113114
*
114-
* @return This buffer
115+
* @return this buffer
115116
*/
116117
public FloatBufferWrapper get(float[] dst) {
117118
floatBuffer.get(dst);
@@ -121,11 +122,12 @@ public FloatBufferWrapper get(float[] dst) {
121122
/**
122123
* Rewinds this buffer. The position is set to zero.
123124
*
124-
* <p> Invoke this method before a sequence of channel-write or get
125+
* <p>
126+
* Invoke this method before a sequence of channel-write or get
125127
* operations, assuming that the limit has already been set
126128
* appropriately.
127129
*
128-
* @return This buffer
130+
* @return this buffer
129131
*/
130132
public FloatBufferWrapper rewind() {
131133
floatBuffer.rewind();
@@ -135,34 +137,54 @@ public FloatBufferWrapper rewind() {
135137
/**
136138
* Relative put method.
137139
*
138-
* <p> Writes the given float into this buffer at the current
140+
* <p>
141+
* Writes the given float into this buffer at the current
139142
* position, and then increments the position.
140143
*
141-
* @param value The float to be written
144+
* @param value the float to be written
142145
*
143-
* @return This buffer
146+
* @return this buffer
144147
*/
145148
public FloatBufferWrapper put(float value) {
146149
floatBuffer.put(value);
147150
return this;
148151
}
149152

153+
/**
154+
* Relative bulk put method.
155+
*
156+
* <p>
157+
* This method transfers floats into this buffer from the given source array.
158+
*
159+
* @param src the array from which floats are to be read
160+
* @param offset the offset within the array of the first float to be read;
161+
* must be non-negative and no larger than {@code array.length}
162+
* @param length the number of floats to be read from the given array;
163+
* must be non-negative and no larger than {@code array.length - offset}
164+
*
165+
* @return this buffer
166+
*/
167+
public FloatBufferWrapper put(float[] src, int offset, int length) {
168+
floatBuffer.put(src, offset, length);
169+
return this;
170+
}
171+
150172
/**
151173
* Returns this buffer's limit.
152174
*
153-
* @return The limit of this buffer
175+
* @return the limit of this buffer
154176
*/
155177
public int limit() {
156178
return floatBuffer.limit();
157179
}
158180

159181
/**
160-
* Sets this buffer's limit. If the position is larger than the new limit
182+
* Sets this buffer's limit. If the position is larger than the new limit
161183
* then it is set to the new limit.
162184
*
163-
* @param newLimit The new limit value; must be non-negative and no larger than this buffer's capacity
185+
* @param newLimit the new limit value; must be non-negative and no larger than this buffer's capacity
164186
*
165-
* @return This buffer
187+
* @return this buffer
166188
*/
167189
public FloatBufferWrapper limit(int newLimit) {
168190
floatBuffer.limit(newLimit);
@@ -172,24 +194,25 @@ public FloatBufferWrapper limit(int newLimit) {
172194
/**
173195
* Creates a new float buffer that shares this buffer's content.
174196
*
175-
* <p> The content of the new buffer will be that of this buffer. Changes
197+
* <p>
198+
* The content of the new buffer will be that of this buffer. Changes
176199
* to this buffer's content will be visible in the new buffer, and vice
177200
* versa; the two buffers' position and limit will be
178201
* independent.
179202
*
180-
* <p> The new buffer's capacity, limit, position and byte order will be identical to those of this buffer.
203+
* <p>
204+
* The new buffer's capacity, limit, position and byte order will be identical to those of this buffer.
181205
*
182-
* @return The new float buffer
206+
* @return the new float buffer
183207
*/
184208
public FloatBufferWrapper duplicate() {
185209
return new FloatBufferWrapper(floatBuffer.duplicate());
186210
}
187211

188212
/**
189-
* Returns the number of elements between the current position and the
190-
* limit.
213+
* Returns the number of elements between the current position and the limit.
191214
*
192-
* @return The number of elements remaining in this buffer
215+
* @return the number of elements remaining in this buffer
193216
*/
194217
public int remaining() {
195218
return floatBuffer.remaining();
@@ -198,9 +221,9 @@ public int remaining() {
198221
/**
199222
* Sets this buffer's position.
200223
*
201-
* @param newPosition The new position value; must be non-negative and no larger than the current limit
224+
* @param newPosition the new position value; must be non-negative and no larger than the current limit
202225
*
203-
* @return This buffer
226+
* @return this buffer
204227
*/
205228
public FloatBufferWrapper position(int newPosition) {
206229
floatBuffer.position(newPosition);
@@ -212,15 +235,17 @@ public FloatBufferWrapper position(int newPosition) {
212235
* Creates a new float buffer whose content is a shared subsequence of
213236
* this buffer's content.
214237
*
215-
* <p> The content of the new buffer will start at this buffer's current
238+
* <p>
239+
* The content of the new buffer will start at this buffer's current
216240
* position. Changes to this buffer's content will be visible in the new
217241
* buffer, and vice versa; the two buffers' position and limit values will be independent.
218242
*
219-
* <p> The new buffer's position will be zero, its capacity and its limit
243+
* <p>
244+
* The new buffer's position will be zero, its capacity and its limit
220245
* will be the number of floats remaining in this buffer and its byte order
221246
* will be identical to that of this buffer.
222247
*
223-
* @return The new float buffer
248+
* @return the new float buffer
224249
*/
225250
public FloatBufferWrapper slice() {
226251
return new FloatBufferWrapper(floatBuffer.slice());
@@ -229,16 +254,17 @@ public FloatBufferWrapper slice() {
229254
/**
230255
* Wraps a float array into a buffer.
231256
*
232-
* <p> The new buffer will be backed by the given float array;
257+
* <p>
258+
* The new buffer will be backed by the given float array;
233259
* that is, modifications to the buffer will cause the array to be modified
234260
* and vice versa. The new buffer's capacity and limit will be
235261
* {@code array.length}, its position will be zero and its byte order
236262
* will be the {@link ByteOrder#nativeOrder native order} of the underlying hardware.
237263
* Its {@link #array backing array} will be the given array, and its {@link #arrayOffset array offset} will be zero.
238264
*
239-
* @param array The array that will back this buffer
265+
* @param array the array that will back this buffer
240266
*
241-
* @return The new float buffer
267+
* @return the new float buffer
242268
*/
243269
public static FloatBufferWrapper wrap(float[] array) {
244270
return new FloatBufferWrapper(FloatBuffer.wrap(array));
@@ -247,17 +273,18 @@ public static FloatBufferWrapper wrap(float[] array) {
247273
/**
248274
* Allocates a new float buffer.
249275
*
250-
* <p> The new buffer's position will be zero, its limit will be its
276+
* <p>
277+
* The new buffer's position will be zero, its limit will be its
251278
* capacity, its mark will be undefined, each of its elements will be
252279
* initialized to zero, and its byte order will be
253280
* the {@link ByteOrder#nativeOrder native order} of the underlying
254281
* hardware.
255282
* It will have a {@link #array backing array}, and its
256283
* {@link #arrayOffset array offset} will be zero.
257284
*
258-
* @param capacity The new buffer's capacity, in floats
285+
* @param capacity the new buffer's capacity, in floats
259286
*
260-
* @return The new float buffer
287+
* @return the new float buffer
261288
*/
262289
public static FloatBufferWrapper allocate(int capacity) {
263290
return new FloatBufferWrapper(FloatBuffer.allocate(capacity));

pdfocr-onnx-abstract/src/main/java/com/itextpdf/pdfocr/onnx/detection/BasicDetectionPostProcessor.java

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@
88

99
import com.itextpdf.kernel.geom.Point;
1010
import com.itextpdf.pdfocr.onnx.FloatBufferMdArray;
11+
import com.itextpdf.pdfocr.onnx.FloatBufferWrapper;
1112
import com.itextpdf.pdfocr.onnx.detection.score.IScoreCalculator;
1213
import com.itextpdf.pdfocr.onnx.detection.score.MeanScoreCalculator;
1314
import com.itextpdf.pdfocr.onnx.util.MathUtil;
1415
import com.itextpdf.pdfocr.onnx.util.OpenCvUtil;
15-
16-
import java.awt.image.BufferedImage;
17-
import java.util.ArrayList;
18-
import java.util.List;
19-
import org.bytedeco.javacpp.indexer.UByteIndexer;
16+
import org.bytedeco.javacpp.BytePointer;
2017
import org.bytedeco.opencv.global.opencv_imgproc;
2118
import org.bytedeco.opencv.opencv_core.Mat;
2219
import org.bytedeco.opencv.opencv_core.MatVector;
@@ -27,6 +24,10 @@
2724
import org.bytedeco.opencv.opencv_core.Size2f;
2825
import org.opencv.core.CvType;
2926

27+
import java.awt.image.BufferedImage;
28+
import java.util.ArrayList;
29+
import java.util.List;
30+
3031
/**
3132
* Implementation of a text detection predictor post-processor, which is used
3233
* as a basis for creating post-processors for handling OnnxTR, EasyOCR and
@@ -68,9 +69,9 @@ public abstract class BasicDetectionPostProcessor implements IDetectionPostProce
6869
* Creates a new post-processor.
6970
*
7071
* @param binarizationThreshold threshold value used, when binarizing a monochromatic image. If pixel value is
71-
* greater or equal to the threshold, it is mapped to 1, otherwise it is mapped to 0
72+
* greater or equal to the threshold, it is mapped to 1, otherwise it is mapped to 0
7273
* @param scoreThreshold score threshold for a detected box. If score is lower than this value,
73-
* the box gets discarded
74+
* the box gets discarded
7475
* @param maxCandidates maximum amount of text box contours, that will be handled in the post processor
7576
*/
7677
protected BasicDetectionPostProcessor(
@@ -272,18 +273,27 @@ private float calcPredictionScore(FloatBufferMdArray preds, Mat contour, Rect co
272273
final IScoreCalculator scoreCalculator = createScoreCalculator();
273274
final int contourX = contourBox.x();
274275
final int contourY = contourBox.y();
275-
try (final Mat mask = buildTextContourPredictionMask(contour, contourBox);
276-
final UByteIndexer maskIndexer = mask.createIndexer()) {
276+
try (final Mat mask = buildTextContourPredictionMask(contour, contourBox)) {
277277
// Making sure we use correct boundaries for preds
278278
final int yEnd = Math.min(mask.rows(), preds.getDimension(0) - contourY);
279279
final int xEnd = Math.min(mask.cols(), preds.getDimension(1) - contourX);
280+
281+
final BytePointer maskPtr = mask.data();
282+
final int maskStep = (int) mask.step();
283+
284+
FloatBufferWrapper predsData = preds.getData();
285+
final int predsWidth = preds.getDimension(1);
286+
final int predsOffsetBase = contourY * predsWidth + contourX;
287+
280288
for (int y = 0; y < yEnd; ++y) {
281-
final FloatBufferMdArray predictionsRow = preds.getSubArray(y + contourY);
289+
final int maskRowStart = y * maskStep;
290+
final int predRowStart = predsOffsetBase + y * predsWidth;
291+
282292
for (int x = 0; x < xEnd; ++x) {
283-
if (maskIndexer.get(y, x) == 0) {
293+
if (maskPtr.get(maskRowStart + x) == 0) {
284294
continue;
285295
}
286-
final float sample = mapPredToSample(predictionsRow.getScalar(x + contourX));
296+
final float sample = mapPredToSample(predsData.get(predRowStart + x));
287297
scoreCalculator.observe(sample);
288298
}
289299
}

pdfocr-onnx-abstract/src/main/java/com/itextpdf/pdfocr/onnx/detection/EasyOcrDetectionPostProcessor.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public class EasyOcrDetectionPostProcessor extends BasicDetectionPostProcessor {
4343
* Creates a new post-processor.
4444
*
4545
* @param scoreThreshold score threshold for a detected box. If score is lower than this value,
46-
* the box gets discarded
46+
* the box gets discarded
4747
*/
4848
public EasyOcrDetectionPostProcessor(float scoreThreshold) {
4949
super(1.0F, scoreThreshold, Integer.MAX_VALUE);
@@ -89,17 +89,21 @@ protected FloatBufferMdArray getMaskSourceArray(FloatBufferMdArray output) {
8989
* link data. So we are creating a new buffer, where they are
9090
* combined.
9191
*/
92-
final FloatBufferWrapper textScoreBuffer = output.getSubArray(0).getData();
93-
final FloatBufferWrapper linkScoreBuffer = output.getSubArray(1).getData();
9492
final int height = output.getDimension(1);
9593
final int width = output.getDimension(2);
9694
final int size = height * width;
95+
final float[] textScoreBuffer = new float[size];
96+
output.getSubArray(0).getData().get(textScoreBuffer);
97+
final float[] linkScoreBuffer = new float[size];
98+
output.getSubArray(1).getData().get(linkScoreBuffer);
9799
final FloatBufferWrapper maskSourceBuffer = FloatBufferWrapper.allocate(height * width);
100+
float[] mask = new float[size];
98101
for (int i = 0; i < size; ++i) {
99-
final float text = textScoreBuffer.get() >= TEXT_BINARIZATION_THRESHOLD ? 1.0F : 0.0F;
100-
final float link = linkScoreBuffer.get() >= LINK_BINARIZATION_THRESHOLD ? 1.0F : 0.0F;
101-
maskSourceBuffer.put(text + link);
102+
float text = textScoreBuffer[i] >= TEXT_BINARIZATION_THRESHOLD ? 1.0F : 0.0F;
103+
float link = linkScoreBuffer[i] >= LINK_BINARIZATION_THRESHOLD ? 1.0F : 0.0F;
104+
mask[i] = text + link;
102105
}
106+
maskSourceBuffer.put(mask, 0, mask.length);
103107
maskSourceBuffer.rewind();
104108
return new FloatBufferMdArray(maskSourceBuffer, new long[]{height, width});
105109
}

0 commit comments

Comments
 (0)