Skip to content

Commit

Permalink
fix(LAB-3447): correct calculation of vertices in kili format
Browse files Browse the repository at this point in the history
  • Loading branch information
Sihem Tchabi committed Feb 3, 2025
1 parent 423b2db commit c952e0e
Showing 1 changed file with 58 additions and 17 deletions.
75 changes: 58 additions & 17 deletions src/kili/services/export/format/kili/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,25 @@

import json
from pathlib import Path
from typing import Callable, Dict, List
from typing import Callable, Dict, List, Optional, Union

from kili.services.export.exceptions import NotCompatibleInputType, NotCompatibleOptions
from kili.services.export.format.base import AbstractExporter
from kili.services.export.format.base import AbstractExporter, reverse_rotation_vertices
from kili.services.export.media.video import cut_video
from kili.services.types import Job


def _clean_json_response(asset: Dict):
if asset.get("latestLabel", {}) and asset["latestLabel"].get("jsonResponse", {}):
if "ROTATION_JOB" in asset["latestLabel"]["jsonResponse"]:
asset["latestLabel"]["jsonResponse"].pop("ROTATION_JOB")
if asset.get("labels"):
for label in asset["labels"]:
if label.get("jsonResponse", {}) and "ROTATION_JOB" in label["jsonResponse"]:
label["jsonResponse"].pop("ROTATION_JOB")
return asset


class KiliExporter(AbstractExporter):
"""Common code for Kili exporters."""

Expand Down Expand Up @@ -96,10 +107,10 @@ def _cut_video_assets(self, assets: List[Dict]) -> List[Dict]:
def process_and_save(self, assets: List[Dict], output_filename: Path) -> None:
"""Extract formatted annotations from labels and save the json in the buckets."""
clean_assets = self.preprocess_assets(assets)

if self.normalized_coordinates is False:
clean_assets = [self.convert_to_pixel_coords(asset) for asset in clean_assets]

if self.project["inputType"] != "LLM_RLHF":
for i, asset in enumerate(clean_assets):
clean_assets[i] = self.convert_to_pixel_coords(asset)
clean_assets[i] = _clean_json_response(asset)
return self._save_assets_export(
clean_assets,
output_filename,
Expand Down Expand Up @@ -131,11 +142,17 @@ def _scale_label_vertices(self, label: Dict, asset: Dict) -> None:
else False
)

rotation_val = 0
if "ROTATION_JOB" in label["jsonResponse"]:
rotation_val = label["jsonResponse"]["ROTATION_JOB"]["rotation"]

if self.project["inputType"] == "PDF":
self._scale_json_response_vertices(
label["jsonResponse"],
asset,
is_label_rotated,
rotation_val,
False,
_scale_normalized_vertices_pdf_annotation,
)

Expand All @@ -144,6 +161,8 @@ def _scale_label_vertices(self, label: Dict, asset: Dict) -> None:
label["jsonResponse"],
asset,
is_label_rotated,
rotation_val,
self.normalized_coordinates,
_scale_normalized_vertices_image_video_annotation,
)

Expand All @@ -154,6 +173,8 @@ def _scale_label_vertices(self, label: Dict, asset: Dict) -> None:
frame_resp,
asset,
is_label_rotated,
rotation_val,
self.normalized_coordinates,
_scale_normalized_vertices_image_video_annotation,
)

Expand All @@ -168,14 +189,16 @@ def _scale_json_response_vertices(
json_resp: Dict,
asset: Dict,
is_label_rotated: bool,
annotation_scaler: Callable[[Dict, Dict, bool], None],
rotation: int,
normalized_vertices: Optional[bool],
annotation_scaler: Callable[[Dict, Dict, bool, int, Union[bool, None]], None],
) -> None:
for job_name in json_resp:
if self._can_scale_vertices_for_job_name(job_name) and json_resp.get(job_name, {}).get(
"annotations"
):
for ann in json_resp[job_name]["annotations"]:
annotation_scaler(ann, asset, is_label_rotated)
annotation_scaler(ann, asset, is_label_rotated, rotation, normalized_vertices)

def _can_scale_vertices_for_job_name(self, job_name: str) -> bool:
return (
Expand Down Expand Up @@ -212,7 +235,11 @@ def _scale_all_vertices(object_, width: int, height: int):


def _scale_normalized_vertices_pdf_annotation(
annotation: Dict, asset: Dict, is_label_rotated: bool = False
annotation: Dict,
asset: Dict,
is_label_rotated: bool = False,
_rotation: int = 0,
_normalized_vertices: Union[bool, None] = False,
) -> None:
"""Scale normalized vertices of a PDF annotation.
Expand Down Expand Up @@ -265,31 +292,45 @@ def _scale_normalized_vertices_pdf_annotation(


def _scale_normalized_vertices_image_video_annotation(
annotation: Dict, asset: Dict, is_label_rotated: bool
annotation: Dict, asset: Dict, _is_label_rotated: bool, rotation: int, _normalized_vertices: Optional[bool]
) -> None:
"""Scale normalized vertices of an image/video object detection annotation."""
if "resolution" not in asset or asset["resolution"] is None:
if _normalized_vertices is False and ("resolution" not in asset or asset["resolution"] is None):
raise NotCompatibleOptions(
"Image and video labels export with absolute coordinates require `resolution` in the"
" asset. Please use `kili.update_properties_in_assets(resolution_array=...)` to update"
" the resolution of your asset.`"
)

width = asset["resolution"]["width"] if not is_label_rotated else asset["resolution"]["height"]
height = asset["resolution"]["height"] if not is_label_rotated else asset["resolution"]["width"]
width = asset["resolution"]["width"] if "resolution" in asset is not None else 0
height = asset["resolution"]["height"] if "resolution" in asset is not None else 0

# bbox, segmentation, polygons
if "boundingPoly" in annotation:
if "boundingPoly" in annotation and _normalized_vertices:
annotation["boundingPoly"] = [
{
**norm_vertices_dict, # keep the original normalizedVertices
"vertices": _scale_all_vertices(
norm_vertices_dict["normalizedVertices"], width=width, height=height
"normalizedVertices": reverse_rotation_vertices(
norm_vertices_dict["normalizedVertices"], rotation
),
}
for norm_vertices_dict in annotation["boundingPoly"]
]
return

if "boundingPoly" in annotation and _normalized_vertices is False:
annotation["boundingPoly"] = [
{
"normalizedVertices": reverse_rotation_vertices(
norm_vertices_dict["normalizedVertices"], rotation
),
"vertices": _scale_all_vertices(
reverse_rotation_vertices(norm_vertices_dict["normalizedVertices"], rotation),
width=width,
height=height,
),
}
for norm_vertices_dict in annotation["boundingPoly"]
]
# point jobs
if "point" in annotation:
annotation["pointPixels"] = _scale_all_vertices(
Expand Down

0 comments on commit c952e0e

Please sign in to comment.