77import numpy as np
88from collections import defaultdict
99
10- from ..annotation_types import Label , ObjectAnnotation , ClassificationAnnotation , Mask , Geometry
10+ from ..annotation_types import Label , ObjectAnnotation , ClassificationAnnotation , Mask , Geometry , Point , Line
1111from ..annotation_types .annotation import BaseAnnotation
1212from labelbox .data import annotation_types
1313
@@ -114,8 +114,10 @@ def subclassification_miou(
114114 return None if not len (classification_iou ) else np .mean (classification_iou )
115115
116116
117- def vector_miou (predictions : List [Geometry ], labels : List [Geometry ],
118- include_subclasses ) -> float :
117+ def vector_miou (predictions : List [ObjectAnnotation ],
118+ labels : List [ObjectAnnotation ],
119+ include_subclasses ,
120+ buffer = 70. ) -> float :
119121 """
120122 Computes an iou score for vector tools.
121123
@@ -127,15 +129,16 @@ def vector_miou(predictions: List[Geometry], labels: List[Geometry],
127129 miou score for the feature schema
128130
129131 """
130- pairs = _get_vector_pairs (predictions , labels )
132+ pairs = _get_vector_pairs (predictions , labels , buffer = buffer )
131133 pairs .sort (key = lambda triplet : triplet [2 ], reverse = True )
132134 solution_agreements = []
133135 solution_features = set ()
134136 all_features = set ()
135137 for pred , label , agreement in pairs :
136- all_features .update ({pred .uuid , label .uuid })
137- if pred .uuid not in solution_features and label .uuid not in solution_features :
138- solution_features .update ({pred .uuid , label .uuid })
138+ all_features .update ({id (pred ), id (label )})
139+ if id (pred ) not in solution_features and id (
140+ label ) not in solution_features :
141+ solution_features .update ({id (pred ), id (label )})
139142 if include_subclasses :
140143 classification_iou = subclassification_miou (
141144 pred .classifications , label .classifications )
@@ -181,14 +184,11 @@ def feature_miou(predictions: List[Union[ObjectAnnotation,
181184 return vector_miou (predictions ,
182185 labels ,
183186 include_subclasses = include_subclasses )
184- elif isinstance (predictions [0 ]. value , ClassificationAnnotation ):
187+ elif isinstance (predictions [0 ], ClassificationAnnotation ):
185188 return classification_miou (predictions , labels )
186189 else :
187190 raise ValueError (
188- f"Unexpected annotation found. Found { type (predictions [0 ])} " )
189-
190-
191-
191+ f"Unexpected annotation found. Found { type (predictions [0 ].value )} " )
192192
193193
194194def data_row_miou (ground_truth : Label ,
@@ -206,7 +206,6 @@ def data_row_miou(ground_truth: Label,
206206 Returns:
207207 float indicating the iou score for this data row.
208208 """
209-
210209 prediction_annotations = _create_name_lookup (predictions .annotations )
211210 ground_truth_annotations = _create_name_lookup (ground_truth .annotations )
212211 feature_schemas = set (prediction_annotations .keys ()).union (
@@ -222,20 +221,33 @@ def data_row_miou(ground_truth: Label,
222221 return None
223222 return np .mean (ious )
224223
224+
225225def _create_name_lookup (annotations : List [BaseAnnotation ]):
226226 grouped_annotations = defaultdict (list )
227227 for annotation in annotations :
228- grouped_annotations [annotation .name ] = annotation
228+ grouped_annotations [annotation .name ]. append ( annotation )
229229 return grouped_annotations
230230
231- def _get_vector_pairs (predictions : List [Geometry ],
232- ground_truths : List [Geometry ]):
231+
232+ def _get_vector_pairs (
233+ predictions : List [ObjectAnnotation ],
234+ ground_truths : List [ObjectAnnotation ], buffer : float
235+ ) -> List [Tuple [ObjectAnnotation , ObjectAnnotation , float ]]:
233236 """
234237 # Get iou score for all pairs of labels and predictions
235238 """
236- return [(prediction , ground_truth ,
237- _polygon_iou (prediction .shapely , ground_truth .shapely ))
238- for prediction , ground_truth in product (predictions , ground_truths )]
239+ pairs = []
240+ for prediction , ground_truth in product (predictions , ground_truths ):
241+ if isinstance (prediction .value , Geometry ) and isinstance (
242+ ground_truth .value , Geometry ):
243+ if isinstance (prediction .value , (Line , Point )):
244+ score = _polygon_iou (prediction .value .shapely .buffer (buffer ),
245+ ground_truth .value .shapely .buffer (buffer ))
246+ else :
247+ score = _polygon_iou (prediction .value .shapely ,
248+ ground_truth .value .shapely )
249+ pairs .append ((prediction , ground_truth , score ))
250+ return pairs
239251
240252
241253def _polygon_iou (poly1 : Polygon , poly2 : Polygon ) -> float :
0 commit comments