@@ -89,7 +89,8 @@ def test__get_coco_image_annotations():
8989 assert coco_annotation ["annotations" ][0 ]["segmentation" ] == [
9090 [0.0 , 0.0 , 960.0 , 0.0 , 0.0 , 540.0 ]
9191 ]
92- assert coco_annotation ["annotations" ][0 ]["area" ] == 2073600
92+ # Area of a triangle: base * height / 2
93+ assert coco_annotation ["annotations" ][0 ]["area" ] == 960.0 * 540.0 / 2
9394
9495 good_date = True
9596 try :
@@ -101,6 +102,182 @@ def test__get_coco_image_annotations():
101102 )
102103
103104
105+ def test__get_coco_image_annotation_area_with_self_intersecting_polygon ():
106+ with TemporaryDirectory () as tmp_dir :
107+ job_name = "JOB_0"
108+ output_file = Path (tmp_dir ) / job_name / "labels.json"
109+ local_file_path = tmp_dir / Path ("image1.jpg" )
110+ image_width = 1920
111+ image_height = 1080
112+ Image .new ("RGB" , (image_width , image_height )).save (local_file_path )
113+ _ , paths = _convert_kili_semantic_to_coco (
114+ jobs = {
115+ JobName (job_name ): {
116+ "mlTask" : "OBJECT_DETECTION" ,
117+ "content" : {
118+ "categories" : {
119+ "OBJECT_A" : {"name" : "Object A" },
120+ "OBJECT_B" : {"name" : "Object B" },
121+ }
122+ },
123+ "instruction" : "" ,
124+ "isChild" : False ,
125+ "isNew" : False ,
126+ "isVisible" : True ,
127+ "models" : {},
128+ "required" : True ,
129+ "tools" : ["semantic" ],
130+ }
131+ },
132+ assets = [
133+ helpers .get_asset (
134+ local_file_path ,
135+ with_annotation = [
136+ {
137+ "x" : 0.0 ,
138+ "y" : 0.0 ,
139+ },
140+ {
141+ "x" : 0.5 ,
142+ "y" : 0.0 ,
143+ },
144+ {
145+ "x" : 0.0 ,
146+ "y" : 0.5 ,
147+ },
148+ {
149+ "x" : 0.5 ,
150+ "y" : 0.5 ,
151+ },
152+ {
153+ "x" : 0.0 ,
154+ "y" : 0.0 ,
155+ },
156+ ],
157+ )
158+ ],
159+ output_dir = Path (tmp_dir ),
160+ title = "Test project" ,
161+ project_input_type = "IMAGE" ,
162+ annotation_modifier = lambda x , _ , _1 : x ,
163+ merged = False ,
164+ )
165+
166+ assert paths [0 ] == output_file
167+ with output_file .open ("r" , encoding = "utf-8" ) as f :
168+ coco_annotation = json .loads (f .read ())
169+
170+ assert coco_annotation ["annotations" ][0 ]["bbox" ] == [0 , 0 , 960 , 540 ]
171+ assert coco_annotation ["annotations" ][0 ]["segmentation" ] == [
172+ [0.0 , 0.0 , 960.0 , 0.0 , 0.0 , 540.0 , 960.0 , 540.0 , 0.0 , 0.0 ]
173+ ]
174+ # Here we have a self-intersecting polygon with 2 opposites triangles, so the area is
175+ # the sum of the areas of the 2 triangles.
176+ # Area of a triangle: base * height / 2
177+ assert coco_annotation ["annotations" ][0 ]["area" ] == (960.0 * 270.0 / 2 ) * 2
178+
179+
180+ def test__get_coco_image_annotation_area_with_negative_polygons ():
181+ with TemporaryDirectory () as tmp_dir :
182+ job_name = "JOB_0"
183+ output_file = Path (tmp_dir ) / job_name / "labels.json"
184+ local_file_path = tmp_dir / Path ("image1.jpg" )
185+ image_width = 1920
186+ image_height = 1080
187+ Image .new ("RGB" , (image_width , image_height )).save (local_file_path )
188+ _ , paths = _convert_kili_semantic_to_coco (
189+ jobs = {
190+ JobName (job_name ): {
191+ "mlTask" : "OBJECT_DETECTION" ,
192+ "content" : {
193+ "categories" : {
194+ "OBJECT_A" : {"name" : "Object A" },
195+ "OBJECT_B" : {"name" : "Object B" },
196+ }
197+ },
198+ "instruction" : "" ,
199+ "isChild" : False ,
200+ "isNew" : False ,
201+ "isVisible" : True ,
202+ "models" : {},
203+ "required" : True ,
204+ "tools" : ["semantic" ],
205+ }
206+ },
207+ assets = [
208+ helpers .get_asset (
209+ local_file_path ,
210+ with_annotation = [
211+ {
212+ "x" : 0.0 ,
213+ "y" : 0.0 ,
214+ },
215+ {
216+ "x" : 0.5 ,
217+ "y" : 0.0 ,
218+ },
219+ {
220+ "x" : 0.0 ,
221+ "y" : 0.5 ,
222+ },
223+ ],
224+ negative_polygons = [
225+ [
226+ {
227+ "x" : 0.1 ,
228+ "y" : 0.1 ,
229+ },
230+ {
231+ "x" : 0.4 ,
232+ "y" : 0.1 ,
233+ },
234+ {
235+ "x" : 0.1 ,
236+ "y" : 0.4 ,
237+ },
238+ ],
239+ [
240+ {
241+ "x" : 0.0 ,
242+ "y" : 0.0 ,
243+ },
244+ {
245+ "x" : 0.1 ,
246+ "y" : 0.0 ,
247+ },
248+ {
249+ "x" : 0.0 ,
250+ "y" : 0.1 ,
251+ },
252+ ],
253+ ],
254+ )
255+ ],
256+ output_dir = Path (tmp_dir ),
257+ title = "Test project" ,
258+ project_input_type = "IMAGE" ,
259+ annotation_modifier = lambda x , _ , _1 : x ,
260+ merged = False ,
261+ )
262+
263+ assert paths [0 ] == output_file
264+ with output_file .open ("r" , encoding = "utf-8" ) as f :
265+ coco_annotation = json .loads (f .read ())
266+
267+ assert coco_annotation ["annotations" ][0 ]["bbox" ] == [0 , 0 , 960 , 540 ]
268+ assert coco_annotation ["annotations" ][0 ]["segmentation" ] == [
269+ [0.0 , 0.0 , 960.0 , 0.0 , 0.0 , 540.0 ],
270+ [192.0 , 108.0 , 768.0 , 108.0 , 192.0 , 432.0 ],
271+ [0.0 , 0.0 , 192.0 , 0.0 , 0.0 , 108.0 ],
272+ ]
273+ # Here we have a positive triangle with 2 negative triangles inside, so the area is the
274+ # area of the positive triangle minus the area of the negative triangles.
275+ # Area of a triangle: base * height / 2
276+ assert coco_annotation ["annotations" ][0 ]["area" ] == (960.0 * 540.0 / 2 ) - (
277+ 576.0 * 324.0 / 2
278+ ) - (192.0 * 108.0 / 2 )
279+
280+
104281@pytest .mark .parametrize (
105282 ("name" , "normalized_vertices" , "expected_angle" , "expected_bounding_box" ),
106283 [
@@ -139,8 +316,6 @@ def test__get_coco_image_annotations_with_label_modifier(
139316 local_file_path = tmp_dir / Path ("image1.jpg" )
140317 Image .new ("RGB" , (image_width , image_height )).save (local_file_path )
141318
142- area = 2073600
143-
144319 expected_segmentation = [
145320 a for p in normalized_vertices for a in [p ["x" ] * image_width , p ["y" ] * image_height ]
146321 ]
@@ -199,7 +374,10 @@ def test__get_coco_image_annotations_with_label_modifier(
199374 assert coco_annotation ["annotations" ][0 ]["segmentation" ][0 ] == pytest .approx (
200375 expected_segmentation
201376 )
202- assert coco_annotation ["annotations" ][0 ]["area" ] == area
377+ # Area of a rectangle: width * height
378+ assert coco_annotation ["annotations" ][0 ]["area" ] == pytest .approx (
379+ expected_bounding_box [2 ] * expected_bounding_box [3 ]
380+ )
203381
204382 good_date = True
205383 try :
@@ -409,13 +587,16 @@ def test_get_coco_geometry_from_kili_bpoly():
409587 }
410588 ]
411589 image_width , image_height = 1920 , 1080
412- bbox , poly = _get_coco_geometry_from_kili_bpoly (boundingPoly , image_width , image_height )
590+ area , bbox , polygons = _get_coco_geometry_from_kili_bpoly (
591+ boundingPoly , image_width , image_height
592+ )
413593 assert bbox == [192 , 108 , 1344 , 324 ]
594+ assert area == bbox [2 ] * bbox [3 ] # Area of a rectangle: width * height
414595 assert bbox [0 ] == int (0.1 * image_width )
415596 assert bbox [1 ] == int (0.1 * image_height )
416597 assert bbox [2 ] == int ((0.8 - 0.1 ) * image_width )
417598 assert bbox [3 ] == int ((0.4 - 0.1 ) * image_height )
418- assert poly == [192.0 , 108.0 , 192.0 , 432.0 , 1536.0 , 432.0 , 1536.0 , 108.0 ]
599+ assert polygons == [[ 192.0 , 108.0 , 192.0 , 432.0 , 1536.0 , 432.0 , 1536.0 , 108.0 ] ]
419600
420601
421602def test__get_kili_cat_id_to_coco_cat_id_mapping_with_split_jobs ():
0 commit comments