diff --git a/pytest.ini b/pytest.ini index d9ab3b4..de4eaf7 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,4 +2,4 @@ minversion = 3.0 log_cli=true python_files = test_*.py -;addopts = -n auto --dist=loadscope \ No newline at end of file +addopts = -n auto --dist=loadscope diff --git a/src/superannotate_schemas/bin/interface.py b/src/superannotate_schemas/bin/interface.py index ae10627..7cd5f18 100644 --- a/src/superannotate_schemas/bin/interface.py +++ b/src/superannotate_schemas/bin/interface.py @@ -1,4 +1,5 @@ import os +from os.path import expanduser import json import errno from pathlib import Path @@ -61,7 +62,7 @@ def validate(*paths, project_type, internal=False, verbose=False, report_path=No if verbose: print(f"{'-'* 4}{path}\n{report}") if report_path: - with open(f"{report_path}/{uniquify(Path(path).name)}") as validation_report: + with open(uniquify(f"{report_path}/{(Path(path).name)}"), "w") as validation_report: validation_report.write(report) else: validation_result.append({path: False}) diff --git a/src/superannotate_schemas/schemas/base.py b/src/superannotate_schemas/schemas/base.py index d8522a4..c9056bb 100644 --- a/src/superannotate_schemas/schemas/base.py +++ b/src/superannotate_schemas/schemas/base.py @@ -26,6 +26,7 @@ from superannotate_schemas.schemas.enums import BaseImageRoleEnum from superannotate_schemas.schemas.enums import VectorAnnotationTypeEnum from superannotate_schemas.schemas.enums import AnnotationStatusEnum +from superannotate_schemas.schemas.enums import ClassTypeEnum from superannotate_schemas.schemas.constances import DATE_REGEX from superannotate_schemas.schemas.constances import DATE_TIME_FORMAT_ERROR_MESSAGE from superannotate_schemas.schemas.constances import POINT_LABEL_VALUE_FORMAT_ERROR_MESSAGE @@ -64,20 +65,14 @@ class AxisPoint(BaseModel): class BaseAttribute(BaseModel): id: Optional[StrictInt] group_id: Optional[StrictInt] = Field(alias="groupId") - name: NotEmptyStr - group_name: NotEmptyStr = Field(alias="groupName") + name: Optional[NotEmptyStr] + group_name: Optional[NotEmptyStr] = Field(alias="groupName") class Tag(BaseModel): __root__: NotEmptyStr -class AttributeGroup(BaseModel): - name: NotEmptyStr - is_multiselect: Optional[bool] = Field(False) - attributes: List[BaseAttribute] - - class BboxPoints(BaseModel): x1: StrictNumber x2: StrictNumber @@ -126,6 +121,12 @@ class BaseInstance(TrackableModel, TimedBaseModel): class_name: Optional[NotEmptyStr] = Field(None, alias="className") +class BaseInstanceTag(BaseInstance): + type: ClassTypeEnum + probability: Optional[StrictInt] = Field(100) + attributes: Optional[List[BaseAttribute]] = Field(list()) + + class BaseMetadata(BaseModel): name: NotEmptyStr url: Optional[StrictStr] @@ -220,15 +221,8 @@ class BaseVectorInstance(BaseImageAnnotationInstance): tracking_id: Optional[str] = Field(alias="trackingId") group_id: Optional[int] = Field(alias="groupId") -# -# class Metadata(BaseMetadata): -# name: NotEmptyStr -# status: Optional[AnnotationStatusEnum] -# pinned: Optional[StrictBool] -# is_predicted: Optional[StrictBool] = Field(None, alias="isPredicted") - -class PixelColor(BaseModel): +class HexColor(BaseModel): __root__: ColorType @validator("__root__") diff --git a/src/superannotate_schemas/schemas/classes.py b/src/superannotate_schemas/schemas/classes.py new file mode 100644 index 0000000..314b870 --- /dev/null +++ b/src/superannotate_schemas/schemas/classes.py @@ -0,0 +1,48 @@ +from typing import Optional +from typing import List + +from superannotate_schemas.schemas.base import BaseModel +from superannotate_schemas.schemas.base import TimedBaseModel +from superannotate_schemas.schemas.base import StrictInt +from superannotate_schemas.schemas.base import StrictStr +from superannotate_schemas.schemas.base import HexColor +from superannotate_schemas.schemas.enums import ClassTypeEnum + + +class Attribute(TimedBaseModel): + id: Optional[StrictInt] + group_id: Optional[StrictInt] + project_id: Optional[StrictInt] + name: StrictStr + count: Optional[StrictInt] + + def __hash__(self): + return hash(f"{self.id}{self.group_id}{self.name}") + + +class AttributeGroup(TimedBaseModel): + id: Optional[StrictInt] + class_id: Optional[StrictInt] + name: StrictStr + is_multiselect: Optional[bool] + attributes: List[Attribute] + + def __hash__(self): + return hash(f"{self.id}{self.class_id}{self.name}") + + +class AnnotationClass(TimedBaseModel): + id: Optional[StrictInt] + project_id: Optional[StrictInt] + type: ClassTypeEnum = ClassTypeEnum.OBJECT + name: StrictStr + color: HexColor + count: Optional[StrictInt] + attribute_groups: List[AttributeGroup] + + def __hash__(self): + return hash(f"{self.id}{self.type}{self.name}") + + +class AnnotationClasses(BaseModel): + __root__: List[AnnotationClass] diff --git a/src/superannotate_schemas/schemas/enums.py b/src/superannotate_schemas/schemas/enums.py index 0b8557b..1d8cb8e 100644 --- a/src/superannotate_schemas/schemas/enums.py +++ b/src/superannotate_schemas/schemas/enums.py @@ -10,6 +10,7 @@ class VectorAnnotationTypeEnum(str, Enum): POLYGON = "polygon" POINT = "point" RBBOX = "rbbox" + TAG = "tag" class CreationTypeEnum(str, Enum): @@ -38,3 +39,8 @@ class BaseImageRoleEnum(str, Enum): ADMIN = "Admin" ANNOTATOR = "Annotator" QA = "QA" + + +class ClassTypeEnum(str, Enum): + OBJECT = "object" + TAG = "tag" diff --git a/src/superannotate_schemas/schemas/external/pixel.py b/src/superannotate_schemas/schemas/external/pixel.py index b21b3d5..23de3a1 100644 --- a/src/superannotate_schemas/schemas/external/pixel.py +++ b/src/superannotate_schemas/schemas/external/pixel.py @@ -6,7 +6,7 @@ from superannotate_schemas.schemas.base import BaseImageMetadata from superannotate_schemas.schemas.base import NotEmptyStr from superannotate_schemas.schemas.base import StrictStr -from superannotate_schemas.schemas.base import PixelColor +from superannotate_schemas.schemas.base import HexColor from superannotate_schemas.schemas.base import Tag from superannotate_schemas.schemas.base import Comment @@ -25,7 +25,7 @@ class MetaData(BaseImageMetadata): class AnnotationPart(BaseModel): - color: PixelColor + color: HexColor class AnnotationInstance(BaseImageAnnotationInstance): diff --git a/src/superannotate_schemas/schemas/external/vector.py b/src/superannotate_schemas/schemas/external/vector.py index 637faca..d04be70 100644 --- a/src/superannotate_schemas/schemas/external/vector.py +++ b/src/superannotate_schemas/schemas/external/vector.py @@ -21,9 +21,14 @@ from superannotate_schemas.schemas.base import NotEmptyStr from superannotate_schemas.schemas.base import StrictNumber from superannotate_schemas.schemas.base import Tag +from superannotate_schemas.schemas.base import BaseInstanceTag from superannotate_schemas.schemas.enums import VectorAnnotationTypeEnum +class InstanceTag(BaseInstanceTag): + class_name: NotEmptyStr + + class Attribute(BaseAttribute): name: NotEmptyStr group_name: NotEmptyStr = Field(alias="groupName") @@ -115,12 +120,13 @@ class Cuboid(VectorInstance): VectorAnnotationTypeEnum.POLYLINE: PolyLine, VectorAnnotationTypeEnum.ELLIPSE: Ellipse, VectorAnnotationTypeEnum.RBBOX: RotatedBox, + VectorAnnotationTypeEnum.TAG: InstanceTag, } class AnnotationInstance(BaseModel): __root__: Union[ - Template, Cuboid, Point, PolyLine, Polygon, Bbox, Ellipse, RotatedBox + Template, Cuboid, Point, PolyLine, Polygon, Bbox, Ellipse, RotatedBox, InstanceTag ] @classmethod diff --git a/src/superannotate_schemas/schemas/internal/pixel.py b/src/superannotate_schemas/schemas/internal/pixel.py index 3d73ec1..0b4d981 100644 --- a/src/superannotate_schemas/schemas/internal/pixel.py +++ b/src/superannotate_schemas/schemas/internal/pixel.py @@ -2,7 +2,7 @@ from typing import Optional from superannotate_schemas.schemas.base import BaseImageMetadata as Metadata -from superannotate_schemas.schemas.base import PixelColor +from superannotate_schemas.schemas.base import HexColor from superannotate_schemas.schemas.base import BaseAttribute from superannotate_schemas.schemas.base import BaseImageAnnotationInstance from superannotate_schemas.schemas.base import Tag @@ -19,7 +19,7 @@ class Attribute(BaseAttribute): class AnnotationPart(BaseModel): - color: PixelColor + color: HexColor class AnnotationInstance(BaseImageAnnotationInstance): diff --git a/src/superannotate_schemas/schemas/internal/vector.py b/src/superannotate_schemas/schemas/internal/vector.py index 4ec86bb..16cc89b 100644 --- a/src/superannotate_schemas/schemas/internal/vector.py +++ b/src/superannotate_schemas/schemas/internal/vector.py @@ -10,6 +10,7 @@ from superannotate_schemas.schemas.base import Tag from superannotate_schemas.schemas.base import AxisPoint from superannotate_schemas.schemas.base import VectorAnnotationTypeEnum +from superannotate_schemas.schemas.base import BaseInstanceTag from superannotate_schemas.schemas.base import StrictNumber from superannotate_schemas.schemas.base import INVALID_DICT_MESSAGE from superannotate_schemas.schemas.base import BaseModel @@ -24,6 +25,11 @@ from pydantic.error_wrappers import ErrorWrapper + +class InstanceTag(BaseInstanceTag): + class_id: StrictInt + + class Attribute(BaseAttribute): id: StrictInt group_id: StrictInt = Field(alias="groupId") @@ -110,11 +116,13 @@ class Cuboid(VectorInstance): VectorAnnotationTypeEnum.POLYLINE: PolyLine, VectorAnnotationTypeEnum.ELLIPSE: Ellipse, VectorAnnotationTypeEnum.RBBOX: RotatedBox, + VectorAnnotationTypeEnum.TAG: InstanceTag, } + class AnnotationInstance(BaseModel): __root__: Union[ - Template, Cuboid, Point, PolyLine, Polygon, Bbox, Ellipse, RotatedBox + Template, Cuboid, Point, PolyLine, Polygon, Bbox, Ellipse, RotatedBox, InstanceTag ] @classmethod diff --git a/src/superannotate_schemas/validators.py b/src/superannotate_schemas/validators.py index a093e03..ea4ee8f 100644 --- a/src/superannotate_schemas/validators.py +++ b/src/superannotate_schemas/validators.py @@ -15,6 +15,7 @@ from superannotate_schemas.schemas.internal import VectorAnnotation as InternalVectorAnnotation from superannotate_schemas.schemas.internal import VideoAnnotation as InternalVideoAnnotation from superannotate_schemas.schemas.internal import DocumentAnnotation as InternalDocumentAnnotation +from superannotate_schemas.schemas.classes import AnnotationClass from superannotate_schemas.schemas.base import BaseModel diff --git a/tests/test_cli.py b/tests/test_cli.py index c968554..5b995e8 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -82,4 +82,5 @@ def test_(self): # pass # print(time.time() - s) import datetime - print((datetime.datetime.now(datetime.timezone.utc)).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + 'Z') \ No newline at end of file + print((datetime.datetime.now(datetime.timezone.utc)).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + 'Z') +