Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions next_cvat/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
LabelAttribute,
Mask,
Polygon,
Polyline,
Project,
Tag,
Task,
Expand Down
32 changes: 32 additions & 0 deletions next_cvat/client/job_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,38 @@ def add_mask_(

return self

def add_polyline_(
self,
polyline: next_cvat.Polyline,
image_name: str,
group: int = 0,
) -> JobAnnotations:
label = self.job.task.project.label(name=polyline.label)

frame = self.job.task.frame(image_name=image_name)

self.annotations["shapes"].append(
polyline.request(frame=frame.id, label_id=label.id, group=group)
)

return self

def add_tag_(
self,
tag: next_cvat.Tag,
image_name: str,
group: int = 0,
) -> JobAnnotations:
label = self.job.task.project.label(name=tag.label)

frame = self.job.task.frame(image_name=image_name)

self.annotations["tags"].append(
tag.request(frame=frame.id, label_id=label.id, group=group)
)

return self

def request(self) -> models.LabeledDataRequest:
request = models.LabeledDataRequest()
request.version = self.annotations["version"]
Expand Down
18 changes: 18 additions & 0 deletions next_cvat/types/polyline.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from typing import List, Tuple

import numpy as np
from cvat_sdk.api_client import models
from pydantic import BaseModel, field_validator

from .attribute import Attribute
Expand Down Expand Up @@ -33,3 +35,19 @@ def topmost(self) -> float:

def bottommost(self) -> float:
return max([y for _, y in self.points])

def request(
self, frame: int, label_id: int, group: int = 0
) -> models.LabeledShapeRequest:
return models.LabeledShapeRequest(
type="polyline",
occluded=bool(self.occluded),
points=np.array(self.points).flatten().tolist(),
rotation=0.0,
outside=False,
attributes=[attr.model_dump() for attr in self.attributes],
group=group,
source=self.source,
frame=frame,
label_id=label_id,
)
12 changes: 12 additions & 0 deletions next_cvat/types/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import List

from cvat_sdk.api_client import models
from pydantic import BaseModel

from .attribute import Attribute
Expand All @@ -11,3 +12,14 @@ class Tag(BaseModel):
label: str
source: str
attributes: List[Attribute]

def request(
self, frame: int, label_id: int, group: int = 0
) -> models.LabeledImageRequest:
return models.LabeledImageRequest(
frame=frame,
label_id=label_id,
group=group,
source=self.source,
attributes=[attr.model_dump() for attr in self.attributes],
)
54 changes: 54 additions & 0 deletions tests/test_add_polyline.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from pathlib import Path

import numpy as np
import pytest

import next_cvat


def test_add_polyline():
if not Path(".env.cvat.secrets").exists():
pytest.skip("No secrets file found")

client = next_cvat.Client.from_env_file(".env.cvat.secrets")

project_id = 198488 # Using the same test project as in test_add_mask
job_id = 1442235
task_id = 999670
deformation_attribute_id = 1389238

job = client.project(project_id).task(task_id).job(job_id)

annotations = job.annotations()

# Create a simple polyline (e.g., a zigzag pattern)
points = np.array(
[
[100, 100],
[200, 150],
[300, 100],
[400, 150],
]
).tolist()

annotations.add_polyline_(
next_cvat.Polyline(
points=points,
label="Deformation",
source="manual",
occluded=False,
z_order=0,
attributes=[
next_cvat.Attribute(
name="Severity",
value="High",
spec_id=deformation_attribute_id,
)
],
),
image_name="20240916_000854_2011T_437.bmp",
)

job.update_annotations_(annotations)

print("Successfully added polyline annotation")
40 changes: 40 additions & 0 deletions tests/test_add_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from pathlib import Path

import pytest

import next_cvat


def test_add_tag():
if not Path(".env.cvat.secrets").exists():
pytest.skip("No secrets file found")

client = next_cvat.Client.from_env_file(".env.cvat.secrets")

project_id = 198488 # Using the same test project as in other tests
job_id = 1442235
task_id = 999670
deformation_attribute_id = 1389238

job = client.project(project_id).task(task_id).job(job_id)

annotations = job.annotations()

annotations.add_tag_(
next_cvat.Tag(
label="Deformation",
source="manual",
attributes=[
next_cvat.Attribute(
name="Severity",
value="High",
spec_id=deformation_attribute_id,
)
],
),
image_name="20240916_000854_2011T_437.bmp",
)

job.update_annotations_(annotations)

print("Successfully added tag annotation")