55from typing import Callable , Dict , List
66
77from kili .services .export .exceptions import NotCompatibleInputType , NotCompatibleOptions
8- from kili .services .export .format .base import AbstractExporter
8+ from kili .services .export .format .base import AbstractExporter , reverse_rotation_vertices
99from kili .services .export .media .video import cut_video
1010from kili .services .types import Job
1111
1212
13+ def _clean_json_response (asset : Dict ):
14+ if "latestLabel" in asset and "jsonResponse" in asset ["latestLabel" ]:
15+ if "ROTATION_JOB" in asset ["latestLabel" ]["jsonResponse" ]:
16+ asset ["latestLabel" ]["jsonResponse" ].pop ("ROTATION_JOB" )
17+ if "labels" in asset :
18+ for label in asset ["labels" ]:
19+ if "jsonResponse" in label and "ROTATION_JOB" in label ["jsonResponse" ]:
20+ label ["jsonResponse" ].pop ("ROTATION_JOB" )
21+ return asset
22+
23+
1324class KiliExporter (AbstractExporter ):
1425 """Common code for Kili exporters."""
1526
@@ -96,10 +107,10 @@ def _cut_video_assets(self, assets: List[Dict]) -> List[Dict]:
96107 def process_and_save (self , assets : List [Dict ], output_filename : Path ) -> None :
97108 """Extract formatted annotations from labels and save the json in the buckets."""
98109 clean_assets = self .preprocess_assets (assets )
99-
100- if self . normalized_coordinates is False :
101- clean_assets = [ self .convert_to_pixel_coords (asset ) for asset in clean_assets ]
102-
110+ if self . project [ "inputType" ] != "LLM_RLHF" :
111+ for i , asset in enumerate ( clean_assets ) :
112+ clean_assets [ i ] = self .convert_to_pixel_coords (asset )
113+ clean_assets [ i ] = _clean_json_response ( asset )
103114 return self ._save_assets_export (
104115 clean_assets ,
105116 output_filename ,
@@ -131,30 +142,38 @@ def _scale_label_vertices(self, label: Dict, asset: Dict) -> None:
131142 else False
132143 )
133144
145+ rotation_val = 0
146+ if "ROTATION_JOB" in label ["jsonResponse" ]:
147+ rotation_val = label ["jsonResponse" ]["ROTATION_JOB" ]["rotation" ]
148+
149+ normalized_vertices = self .normalized_coordinates is not False
150+
134151 if self .project ["inputType" ] == "PDF" :
135152 self ._scale_json_response_vertices (
136- label ["jsonResponse" ],
137- asset ,
138- is_label_rotated ,
139- _scale_normalized_vertices_pdf_annotation ,
153+ json_resp = label ["jsonResponse" ],
154+ asset = asset ,
155+ is_label_rotated = is_label_rotated ,
156+ annotation_scaler = _scale_normalized_vertices_pdf_annotation ,
140157 )
141158
142159 elif self .project ["inputType" ] == "IMAGE" :
143160 self ._scale_json_response_vertices (
144- label ["jsonResponse" ],
145- asset ,
146- is_label_rotated ,
147- _scale_normalized_vertices_image_video_annotation ,
161+ json_resp = label ["jsonResponse" ],
162+ asset = asset ,
163+ rotation = rotation_val ,
164+ normalized_vertices = normalized_vertices ,
165+ annotation_scaler = _scale_normalized_vertices_image_video_annotation ,
148166 )
149167
150168 elif self .project ["inputType" ] == "VIDEO" :
151169 for frame_resp in label ["jsonResponse" ].values ():
152170 if frame_resp :
153171 self ._scale_json_response_vertices (
154- frame_resp ,
155- asset ,
156- is_label_rotated ,
157- _scale_normalized_vertices_image_video_annotation ,
172+ json_resp = frame_resp ,
173+ asset = asset ,
174+ rotation = rotation_val ,
175+ normalized_vertices = normalized_vertices ,
176+ annotation_scaler = _scale_normalized_vertices_image_video_annotation ,
158177 )
159178
160179 else :
@@ -164,18 +183,16 @@ def _scale_label_vertices(self, label: Dict, asset: Dict) -> None:
164183 )
165184
166185 def _scale_json_response_vertices (
167- self ,
168- json_resp : Dict ,
169- asset : Dict ,
170- is_label_rotated : bool ,
171- annotation_scaler : Callable [[Dict , Dict , bool ], None ],
186+ self , asset : Dict , json_resp : Dict , annotation_scaler : Callable , ** kwargs
172187 ) -> None :
188+ if not callable (annotation_scaler ):
189+ return
173190 for job_name in json_resp :
174191 if self ._can_scale_vertices_for_job_name (job_name ) and json_resp .get (job_name , {}).get (
175192 "annotations"
176193 ):
177194 for ann in json_resp [job_name ]["annotations" ]:
178- annotation_scaler (ann , asset , is_label_rotated )
195+ annotation_scaler (ann , asset , ** kwargs )
179196
180197 def _can_scale_vertices_for_job_name (self , job_name : str ) -> bool :
181198 return (
@@ -211,23 +228,23 @@ def _scale_all_vertices(object_, width: int, height: int):
211228 return object_
212229
213230
214- def _scale_normalized_vertices_pdf_annotation (
215- annotation : Dict , asset : Dict , is_label_rotated : bool = False
216- ) -> None :
231+ def _scale_normalized_vertices_pdf_annotation (annotation : Dict , asset : Dict , ** kwargs ) -> None :
217232 """Scale normalized vertices of a PDF annotation.
218233
219234 PDF annotations are different from image annotations because the asset width/height can vary.
220235
221236 PDF only have BBox detection, so we only scale the boundingPoly and polys keys.
222237 """
238+ is_label_rotated = kwargs .get ("is_label_rotated" , False )
239+
223240 if is_label_rotated :
224241 raise NotCompatibleOptions ("PDF labels cannot be rotated" )
225242
226243 if "annotations" in annotation :
227244 # pdf annotations have two layers of "annotations"
228245 # https://docs.kili-technology.com/reference/export-object-entity-detection-and-relation#ner-in-pdfs
229246 for ann in annotation ["annotations" ]:
230- _scale_normalized_vertices_pdf_annotation (ann , asset )
247+ _scale_normalized_vertices_pdf_annotation (ann , asset , ** kwargs )
231248
232249 # an annotation has three keys:
233250 # - pageNumberArray: list of page numbers
@@ -265,31 +282,48 @@ def _scale_normalized_vertices_pdf_annotation(
265282
266283
267284def _scale_normalized_vertices_image_video_annotation (
268- annotation : Dict , asset : Dict , is_label_rotated : bool
285+ annotation : Dict , asset : Dict , ** kwargs
269286) -> None :
270287 """Scale normalized vertices of an image/video object detection annotation."""
271- if "resolution" not in asset or asset ["resolution" ] is None :
288+ rotation = kwargs .get ("rotation" , 0 )
289+ normalized_vertices = kwargs .get ("normalized_vertices" , True )
290+
291+ if not normalized_vertices and ("resolution" not in asset or asset ["resolution" ] is None ):
272292 raise NotCompatibleOptions (
273293 "Image and video labels export with absolute coordinates require `resolution` in the"
274294 " asset. Please use `kili.update_properties_in_assets(resolution_array=...)` to update"
275295 " the resolution of your asset.`"
276296 )
277297
278- width = asset ["resolution" ]["width" ] if not is_label_rotated else asset [ "resolution" ][ "height" ]
279- height = asset ["resolution" ]["height" ] if not is_label_rotated else asset [ "resolution" ][ "width" ]
298+ width = asset ["resolution" ]["width" ] if "resolution" in asset else 0
299+ height = asset ["resolution" ]["height" ] if "resolution" in asset else 0
280300
281301 # bbox, segmentation, polygons
282- if "boundingPoly" in annotation :
302+ if "boundingPoly" in annotation and normalized_vertices :
283303 annotation ["boundingPoly" ] = [
284304 {
285- ** norm_vertices_dict , # keep the original normalizedVertices
286- "vertices" : _scale_all_vertices (
287- norm_vertices_dict ["normalizedVertices" ], width = width , height = height
305+ "normalizedVertices" : reverse_rotation_vertices (
306+ norm_vertices_dict ["normalizedVertices" ], rotation
288307 ),
289308 }
290309 for norm_vertices_dict in annotation ["boundingPoly" ]
291310 ]
311+ return
292312
313+ if "boundingPoly" in annotation and not normalized_vertices :
314+ annotation ["boundingPoly" ] = [
315+ {
316+ "normalizedVertices" : reverse_rotation_vertices (
317+ norm_vertices_dict ["normalizedVertices" ], rotation
318+ ),
319+ "vertices" : _scale_all_vertices (
320+ reverse_rotation_vertices (norm_vertices_dict ["normalizedVertices" ], rotation ),
321+ width = width ,
322+ height = height ,
323+ ),
324+ }
325+ for norm_vertices_dict in annotation ["boundingPoly" ]
326+ ]
293327 # point jobs
294328 if "point" in annotation :
295329 annotation ["pointPixels" ] = _scale_all_vertices (
0 commit comments