@@ -156,6 +156,25 @@ private Task<MLInference> sendWSIRequest(String provider, String modelID, String
156
156
157
157
try {
158
158
DicomMetaData dicomMetaData = this .getDicomMetadata (uid );
159
+ DicomMetaData baseDicomMetaData = this .getDicomMetadata (baseSopInstanceUID );
160
+
161
+ WSISopDescriptor descriptor = new WSISopDescriptor ();
162
+ descriptor .extractData (dicomMetaData .getAttributes ());
163
+
164
+ WSISopDescriptor baseDescriptor = new WSISopDescriptor ();
165
+ baseDescriptor .extractData (baseDicomMetaData .getAttributes ());
166
+
167
+ double scale = (descriptor .getTotalPixelMatrixRows () * 1.0 ) / baseDescriptor .getTotalPixelMatrixRows ();
168
+
169
+ if (!uid .equals (baseSopInstanceUID )){
170
+ scaleAnnotation (annotation , scale );
171
+ }
172
+
173
+ // Verify dimensions of annotation, reject if too big. In the future, adopt a sliding window strategy to process large processing windows.
174
+ double area = annotation .getArea ();
175
+ if (area > 16000000 ) // This equates to a maximum of 4000x4000 which represents in RGB an image of 48MB
176
+ return null ;
177
+
159
178
BufferedImage bi = roiExtractor .extractROI (dicomMetaData , annotation );
160
179
predictionRequest .setRoi (bi );
161
180
Task <MLInference > task = PluginController .getInstance ().infer (provider , predictionRequest );
@@ -172,12 +191,6 @@ private Task<MLInference> sendWSIRequest(String provider, String modelID, String
172
191
173
192
// Coordinates need to be converted if we're working with WSI
174
193
if (!prediction .getAnnotations ().isEmpty ()){
175
- WSISopDescriptor descriptor = new WSISopDescriptor ();
176
- descriptor .extractData (dicomMetaData .getAttributes ());
177
- DicomMetaData base = this .getDicomMetadata (baseSopInstanceUID );
178
- WSISopDescriptor baseDescriptor = new WSISopDescriptor ();
179
- baseDescriptor .extractData (base .getAttributes ());
180
- double scale = (descriptor .getTotalPixelMatrixRows () * 1.0 ) / baseDescriptor .getTotalPixelMatrixRows ();
181
194
Point2D tl = annotation .getBoundingBox ().get (0 );
182
195
convertCoordinates (prediction , tl , scale );
183
196
}
@@ -308,9 +321,22 @@ private DicomMetaData getDicomMetadata(String sop) throws IOException{
308
321
private void convertCoordinates (MLInference prediction , Point2D tl , double scale ){
309
322
for (BulkAnnotation ann : prediction .getAnnotations ()){
310
323
for (Point2D p : ann .getPoints ()){
311
- p .setX ((p .getX () + tl .getX ())/ scale );
312
- p .setY ((p .getY () + tl .getY ())/ scale );
324
+ p .setX ((p .getX () + tl .getX ()) * scale );
325
+ p .setY ((p .getY () + tl .getY ()) * scale );
313
326
}
314
327
}
315
328
}
329
+
330
+ /**
331
+ * When working with WSI, it is convenient to have coordinates relative to the base of the pyramid.
332
+ * This method takes care of that.
333
+ * @param scale to transform coordinates
334
+ * @return the ml prediction with the converted coordinates.
335
+ */
336
+ private void scaleAnnotation (BulkAnnotation annotation , double scale ){
337
+ for (Point2D p : annotation .getPoints ()){
338
+ p .setX ((p .getX ()) * scale );
339
+ p .setY ((p .getY ()) * scale );
340
+ }
341
+ }
316
342
}
0 commit comments