@@ -1227,6 +1227,70 @@ def patch_predictions_as_annotations(
12271227
12281228 return annotations
12291229
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
12301294
12311295def dict_to_store_semantic_segmentor (
12321296 patch_output : dict | zarr .group ,
@@ -1305,13 +1369,15 @@ def dict_to_store_semantic_segmentor(
13051369 )
13061370
13071371 _ = store .append_many (annotations , [str (i ) for i in range (len (annotations ))])
1372+ store .create_index ("id" , '"id"' )
13081373
13091374 # # if a save director is provided, then dump store into a file
13101375 if save_path :
13111376 # ensure parent directory exists
13121377 save_path .parent .absolute ().mkdir (parents = True , exist_ok = True )
13131378 # ensure proper db extension
13141379 save_path = save_path .parent .absolute () / (save_path .stem + ".db" )
1380+ store .commit ()
13151381 store .dump (save_path )
13161382 return save_path
13171383
0 commit comments