dtlpy 1.115.44__py3-none-any.whl → 1.117.6__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dtlpy/__init__.py +491 -491
- dtlpy/__version__.py +1 -1
- dtlpy/assets/__init__.py +26 -26
- dtlpy/assets/code_server/config.yaml +2 -2
- dtlpy/assets/code_server/installation.sh +24 -24
- dtlpy/assets/code_server/launch.json +13 -13
- dtlpy/assets/code_server/settings.json +2 -2
- dtlpy/assets/main.py +53 -53
- dtlpy/assets/main_partial.py +18 -18
- dtlpy/assets/mock.json +11 -11
- dtlpy/assets/model_adapter.py +83 -83
- dtlpy/assets/package.json +61 -61
- dtlpy/assets/package_catalog.json +29 -29
- dtlpy/assets/package_gitignore +307 -307
- dtlpy/assets/service_runners/__init__.py +33 -33
- dtlpy/assets/service_runners/converter.py +96 -96
- dtlpy/assets/service_runners/multi_method.py +49 -49
- dtlpy/assets/service_runners/multi_method_annotation.py +54 -54
- dtlpy/assets/service_runners/multi_method_dataset.py +55 -55
- dtlpy/assets/service_runners/multi_method_item.py +52 -52
- dtlpy/assets/service_runners/multi_method_json.py +52 -52
- dtlpy/assets/service_runners/single_method.py +37 -37
- dtlpy/assets/service_runners/single_method_annotation.py +43 -43
- dtlpy/assets/service_runners/single_method_dataset.py +43 -43
- dtlpy/assets/service_runners/single_method_item.py +41 -41
- dtlpy/assets/service_runners/single_method_json.py +42 -42
- dtlpy/assets/service_runners/single_method_multi_input.py +45 -45
- dtlpy/assets/voc_annotation_template.xml +23 -23
- dtlpy/caches/base_cache.py +32 -32
- dtlpy/caches/cache.py +473 -473
- dtlpy/caches/dl_cache.py +201 -201
- dtlpy/caches/filesystem_cache.py +89 -89
- dtlpy/caches/redis_cache.py +84 -84
- dtlpy/dlp/__init__.py +20 -20
- dtlpy/dlp/cli_utilities.py +367 -367
- dtlpy/dlp/command_executor.py +764 -764
- dtlpy/dlp/dlp +1 -1
- dtlpy/dlp/dlp.bat +1 -1
- dtlpy/dlp/dlp.py +128 -128
- dtlpy/dlp/parser.py +651 -651
- dtlpy/entities/__init__.py +83 -83
- dtlpy/entities/analytic.py +347 -347
- dtlpy/entities/annotation.py +1879 -1879
- dtlpy/entities/annotation_collection.py +699 -699
- dtlpy/entities/annotation_definitions/__init__.py +20 -20
- dtlpy/entities/annotation_definitions/base_annotation_definition.py +100 -100
- dtlpy/entities/annotation_definitions/box.py +195 -195
- dtlpy/entities/annotation_definitions/classification.py +67 -67
- dtlpy/entities/annotation_definitions/comparison.py +72 -72
- dtlpy/entities/annotation_definitions/cube.py +204 -204
- dtlpy/entities/annotation_definitions/cube_3d.py +149 -149
- dtlpy/entities/annotation_definitions/description.py +32 -32
- dtlpy/entities/annotation_definitions/ellipse.py +124 -124
- dtlpy/entities/annotation_definitions/free_text.py +62 -62
- dtlpy/entities/annotation_definitions/gis.py +69 -69
- dtlpy/entities/annotation_definitions/note.py +139 -139
- dtlpy/entities/annotation_definitions/point.py +117 -117
- dtlpy/entities/annotation_definitions/polygon.py +182 -182
- dtlpy/entities/annotation_definitions/polyline.py +111 -111
- dtlpy/entities/annotation_definitions/pose.py +92 -92
- dtlpy/entities/annotation_definitions/ref_image.py +86 -86
- dtlpy/entities/annotation_definitions/segmentation.py +240 -240
- dtlpy/entities/annotation_definitions/subtitle.py +34 -34
- dtlpy/entities/annotation_definitions/text.py +85 -85
- dtlpy/entities/annotation_definitions/undefined_annotation.py +74 -74
- dtlpy/entities/app.py +220 -220
- dtlpy/entities/app_module.py +107 -107
- dtlpy/entities/artifact.py +174 -174
- dtlpy/entities/assignment.py +399 -399
- dtlpy/entities/base_entity.py +214 -214
- dtlpy/entities/bot.py +113 -113
- dtlpy/entities/codebase.py +292 -292
- dtlpy/entities/collection.py +38 -38
- dtlpy/entities/command.py +169 -169
- dtlpy/entities/compute.py +449 -449
- dtlpy/entities/dataset.py +1299 -1299
- dtlpy/entities/directory_tree.py +44 -44
- dtlpy/entities/dpk.py +470 -470
- dtlpy/entities/driver.py +235 -235
- dtlpy/entities/execution.py +397 -397
- dtlpy/entities/feature.py +124 -124
- dtlpy/entities/feature_set.py +152 -145
- dtlpy/entities/filters.py +798 -798
- dtlpy/entities/gis_item.py +107 -107
- dtlpy/entities/integration.py +184 -184
- dtlpy/entities/item.py +975 -959
- dtlpy/entities/label.py +123 -123
- dtlpy/entities/links.py +85 -85
- dtlpy/entities/message.py +175 -175
- dtlpy/entities/model.py +684 -684
- dtlpy/entities/node.py +1005 -1005
- dtlpy/entities/ontology.py +810 -803
- dtlpy/entities/organization.py +287 -287
- dtlpy/entities/package.py +657 -657
- dtlpy/entities/package_defaults.py +5 -5
- dtlpy/entities/package_function.py +185 -185
- dtlpy/entities/package_module.py +113 -113
- dtlpy/entities/package_slot.py +118 -118
- dtlpy/entities/paged_entities.py +299 -299
- dtlpy/entities/pipeline.py +624 -624
- dtlpy/entities/pipeline_execution.py +279 -279
- dtlpy/entities/project.py +394 -394
- dtlpy/entities/prompt_item.py +505 -505
- dtlpy/entities/recipe.py +301 -301
- dtlpy/entities/reflect_dict.py +102 -102
- dtlpy/entities/resource_execution.py +138 -138
- dtlpy/entities/service.py +974 -963
- dtlpy/entities/service_driver.py +117 -117
- dtlpy/entities/setting.py +294 -294
- dtlpy/entities/task.py +495 -495
- dtlpy/entities/time_series.py +143 -143
- dtlpy/entities/trigger.py +426 -426
- dtlpy/entities/user.py +118 -118
- dtlpy/entities/webhook.py +124 -124
- dtlpy/examples/__init__.py +19 -19
- dtlpy/examples/add_labels.py +135 -135
- dtlpy/examples/add_metadata_to_item.py +21 -21
- dtlpy/examples/annotate_items_using_model.py +65 -65
- dtlpy/examples/annotate_video_using_model_and_tracker.py +75 -75
- dtlpy/examples/annotations_convert_to_voc.py +9 -9
- dtlpy/examples/annotations_convert_to_yolo.py +9 -9
- dtlpy/examples/convert_annotation_types.py +51 -51
- dtlpy/examples/converter.py +143 -143
- dtlpy/examples/copy_annotations.py +22 -22
- dtlpy/examples/copy_folder.py +31 -31
- dtlpy/examples/create_annotations.py +51 -51
- dtlpy/examples/create_video_annotations.py +83 -83
- dtlpy/examples/delete_annotations.py +26 -26
- dtlpy/examples/filters.py +113 -113
- dtlpy/examples/move_item.py +23 -23
- dtlpy/examples/play_video_annotation.py +13 -13
- dtlpy/examples/show_item_and_mask.py +53 -53
- dtlpy/examples/triggers.py +49 -49
- dtlpy/examples/upload_batch_of_items.py +20 -20
- dtlpy/examples/upload_items_and_custom_format_annotations.py +55 -55
- dtlpy/examples/upload_items_with_modalities.py +43 -43
- dtlpy/examples/upload_segmentation_annotations_from_mask_image.py +44 -44
- dtlpy/examples/upload_yolo_format_annotations.py +70 -70
- dtlpy/exceptions.py +125 -125
- dtlpy/miscellaneous/__init__.py +20 -20
- dtlpy/miscellaneous/dict_differ.py +95 -95
- dtlpy/miscellaneous/git_utils.py +217 -217
- dtlpy/miscellaneous/json_utils.py +14 -14
- dtlpy/miscellaneous/list_print.py +105 -105
- dtlpy/miscellaneous/zipping.py +130 -130
- dtlpy/ml/__init__.py +20 -20
- dtlpy/ml/base_feature_extractor_adapter.py +27 -27
- dtlpy/ml/base_model_adapter.py +1287 -1230
- dtlpy/ml/metrics.py +461 -461
- dtlpy/ml/predictions_utils.py +274 -274
- dtlpy/ml/summary_writer.py +57 -57
- dtlpy/ml/train_utils.py +60 -60
- dtlpy/new_instance.py +252 -252
- dtlpy/repositories/__init__.py +56 -56
- dtlpy/repositories/analytics.py +85 -85
- dtlpy/repositories/annotations.py +916 -916
- dtlpy/repositories/apps.py +383 -383
- dtlpy/repositories/artifacts.py +452 -452
- dtlpy/repositories/assignments.py +599 -599
- dtlpy/repositories/bots.py +213 -213
- dtlpy/repositories/codebases.py +559 -559
- dtlpy/repositories/collections.py +332 -332
- dtlpy/repositories/commands.py +152 -152
- dtlpy/repositories/compositions.py +61 -61
- dtlpy/repositories/computes.py +439 -439
- dtlpy/repositories/datasets.py +1585 -1504
- dtlpy/repositories/downloader.py +1157 -923
- dtlpy/repositories/dpks.py +433 -433
- dtlpy/repositories/drivers.py +482 -482
- dtlpy/repositories/executions.py +815 -815
- dtlpy/repositories/feature_sets.py +256 -226
- dtlpy/repositories/features.py +255 -255
- dtlpy/repositories/integrations.py +484 -484
- dtlpy/repositories/items.py +912 -912
- dtlpy/repositories/messages.py +94 -94
- dtlpy/repositories/models.py +1000 -1000
- dtlpy/repositories/nodes.py +80 -80
- dtlpy/repositories/ontologies.py +511 -511
- dtlpy/repositories/organizations.py +525 -525
- dtlpy/repositories/packages.py +1941 -1941
- dtlpy/repositories/pipeline_executions.py +451 -451
- dtlpy/repositories/pipelines.py +640 -640
- dtlpy/repositories/projects.py +539 -539
- dtlpy/repositories/recipes.py +429 -399
- dtlpy/repositories/resource_executions.py +137 -137
- dtlpy/repositories/schema.py +120 -120
- dtlpy/repositories/service_drivers.py +213 -213
- dtlpy/repositories/services.py +1704 -1704
- dtlpy/repositories/settings.py +339 -339
- dtlpy/repositories/tasks.py +1477 -1477
- dtlpy/repositories/times_series.py +278 -278
- dtlpy/repositories/triggers.py +536 -536
- dtlpy/repositories/upload_element.py +257 -257
- dtlpy/repositories/uploader.py +661 -661
- dtlpy/repositories/webhooks.py +249 -249
- dtlpy/services/__init__.py +22 -22
- dtlpy/services/aihttp_retry.py +131 -131
- dtlpy/services/api_client.py +1786 -1785
- dtlpy/services/api_reference.py +40 -40
- dtlpy/services/async_utils.py +133 -133
- dtlpy/services/calls_counter.py +44 -44
- dtlpy/services/check_sdk.py +68 -68
- dtlpy/services/cookie.py +115 -115
- dtlpy/services/create_logger.py +156 -156
- dtlpy/services/events.py +84 -84
- dtlpy/services/logins.py +235 -235
- dtlpy/services/reporter.py +256 -256
- dtlpy/services/service_defaults.py +91 -91
- dtlpy/utilities/__init__.py +20 -20
- dtlpy/utilities/annotations/__init__.py +16 -16
- dtlpy/utilities/annotations/annotation_converters.py +269 -269
- dtlpy/utilities/base_package_runner.py +285 -264
- dtlpy/utilities/converter.py +1650 -1650
- dtlpy/utilities/dataset_generators/__init__.py +1 -1
- dtlpy/utilities/dataset_generators/dataset_generator.py +670 -670
- dtlpy/utilities/dataset_generators/dataset_generator_tensorflow.py +23 -23
- dtlpy/utilities/dataset_generators/dataset_generator_torch.py +21 -21
- dtlpy/utilities/local_development/__init__.py +1 -1
- dtlpy/utilities/local_development/local_session.py +179 -179
- dtlpy/utilities/reports/__init__.py +2 -2
- dtlpy/utilities/reports/figures.py +343 -343
- dtlpy/utilities/reports/report.py +71 -71
- dtlpy/utilities/videos/__init__.py +17 -17
- dtlpy/utilities/videos/video_player.py +598 -598
- dtlpy/utilities/videos/videos.py +470 -470
- {dtlpy-1.115.44.data → dtlpy-1.117.6.data}/scripts/dlp +1 -1
- dtlpy-1.117.6.data/scripts/dlp.bat +2 -0
- {dtlpy-1.115.44.data → dtlpy-1.117.6.data}/scripts/dlp.py +128 -128
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/METADATA +186 -186
- dtlpy-1.117.6.dist-info/RECORD +239 -0
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/WHEEL +1 -1
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/licenses/LICENSE +200 -200
- tests/features/environment.py +551 -551
- dtlpy/assets/__pycache__/__init__.cpython-310.pyc +0 -0
- dtlpy-1.115.44.data/scripts/dlp.bat +0 -2
- dtlpy-1.115.44.dist-info/RECORD +0 -240
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/entry_points.txt +0 -0
- {dtlpy-1.115.44.dist-info → dtlpy-1.117.6.dist-info}/top_level.txt +0 -0
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
from .base_annotation_definition import BaseAnnotationDefinition
|
|
2
|
-
from .box import Box
|
|
3
|
-
from .cube import Cube
|
|
4
|
-
from .cube_3d import Cube3d
|
|
5
|
-
from .note import Note, Message
|
|
6
|
-
from .classification import Classification
|
|
7
|
-
from .comparison import Comparison
|
|
8
|
-
from .ellipse import Ellipse
|
|
9
|
-
from .point import Point
|
|
10
|
-
from .polygon import Polygon
|
|
11
|
-
from .polyline import Polyline
|
|
12
|
-
from .segmentation import Segmentation
|
|
13
|
-
from .subtitle import Subtitle
|
|
14
|
-
from .description import Description
|
|
15
|
-
from .undefined_annotation import UndefinedAnnotationType
|
|
16
|
-
from .pose import Pose
|
|
17
|
-
from .text import Text
|
|
18
|
-
from .free_text import FreeText
|
|
19
|
-
from .ref_image import RefImage
|
|
20
|
-
from .gis import Gis, GisType
|
|
1
|
+
from .base_annotation_definition import BaseAnnotationDefinition
|
|
2
|
+
from .box import Box
|
|
3
|
+
from .cube import Cube
|
|
4
|
+
from .cube_3d import Cube3d
|
|
5
|
+
from .note import Note, Message
|
|
6
|
+
from .classification import Classification
|
|
7
|
+
from .comparison import Comparison
|
|
8
|
+
from .ellipse import Ellipse
|
|
9
|
+
from .point import Point
|
|
10
|
+
from .polygon import Polygon
|
|
11
|
+
from .polyline import Polyline
|
|
12
|
+
from .segmentation import Segmentation
|
|
13
|
+
from .subtitle import Subtitle
|
|
14
|
+
from .description import Description
|
|
15
|
+
from .undefined_annotation import UndefinedAnnotationType
|
|
16
|
+
from .pose import Pose
|
|
17
|
+
from .text import Text
|
|
18
|
+
from .free_text import FreeText
|
|
19
|
+
from .ref_image import RefImage
|
|
20
|
+
from .gis import Gis, GisType
|
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import numpy as np
|
|
3
|
-
import warnings
|
|
4
|
-
|
|
5
|
-
logger = logging.getLogger(name='dtlpy')
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class BaseAnnotationDefinition:
|
|
9
|
-
def __init__(self, description=None, attributes=None):
|
|
10
|
-
self.description = description
|
|
11
|
-
self._top = 0
|
|
12
|
-
self._left = 0
|
|
13
|
-
self._bottom = 0
|
|
14
|
-
self._right = 0
|
|
15
|
-
self._annotation = None
|
|
16
|
-
if attributes and not isinstance(attributes, dict):
|
|
17
|
-
raise TypeError('attributes should be a dictionary')
|
|
18
|
-
self._attributes = attributes or {}
|
|
19
|
-
|
|
20
|
-
@property
|
|
21
|
-
def attributes(self):
|
|
22
|
-
return self._attributes
|
|
23
|
-
|
|
24
|
-
@attributes.setter
|
|
25
|
-
def attributes(self, v):
|
|
26
|
-
if v and not isinstance(v, dict):
|
|
27
|
-
raise TypeError('attributes should be a dictionary')
|
|
28
|
-
self._attributes = v
|
|
29
|
-
|
|
30
|
-
@property
|
|
31
|
-
def top(self):
|
|
32
|
-
return self._top
|
|
33
|
-
|
|
34
|
-
@top.setter
|
|
35
|
-
def top(self, v):
|
|
36
|
-
self._top = v
|
|
37
|
-
|
|
38
|
-
@property
|
|
39
|
-
def left(self):
|
|
40
|
-
return self._left
|
|
41
|
-
|
|
42
|
-
@left.setter
|
|
43
|
-
def left(self, v):
|
|
44
|
-
self._left = v
|
|
45
|
-
|
|
46
|
-
@property
|
|
47
|
-
def bottom(self):
|
|
48
|
-
return self._bottom
|
|
49
|
-
|
|
50
|
-
@bottom.setter
|
|
51
|
-
def bottom(self, v):
|
|
52
|
-
self._bottom = v
|
|
53
|
-
|
|
54
|
-
@property
|
|
55
|
-
def right(self):
|
|
56
|
-
return self._right
|
|
57
|
-
|
|
58
|
-
@right.setter
|
|
59
|
-
def right(self, v):
|
|
60
|
-
self._right = v
|
|
61
|
-
|
|
62
|
-
@property
|
|
63
|
-
def height(self):
|
|
64
|
-
return np.round(self.bottom - self.top)
|
|
65
|
-
|
|
66
|
-
@property
|
|
67
|
-
def width(self):
|
|
68
|
-
return np.round(self.right - self.left)
|
|
69
|
-
|
|
70
|
-
@staticmethod
|
|
71
|
-
def add_text_to_image(image, annotation):
|
|
72
|
-
"""
|
|
73
|
-
:param image:
|
|
74
|
-
:param annotation:
|
|
75
|
-
"""
|
|
76
|
-
try:
|
|
77
|
-
import cv2
|
|
78
|
-
except (ImportError, ModuleNotFoundError):
|
|
79
|
-
logger.error(
|
|
80
|
-
'Import Error! Cant import cv2. Annotations operations will be limited. import manually and fix errors')
|
|
81
|
-
raise
|
|
82
|
-
|
|
83
|
-
text = '{label}-{attributes}'.format(label=annotation.label, attributes=','.join(annotation.attributes))
|
|
84
|
-
top = annotation.top
|
|
85
|
-
left = annotation.left
|
|
86
|
-
if top == 0:
|
|
87
|
-
top = image.shape[0] / 10
|
|
88
|
-
if left == 0:
|
|
89
|
-
left = image.shape[1] / 10
|
|
90
|
-
return cv2.putText(img=image,
|
|
91
|
-
text=text,
|
|
92
|
-
org=tuple([int(np.round(left)), int(np.round(top))]),
|
|
93
|
-
color=(255, 0, 0),
|
|
94
|
-
fontFace=cv2.FONT_HERSHEY_DUPLEX,
|
|
95
|
-
fontScale=1,
|
|
96
|
-
thickness=2)
|
|
97
|
-
|
|
98
|
-
@property
|
|
99
|
-
def logger(self):
|
|
100
|
-
return logger
|
|
1
|
+
import logging
|
|
2
|
+
import numpy as np
|
|
3
|
+
import warnings
|
|
4
|
+
|
|
5
|
+
logger = logging.getLogger(name='dtlpy')
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BaseAnnotationDefinition:
|
|
9
|
+
def __init__(self, description=None, attributes=None):
|
|
10
|
+
self.description = description
|
|
11
|
+
self._top = 0
|
|
12
|
+
self._left = 0
|
|
13
|
+
self._bottom = 0
|
|
14
|
+
self._right = 0
|
|
15
|
+
self._annotation = None
|
|
16
|
+
if attributes and not isinstance(attributes, dict):
|
|
17
|
+
raise TypeError('attributes should be a dictionary')
|
|
18
|
+
self._attributes = attributes or {}
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def attributes(self):
|
|
22
|
+
return self._attributes
|
|
23
|
+
|
|
24
|
+
@attributes.setter
|
|
25
|
+
def attributes(self, v):
|
|
26
|
+
if v and not isinstance(v, dict):
|
|
27
|
+
raise TypeError('attributes should be a dictionary')
|
|
28
|
+
self._attributes = v
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def top(self):
|
|
32
|
+
return self._top
|
|
33
|
+
|
|
34
|
+
@top.setter
|
|
35
|
+
def top(self, v):
|
|
36
|
+
self._top = v
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def left(self):
|
|
40
|
+
return self._left
|
|
41
|
+
|
|
42
|
+
@left.setter
|
|
43
|
+
def left(self, v):
|
|
44
|
+
self._left = v
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def bottom(self):
|
|
48
|
+
return self._bottom
|
|
49
|
+
|
|
50
|
+
@bottom.setter
|
|
51
|
+
def bottom(self, v):
|
|
52
|
+
self._bottom = v
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def right(self):
|
|
56
|
+
return self._right
|
|
57
|
+
|
|
58
|
+
@right.setter
|
|
59
|
+
def right(self, v):
|
|
60
|
+
self._right = v
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def height(self):
|
|
64
|
+
return np.round(self.bottom - self.top)
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def width(self):
|
|
68
|
+
return np.round(self.right - self.left)
|
|
69
|
+
|
|
70
|
+
@staticmethod
|
|
71
|
+
def add_text_to_image(image, annotation):
|
|
72
|
+
"""
|
|
73
|
+
:param image:
|
|
74
|
+
:param annotation:
|
|
75
|
+
"""
|
|
76
|
+
try:
|
|
77
|
+
import cv2
|
|
78
|
+
except (ImportError, ModuleNotFoundError):
|
|
79
|
+
logger.error(
|
|
80
|
+
'Import Error! Cant import cv2. Annotations operations will be limited. import manually and fix errors')
|
|
81
|
+
raise
|
|
82
|
+
|
|
83
|
+
text = '{label}-{attributes}'.format(label=annotation.label, attributes=','.join(annotation.attributes))
|
|
84
|
+
top = annotation.top
|
|
85
|
+
left = annotation.left
|
|
86
|
+
if top == 0:
|
|
87
|
+
top = image.shape[0] / 10
|
|
88
|
+
if left == 0:
|
|
89
|
+
left = image.shape[1] / 10
|
|
90
|
+
return cv2.putText(img=image,
|
|
91
|
+
text=text,
|
|
92
|
+
org=tuple([int(np.round(left)), int(np.round(top))]),
|
|
93
|
+
color=(255, 0, 0),
|
|
94
|
+
fontFace=cv2.FONT_HERSHEY_DUPLEX,
|
|
95
|
+
fontScale=1,
|
|
96
|
+
thickness=2)
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def logger(self):
|
|
100
|
+
return logger
|
|
@@ -1,195 +1,195 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
from . import BaseAnnotationDefinition
|
|
3
|
-
from .polygon import Polygon
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Box(BaseAnnotationDefinition):
|
|
7
|
-
"""
|
|
8
|
-
Box annotation object
|
|
9
|
-
Can create a box using 2 point using: "top", "left", "bottom", "right" (to form a box [(left, top), (right, bottom)])
|
|
10
|
-
For rotated box add the "angel"
|
|
11
|
-
"""
|
|
12
|
-
type = "box"
|
|
13
|
-
|
|
14
|
-
def __init__(self,
|
|
15
|
-
left=None, top=None, right=None, bottom=None,
|
|
16
|
-
label=None, attributes=None, description=None, angle=None):
|
|
17
|
-
"""
|
|
18
|
-
Can create a box using 2 point using:
|
|
19
|
-
"top", "left", "bottom", "right" (to form a box [(left, top), (right, bottom)])
|
|
20
|
-
And for create a rotated box need to add the angle of the rotation
|
|
21
|
-
|
|
22
|
-
:param left: left x coordinate of the box
|
|
23
|
-
:param top: top Y coordinate of the box
|
|
24
|
-
:param right: right x coordinate of the box
|
|
25
|
-
:param bottom: bottom Y coordinate of the box
|
|
26
|
-
:param label: annotation label
|
|
27
|
-
:param attributes: a list of attributes for the annotation
|
|
28
|
-
:param description:
|
|
29
|
-
:param angle: the angle of the rotation in degrees
|
|
30
|
-
|
|
31
|
-
:return:
|
|
32
|
-
"""
|
|
33
|
-
super().__init__(description=description, attributes=attributes)
|
|
34
|
-
|
|
35
|
-
self.angle = angle
|
|
36
|
-
self.left = left
|
|
37
|
-
self.top = top
|
|
38
|
-
self.right = right
|
|
39
|
-
self.bottom = bottom
|
|
40
|
-
self.top_left = [left, top]
|
|
41
|
-
self.top_right = [right, top]
|
|
42
|
-
self.bottom_left = [left, bottom]
|
|
43
|
-
self.bottom_right = [right, bottom]
|
|
44
|
-
self.label = label
|
|
45
|
-
|
|
46
|
-
@property
|
|
47
|
-
def x(self):
|
|
48
|
-
return [self.left, self.right]
|
|
49
|
-
|
|
50
|
-
@property
|
|
51
|
-
def y(self):
|
|
52
|
-
return [self.top, self.bottom]
|
|
53
|
-
|
|
54
|
-
@property
|
|
55
|
-
def geo(self):
|
|
56
|
-
return [
|
|
57
|
-
[self.left, self.top],
|
|
58
|
-
[self.right, self.bottom]
|
|
59
|
-
]
|
|
60
|
-
|
|
61
|
-
@property
|
|
62
|
-
def four_points(self):
|
|
63
|
-
return [self.top_left, self.bottom_left, self.bottom_right, self.top_right]
|
|
64
|
-
|
|
65
|
-
def show(self, image, thickness, with_text, height, width, annotation_format, color, alpha=1):
|
|
66
|
-
"""
|
|
67
|
-
Show annotation as ndarray
|
|
68
|
-
:param image: empty or image to draw on
|
|
69
|
-
:param thickness:
|
|
70
|
-
:param with_text: not required
|
|
71
|
-
:param height: item height
|
|
72
|
-
:param width: item width
|
|
73
|
-
:param annotation_format: options: list(dl.ViewAnnotationOptions)
|
|
74
|
-
:param color: color
|
|
75
|
-
:param alpha: opacity value [0 1], default 1
|
|
76
|
-
:return: ndarray
|
|
77
|
-
"""
|
|
78
|
-
try:
|
|
79
|
-
import cv2
|
|
80
|
-
except (ImportError, ModuleNotFoundError):
|
|
81
|
-
self.logger.error(
|
|
82
|
-
'Import Error! Cant import cv2. Annotations operations will be limited. import manually and fix errors')
|
|
83
|
-
raise
|
|
84
|
-
|
|
85
|
-
if thickness is None:
|
|
86
|
-
thickness = 2
|
|
87
|
-
|
|
88
|
-
# draw annotation
|
|
89
|
-
points = self.four_points
|
|
90
|
-
|
|
91
|
-
# create image to draw on
|
|
92
|
-
if alpha != 1:
|
|
93
|
-
overlay = image.copy()
|
|
94
|
-
else:
|
|
95
|
-
overlay = image
|
|
96
|
-
|
|
97
|
-
# draw annotation
|
|
98
|
-
overlay = cv2.drawContours(
|
|
99
|
-
image=overlay,
|
|
100
|
-
contours=[np.round(points).astype(int)],
|
|
101
|
-
contourIdx=-1,
|
|
102
|
-
color=color,
|
|
103
|
-
thickness=thickness,
|
|
104
|
-
lineType=cv2.LINE_AA
|
|
105
|
-
)
|
|
106
|
-
|
|
107
|
-
if not isinstance(color, int) and len(color) == 4 and color[3] != 255:
|
|
108
|
-
# add with opacity
|
|
109
|
-
image = cv2.addWeighted(src1=overlay,
|
|
110
|
-
alpha=alpha,
|
|
111
|
-
src2=image,
|
|
112
|
-
beta=1 - alpha,
|
|
113
|
-
gamma=0)
|
|
114
|
-
else:
|
|
115
|
-
image = overlay
|
|
116
|
-
|
|
117
|
-
if with_text:
|
|
118
|
-
image = self.add_text_to_image(image=image, annotation=self)
|
|
119
|
-
return image
|
|
120
|
-
|
|
121
|
-
def to_coordinates(self, color):
|
|
122
|
-
points = [
|
|
123
|
-
[self.left, self.top],
|
|
124
|
-
[self.right, self.bottom]
|
|
125
|
-
]
|
|
126
|
-
pts = [{"x": float(x), "y": float(y), "z": 0} for x, y in points]
|
|
127
|
-
|
|
128
|
-
if self.angle is not None and self.angle != 0:
|
|
129
|
-
pts.append(self.angle)
|
|
130
|
-
|
|
131
|
-
return pts
|
|
132
|
-
|
|
133
|
-
@staticmethod
|
|
134
|
-
def from_coordinates(coordinates):
|
|
135
|
-
return np.asarray([[pt["x"], pt["y"]] for pt in coordinates[:2]])
|
|
136
|
-
|
|
137
|
-
@classmethod
|
|
138
|
-
def from_json(cls, _json):
|
|
139
|
-
coordinates = _json.get("coordinates", None) if "coordinates" in _json else _json.get("data", None)
|
|
140
|
-
if coordinates is None:
|
|
141
|
-
raise ValueError('can not find "coordinates" or "data" in annotation. id: {}'.format(_json["id"]))
|
|
142
|
-
|
|
143
|
-
geo = cls.from_coordinates(coordinates=coordinates)
|
|
144
|
-
|
|
145
|
-
left = np.min(geo[:, 0])
|
|
146
|
-
top = np.min(geo[:, 1])
|
|
147
|
-
right = np.max(geo[:, 0])
|
|
148
|
-
bottom = np.max(geo[:, 1])
|
|
149
|
-
|
|
150
|
-
angel = coordinates[2] if len(coordinates) > 2 and (
|
|
151
|
-
isinstance(coordinates[2], float) or isinstance(coordinates[2], int)) else None
|
|
152
|
-
|
|
153
|
-
return cls(
|
|
154
|
-
left=left,
|
|
155
|
-
top=top,
|
|
156
|
-
right=right,
|
|
157
|
-
bottom=bottom,
|
|
158
|
-
label=_json["label"],
|
|
159
|
-
attributes=_json.get("attributes", None),
|
|
160
|
-
angle=angel
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
@classmethod
|
|
164
|
-
def from_segmentation(cls, mask, label, attributes=None):
|
|
165
|
-
"""
|
|
166
|
-
Convert binary mask to Polygon
|
|
167
|
-
|
|
168
|
-
:param mask: binary mask (0,1)
|
|
169
|
-
:param label: annotation label
|
|
170
|
-
:param attributes: annotations list of attributes
|
|
171
|
-
|
|
172
|
-
:return: Box annotations list to each separated segmentation
|
|
173
|
-
"""
|
|
174
|
-
polygons = Polygon.from_segmentation(
|
|
175
|
-
mask=mask,
|
|
176
|
-
label=label,
|
|
177
|
-
attributes=attributes,
|
|
178
|
-
max_instances=None
|
|
179
|
-
)
|
|
180
|
-
|
|
181
|
-
if not isinstance(polygons, list):
|
|
182
|
-
polygons = [polygons]
|
|
183
|
-
|
|
184
|
-
boxes = [
|
|
185
|
-
cls(
|
|
186
|
-
left=polygon.left,
|
|
187
|
-
top=polygon.top,
|
|
188
|
-
right=polygon.right,
|
|
189
|
-
bottom=polygon.bottom,
|
|
190
|
-
label=label,
|
|
191
|
-
attributes=attributes
|
|
192
|
-
) for polygon in polygons
|
|
193
|
-
]
|
|
194
|
-
|
|
195
|
-
return boxes
|
|
1
|
+
import numpy as np
|
|
2
|
+
from . import BaseAnnotationDefinition
|
|
3
|
+
from .polygon import Polygon
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Box(BaseAnnotationDefinition):
|
|
7
|
+
"""
|
|
8
|
+
Box annotation object
|
|
9
|
+
Can create a box using 2 point using: "top", "left", "bottom", "right" (to form a box [(left, top), (right, bottom)])
|
|
10
|
+
For rotated box add the "angel"
|
|
11
|
+
"""
|
|
12
|
+
type = "box"
|
|
13
|
+
|
|
14
|
+
def __init__(self,
|
|
15
|
+
left=None, top=None, right=None, bottom=None,
|
|
16
|
+
label=None, attributes=None, description=None, angle=None):
|
|
17
|
+
"""
|
|
18
|
+
Can create a box using 2 point using:
|
|
19
|
+
"top", "left", "bottom", "right" (to form a box [(left, top), (right, bottom)])
|
|
20
|
+
And for create a rotated box need to add the angle of the rotation
|
|
21
|
+
|
|
22
|
+
:param left: left x coordinate of the box
|
|
23
|
+
:param top: top Y coordinate of the box
|
|
24
|
+
:param right: right x coordinate of the box
|
|
25
|
+
:param bottom: bottom Y coordinate of the box
|
|
26
|
+
:param label: annotation label
|
|
27
|
+
:param attributes: a list of attributes for the annotation
|
|
28
|
+
:param description:
|
|
29
|
+
:param angle: the angle of the rotation in degrees
|
|
30
|
+
|
|
31
|
+
:return:
|
|
32
|
+
"""
|
|
33
|
+
super().__init__(description=description, attributes=attributes)
|
|
34
|
+
|
|
35
|
+
self.angle = angle
|
|
36
|
+
self.left = left
|
|
37
|
+
self.top = top
|
|
38
|
+
self.right = right
|
|
39
|
+
self.bottom = bottom
|
|
40
|
+
self.top_left = [left, top]
|
|
41
|
+
self.top_right = [right, top]
|
|
42
|
+
self.bottom_left = [left, bottom]
|
|
43
|
+
self.bottom_right = [right, bottom]
|
|
44
|
+
self.label = label
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def x(self):
|
|
48
|
+
return [self.left, self.right]
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def y(self):
|
|
52
|
+
return [self.top, self.bottom]
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def geo(self):
|
|
56
|
+
return [
|
|
57
|
+
[self.left, self.top],
|
|
58
|
+
[self.right, self.bottom]
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def four_points(self):
|
|
63
|
+
return [self.top_left, self.bottom_left, self.bottom_right, self.top_right]
|
|
64
|
+
|
|
65
|
+
def show(self, image, thickness, with_text, height, width, annotation_format, color, alpha=1):
|
|
66
|
+
"""
|
|
67
|
+
Show annotation as ndarray
|
|
68
|
+
:param image: empty or image to draw on
|
|
69
|
+
:param thickness:
|
|
70
|
+
:param with_text: not required
|
|
71
|
+
:param height: item height
|
|
72
|
+
:param width: item width
|
|
73
|
+
:param annotation_format: options: list(dl.ViewAnnotationOptions)
|
|
74
|
+
:param color: color
|
|
75
|
+
:param alpha: opacity value [0 1], default 1
|
|
76
|
+
:return: ndarray
|
|
77
|
+
"""
|
|
78
|
+
try:
|
|
79
|
+
import cv2
|
|
80
|
+
except (ImportError, ModuleNotFoundError):
|
|
81
|
+
self.logger.error(
|
|
82
|
+
'Import Error! Cant import cv2. Annotations operations will be limited. import manually and fix errors')
|
|
83
|
+
raise
|
|
84
|
+
|
|
85
|
+
if thickness is None:
|
|
86
|
+
thickness = 2
|
|
87
|
+
|
|
88
|
+
# draw annotation
|
|
89
|
+
points = self.four_points
|
|
90
|
+
|
|
91
|
+
# create image to draw on
|
|
92
|
+
if alpha != 1:
|
|
93
|
+
overlay = image.copy()
|
|
94
|
+
else:
|
|
95
|
+
overlay = image
|
|
96
|
+
|
|
97
|
+
# draw annotation
|
|
98
|
+
overlay = cv2.drawContours(
|
|
99
|
+
image=overlay,
|
|
100
|
+
contours=[np.round(points).astype(int)],
|
|
101
|
+
contourIdx=-1,
|
|
102
|
+
color=color,
|
|
103
|
+
thickness=thickness,
|
|
104
|
+
lineType=cv2.LINE_AA
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
if not isinstance(color, int) and len(color) == 4 and color[3] != 255:
|
|
108
|
+
# add with opacity
|
|
109
|
+
image = cv2.addWeighted(src1=overlay,
|
|
110
|
+
alpha=alpha,
|
|
111
|
+
src2=image,
|
|
112
|
+
beta=1 - alpha,
|
|
113
|
+
gamma=0)
|
|
114
|
+
else:
|
|
115
|
+
image = overlay
|
|
116
|
+
|
|
117
|
+
if with_text:
|
|
118
|
+
image = self.add_text_to_image(image=image, annotation=self)
|
|
119
|
+
return image
|
|
120
|
+
|
|
121
|
+
def to_coordinates(self, color):
|
|
122
|
+
points = [
|
|
123
|
+
[self.left, self.top],
|
|
124
|
+
[self.right, self.bottom]
|
|
125
|
+
]
|
|
126
|
+
pts = [{"x": float(x), "y": float(y), "z": 0} for x, y in points]
|
|
127
|
+
|
|
128
|
+
if self.angle is not None and self.angle != 0:
|
|
129
|
+
pts.append(self.angle)
|
|
130
|
+
|
|
131
|
+
return pts
|
|
132
|
+
|
|
133
|
+
@staticmethod
|
|
134
|
+
def from_coordinates(coordinates):
|
|
135
|
+
return np.asarray([[pt["x"], pt["y"]] for pt in coordinates[:2]])
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def from_json(cls, _json):
|
|
139
|
+
coordinates = _json.get("coordinates", None) if "coordinates" in _json else _json.get("data", None)
|
|
140
|
+
if coordinates is None:
|
|
141
|
+
raise ValueError('can not find "coordinates" or "data" in annotation. id: {}'.format(_json["id"]))
|
|
142
|
+
|
|
143
|
+
geo = cls.from_coordinates(coordinates=coordinates)
|
|
144
|
+
|
|
145
|
+
left = np.min(geo[:, 0])
|
|
146
|
+
top = np.min(geo[:, 1])
|
|
147
|
+
right = np.max(geo[:, 0])
|
|
148
|
+
bottom = np.max(geo[:, 1])
|
|
149
|
+
|
|
150
|
+
angel = coordinates[2] if len(coordinates) > 2 and (
|
|
151
|
+
isinstance(coordinates[2], float) or isinstance(coordinates[2], int)) else None
|
|
152
|
+
|
|
153
|
+
return cls(
|
|
154
|
+
left=left,
|
|
155
|
+
top=top,
|
|
156
|
+
right=right,
|
|
157
|
+
bottom=bottom,
|
|
158
|
+
label=_json["label"],
|
|
159
|
+
attributes=_json.get("attributes", None),
|
|
160
|
+
angle=angel
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
@classmethod
|
|
164
|
+
def from_segmentation(cls, mask, label, attributes=None):
|
|
165
|
+
"""
|
|
166
|
+
Convert binary mask to Polygon
|
|
167
|
+
|
|
168
|
+
:param mask: binary mask (0,1)
|
|
169
|
+
:param label: annotation label
|
|
170
|
+
:param attributes: annotations list of attributes
|
|
171
|
+
|
|
172
|
+
:return: Box annotations list to each separated segmentation
|
|
173
|
+
"""
|
|
174
|
+
polygons = Polygon.from_segmentation(
|
|
175
|
+
mask=mask,
|
|
176
|
+
label=label,
|
|
177
|
+
attributes=attributes,
|
|
178
|
+
max_instances=None
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
if not isinstance(polygons, list):
|
|
182
|
+
polygons = [polygons]
|
|
183
|
+
|
|
184
|
+
boxes = [
|
|
185
|
+
cls(
|
|
186
|
+
left=polygon.left,
|
|
187
|
+
top=polygon.top,
|
|
188
|
+
right=polygon.right,
|
|
189
|
+
bottom=polygon.bottom,
|
|
190
|
+
label=label,
|
|
191
|
+
attributes=attributes
|
|
192
|
+
) for polygon in polygons
|
|
193
|
+
]
|
|
194
|
+
|
|
195
|
+
return boxes
|