@@ -1227,6 +1227,70 @@ def patch_predictions_as_annotations(
1227
1227
1228
1228
return annotations
1229
1229
1230
+ def mask_to_polygons (mask ):
1231
+ """Extract polygons from a binary mask using OpenCV."""
1232
+ contours , _ = cv2 .findContours (
1233
+ mask .astype (np .uint8 ), cv2 .RETR_EXTERNAL , cv2 .CHAIN_APPROX_SIMPLE
1234
+ )
1235
+ polygons = [
1236
+ Polygon (c .squeeze ()) for c in contours if len (c ) > 2
1237
+ ] # Avoid single-point contours
1238
+ return polygons
1239
+
1240
+
1241
+ def dict_to_store_semantic_segmentor_new (
1242
+ patch_output : dict | zarr .group ,
1243
+ scale_factor : tuple [float , float ],
1244
+ class_dict : dict | None = None ,
1245
+ save_path : Path | None = None ,
1246
+ ):
1247
+ """Converts output of TIAToolbox SemanticSegmentor engine to AnnotationStore.
1248
+
1249
+ Args:
1250
+ patch_output (dict | zarr.Group):
1251
+ A dictionary with "probabilities", "predictions", and "labels" keys.
1252
+ scale_factor (tuple[float, float]):
1253
+ The scale factor to use when loading the
1254
+ annotations. All coordinates will be multiplied by this factor to allow
1255
+ conversion of annotations saved at non-baseline resolution to baseline.
1256
+ Should be model_mpp/slide_mpp.
1257
+ class_dict (dict):
1258
+ Optional dictionary mapping class indices to class names.
1259
+ save_path (str or Path):
1260
+ Optional Output directory to save the Annotation
1261
+ Store results.
1262
+
1263
+ Returns:
1264
+ (SQLiteStore or Path):
1265
+ An SQLiteStore containing Annotations for each patch
1266
+ or Path to file storing SQLiteStore containing Annotations
1267
+ for each patch.
1268
+
1269
+ """
1270
+ preds = patch_output ["predictions" ]
1271
+ mask = preds [0 ]
1272
+
1273
+ polygons = mask_to_polygons (mask )
1274
+
1275
+ props = {"type" : "Mask" }
1276
+ store = SQLiteStore ()
1277
+
1278
+ for poly in polygons :
1279
+ annotation = Annotation (geometry = poly , properties = props )
1280
+ store .append (annotation )
1281
+
1282
+ if save_path :
1283
+ # ensure parent directory exists
1284
+ save_path .parent .absolute ().mkdir (parents = True , exist_ok = True )
1285
+ # ensure proper db extension
1286
+ save_path = save_path .parent .absolute () / (save_path .stem + ".db" )
1287
+ store .create_index ("id" , '"id"' )
1288
+ store .commit ()
1289
+ store .dump (save_path )
1290
+ store .close ()
1291
+ return save_path
1292
+
1293
+ return store
1230
1294
1231
1295
def dict_to_store_semantic_segmentor (
1232
1296
patch_output : dict | zarr .group ,
@@ -1305,13 +1369,15 @@ def dict_to_store_semantic_segmentor(
1305
1369
)
1306
1370
1307
1371
_ = store .append_many (annotations , [str (i ) for i in range (len (annotations ))])
1372
+ store .create_index ("id" , '"id"' )
1308
1373
1309
1374
# # if a save director is provided, then dump store into a file
1310
1375
if save_path :
1311
1376
# ensure parent directory exists
1312
1377
save_path .parent .absolute ().mkdir (parents = True , exist_ok = True )
1313
1378
# ensure proper db extension
1314
1379
save_path = save_path .parent .absolute () / (save_path .stem + ".db" )
1380
+ store .commit ()
1315
1381
store .dump (save_path )
1316
1382
return save_path
1317
1383
0 commit comments