@@ -89,7 +89,8 @@ def test__get_coco_image_annotations():
89
89
assert coco_annotation ["annotations" ][0 ]["segmentation" ] == [
90
90
[0.0 , 0.0 , 960.0 , 0.0 , 0.0 , 540.0 ]
91
91
]
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
93
94
94
95
good_date = True
95
96
try :
@@ -101,6 +102,182 @@ def test__get_coco_image_annotations():
101
102
)
102
103
103
104
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
+
104
281
@pytest .mark .parametrize (
105
282
("name" , "normalized_vertices" , "expected_angle" , "expected_bounding_box" ),
106
283
[
@@ -139,8 +316,6 @@ def test__get_coco_image_annotations_with_label_modifier(
139
316
local_file_path = tmp_dir / Path ("image1.jpg" )
140
317
Image .new ("RGB" , (image_width , image_height )).save (local_file_path )
141
318
142
- area = 2073600
143
-
144
319
expected_segmentation = [
145
320
a for p in normalized_vertices for a in [p ["x" ] * image_width , p ["y" ] * image_height ]
146
321
]
@@ -199,7 +374,10 @@ def test__get_coco_image_annotations_with_label_modifier(
199
374
assert coco_annotation ["annotations" ][0 ]["segmentation" ][0 ] == pytest .approx (
200
375
expected_segmentation
201
376
)
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
+ )
203
381
204
382
good_date = True
205
383
try :
@@ -409,13 +587,16 @@ def test_get_coco_geometry_from_kili_bpoly():
409
587
}
410
588
]
411
589
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
+ )
413
593
assert bbox == [192 , 108 , 1344 , 324 ]
594
+ assert area == bbox [2 ] * bbox [3 ] # Area of a rectangle: width * height
414
595
assert bbox [0 ] == int (0.1 * image_width )
415
596
assert bbox [1 ] == int (0.1 * image_height )
416
597
assert bbox [2 ] == int ((0.8 - 0.1 ) * image_width )
417
598
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 ] ]
419
600
420
601
421
602
def test__get_kili_cat_id_to_coco_cat_id_mapping_with_split_jobs ():
0 commit comments