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 c2ae1c7
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/kili/presentation/client/label.py
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ def export_labels(
external_ids: Optional[List[str]] = None,
annotation_modifier: Optional[CocoAnnotationModifier] = None,
asset_filter_kwargs: Optional[Dict[str, object]] = None,
normalized_coordinates: Optional[bool] = None,
normalized_coordinates: Optional[bool] = True,
label_type_in: Optional[List[str]] = None,
include_sent_back_labels: Optional[bool] = None,
) -> Optional[List[Dict[str, Union[List[str], str]]]]:
Expand Down
62 changes: 48 additions & 14 deletions src/kili/services/export/format/kili/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@
from typing import Callable, Dict, List

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 @@ -97,9 +108,9 @@ 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]

for i in range (len(clean_assets)):
clean_assets[i] = self.convert_to_pixel_coords(clean_assets[i])
clean_assets[i] = _clean_json_response(clean_assets[i])
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,
self.normalized_coordinates,
_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: bool,
annotation_scaler: Callable[[Dict, Dict, bool, int,bool], 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,7 @@ 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: bool = False
) -> None:
"""Scale normalized vertices of a PDF annotation.
Expand Down Expand Up @@ -265,7 +288,7 @@ 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: bool
) -> None:
"""Scale normalized vertices of an image/video object detection annotation."""
if "resolution" not in asset or asset["resolution"] is None:
Expand All @@ -275,21 +298,32 @@ def _scale_normalized_vertices_image_video_annotation(
" 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"]
height = asset["resolution"]["height"]

# bbox, segmentation, polygons
if "boundingPoly" in annotation:
if "boundingPoly" in annotation and not 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"]
]

if "boundingPoly" in annotation and normalized_vertices:
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 c2ae1c7

Please sign in to comment.