supervisely 6.73.420__py3-none-any.whl → 6.73.421__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.
Files changed (76) hide show
  1. supervisely/api/api.py +10 -5
  2. supervisely/api/app_api.py +71 -4
  3. supervisely/api/module_api.py +4 -0
  4. supervisely/api/nn/deploy_api.py +15 -9
  5. supervisely/api/nn/ecosystem_models_api.py +201 -0
  6. supervisely/api/nn/neural_network_api.py +12 -3
  7. supervisely/api/project_api.py +35 -6
  8. supervisely/api/task_api.py +5 -1
  9. supervisely/app/widgets/__init__.py +8 -1
  10. supervisely/app/widgets/agent_selector/template.html +1 -0
  11. supervisely/app/widgets/deploy_model/__init__.py +0 -0
  12. supervisely/app/widgets/deploy_model/deploy_model.py +729 -0
  13. supervisely/app/widgets/dropdown_checkbox_selector/__init__.py +0 -0
  14. supervisely/app/widgets/dropdown_checkbox_selector/dropdown_checkbox_selector.py +87 -0
  15. supervisely/app/widgets/dropdown_checkbox_selector/template.html +12 -0
  16. supervisely/app/widgets/ecosystem_model_selector/__init__.py +0 -0
  17. supervisely/app/widgets/ecosystem_model_selector/ecosystem_model_selector.py +190 -0
  18. supervisely/app/widgets/experiment_selector/experiment_selector.py +447 -264
  19. supervisely/app/widgets/fast_table/fast_table.py +402 -74
  20. supervisely/app/widgets/fast_table/script.js +364 -96
  21. supervisely/app/widgets/fast_table/style.css +24 -0
  22. supervisely/app/widgets/fast_table/template.html +43 -3
  23. supervisely/app/widgets/radio_table/radio_table.py +10 -2
  24. supervisely/app/widgets/select/select.py +6 -4
  25. supervisely/app/widgets/select_dataset_tree/select_dataset_tree.py +18 -0
  26. supervisely/app/widgets/tabs/tabs.py +22 -6
  27. supervisely/app/widgets/tabs/template.html +5 -1
  28. supervisely/nn/artifacts/__init__.py +1 -1
  29. supervisely/nn/artifacts/artifacts.py +10 -2
  30. supervisely/nn/artifacts/detectron2.py +1 -0
  31. supervisely/nn/artifacts/hrda.py +1 -0
  32. supervisely/nn/artifacts/mmclassification.py +20 -0
  33. supervisely/nn/artifacts/mmdetection.py +5 -3
  34. supervisely/nn/artifacts/mmsegmentation.py +1 -0
  35. supervisely/nn/artifacts/ritm.py +1 -0
  36. supervisely/nn/artifacts/rtdetr.py +1 -0
  37. supervisely/nn/artifacts/unet.py +1 -0
  38. supervisely/nn/artifacts/utils.py +3 -0
  39. supervisely/nn/artifacts/yolov5.py +2 -0
  40. supervisely/nn/artifacts/yolov8.py +1 -0
  41. supervisely/nn/benchmark/semantic_segmentation/metric_provider.py +18 -18
  42. supervisely/nn/experiments.py +9 -0
  43. supervisely/nn/inference/gui/serving_gui_template.py +39 -13
  44. supervisely/nn/inference/inference.py +160 -94
  45. supervisely/nn/inference/predict_app/__init__.py +0 -0
  46. supervisely/nn/inference/predict_app/gui/__init__.py +0 -0
  47. supervisely/nn/inference/predict_app/gui/classes_selector.py +91 -0
  48. supervisely/nn/inference/predict_app/gui/gui.py +710 -0
  49. supervisely/nn/inference/predict_app/gui/input_selector.py +165 -0
  50. supervisely/nn/inference/predict_app/gui/model_selector.py +79 -0
  51. supervisely/nn/inference/predict_app/gui/output_selector.py +139 -0
  52. supervisely/nn/inference/predict_app/gui/preview.py +93 -0
  53. supervisely/nn/inference/predict_app/gui/settings_selector.py +184 -0
  54. supervisely/nn/inference/predict_app/gui/tags_selector.py +110 -0
  55. supervisely/nn/inference/predict_app/gui/utils.py +282 -0
  56. supervisely/nn/inference/predict_app/predict_app.py +184 -0
  57. supervisely/nn/inference/uploader.py +9 -5
  58. supervisely/nn/model/prediction.py +2 -0
  59. supervisely/nn/model/prediction_session.py +20 -3
  60. supervisely/nn/training/gui/gui.py +131 -44
  61. supervisely/nn/training/gui/model_selector.py +8 -6
  62. supervisely/nn/training/gui/train_val_splits_selector.py +122 -70
  63. supervisely/nn/training/gui/training_artifacts.py +0 -5
  64. supervisely/nn/training/train_app.py +161 -44
  65. supervisely/template/experiment/experiment.html.jinja +74 -17
  66. supervisely/template/experiment/experiment_generator.py +258 -112
  67. supervisely/template/experiment/header.html.jinja +31 -13
  68. supervisely/template/experiment/sly-style.css +7 -2
  69. {supervisely-6.73.420.dist-info → supervisely-6.73.421.dist-info}/METADATA +3 -1
  70. {supervisely-6.73.420.dist-info → supervisely-6.73.421.dist-info}/RECORD +74 -56
  71. supervisely/app/widgets/experiment_selector/style.css +0 -27
  72. supervisely/app/widgets/experiment_selector/template.html +0 -61
  73. {supervisely-6.73.420.dist-info → supervisely-6.73.421.dist-info}/LICENSE +0 -0
  74. {supervisely-6.73.420.dist-info → supervisely-6.73.421.dist-info}/WHEEL +0 -0
  75. {supervisely-6.73.420.dist-info → supervisely-6.73.421.dist-info}/entry_points.txt +0 -0
  76. {supervisely-6.73.420.dist-info → supervisely-6.73.421.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,165 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from supervisely.app.widgets import (
4
+ Button,
5
+ Card,
6
+ Container,
7
+ OneOf,
8
+ RadioGroup,
9
+ RadioTable,
10
+ SelectDatasetTree,
11
+ Text,
12
+ )
13
+ from supervisely.project.project import ProjectType
14
+
15
+
16
+ class InputSelector:
17
+ title = "Select Input"
18
+ description = "Select input data on which to run model for prediction"
19
+ lock_message = None
20
+
21
+ def __init__(self, workspace_id: int):
22
+ # Init Step
23
+ self.workspace_id = workspace_id
24
+ self.display_widgets: List[Any] = []
25
+ # -------------------------------- #
26
+
27
+ # Init Base Widgets
28
+ self.validator_text = None
29
+ self.button = None
30
+ self.container = None
31
+ self.card = None
32
+ # -------------------------------- #
33
+
34
+ # Init Step Widgets
35
+ # Images
36
+ self.select_dataset_for_images = None
37
+ self.select_image_container = None
38
+ # Videos
39
+ self.select_dataset_for_video = None
40
+ self.select_video = None
41
+ self.select_video_container = None
42
+ # Selector
43
+ self.radio = None
44
+ self.one_of = None
45
+ # -------------------------------- #
46
+
47
+ # Images
48
+ self.select_dataset_for_images = SelectDatasetTree(
49
+ multiselect=True,
50
+ flat=True,
51
+ select_all_datasets=False,
52
+ allowed_project_types=[ProjectType.IMAGES],
53
+ always_open=False,
54
+ compact=False,
55
+ team_is_selectable=False,
56
+ workspace_is_selectable=False,
57
+ show_select_all_datasets_checkbox=True,
58
+ )
59
+ self.select_image_container = Container(widgets=[self.select_dataset_for_images])
60
+ self._radio_item_images = RadioGroup.Item(
61
+ ProjectType.IMAGES.value, "Images", content=self.select_image_container
62
+ )
63
+ # -------------------------------- #
64
+
65
+ # Videos
66
+ self.select_dataset_for_video = SelectDatasetTree(
67
+ flat=True,
68
+ select_all_datasets=False,
69
+ allowed_project_types=[ProjectType.VIDEOS],
70
+ always_open=False,
71
+ compact=False,
72
+ team_is_selectable=False,
73
+ workspace_is_selectable=False,
74
+ show_select_all_datasets_checkbox=False,
75
+ )
76
+ self.select_video = RadioTable(columns=["id", "name", "dataset"], rows=[])
77
+ self.select_video_container = Container(
78
+ widgets=[self.select_dataset_for_video, self.select_video]
79
+ )
80
+ self._radio_item_videos = RadioGroup.Item(
81
+ ProjectType.VIDEOS.value, "Videos", content=self.select_video_container
82
+ )
83
+ # -------------------------------- #
84
+
85
+ # Data type Radio Selector
86
+ # self.radio = RadioGroup(items=[self._radio_item_images, self._radio_item_videos])
87
+ self.radio = RadioGroup(items=[self._radio_item_images])
88
+ self.radio.hide()
89
+ self.one_of = OneOf(conditional_widget=self.radio)
90
+ # Add widgets to display ------------ #
91
+ self.display_widgets.extend([self.radio, self.one_of])
92
+ # ----------------------------------- #
93
+
94
+ # Base Widgets
95
+ self.validator_text = Text("")
96
+ self.validator_text.hide()
97
+ self.button = Button("Select")
98
+ # Add widgets to display ------------ #
99
+ self.display_widgets.extend([self.validator_text, self.button])
100
+ # ----------------------------------- #
101
+
102
+ # Card Layout
103
+ self.container = Container(self.display_widgets)
104
+ self.card = Card(
105
+ title=self.title,
106
+ description=self.description,
107
+ content=self.container,
108
+ lock_message=self.lock_message,
109
+ )
110
+ # ----------------------------------- #
111
+
112
+ @property
113
+ def widgets_to_disable(self) -> list:
114
+ return [
115
+ self.select_dataset_for_images,
116
+ self.select_dataset_for_video,
117
+ self.select_video,
118
+ self.radio,
119
+ self.one_of,
120
+ ]
121
+
122
+ def get_settings(self) -> Dict[str, Any]:
123
+ if self.radio.get_value() == ProjectType.IMAGES.value:
124
+ return {
125
+ "project_id": self.select_dataset_for_images.get_selected_project_id(),
126
+ "dataset_ids": self.select_dataset_for_images.get_selected_ids(),
127
+ }
128
+ if self.radio.get_value() == ProjectType.VIDEOS.value:
129
+ return {"video_id": self.select_video.get_selected_row()}
130
+
131
+ def load_from_json(self, data):
132
+ if "project_id" in data:
133
+ self.select_dataset_for_images.set_project_id(data["project_id"])
134
+ self.select_dataset_for_images.select_all()
135
+ self.radio.set_value(ProjectType.IMAGES.value)
136
+ if "dataset_ids" in data:
137
+ self.select_dataset_for_images.set_dataset_ids(data["dataset_ids"])
138
+ self.radio.set_value(ProjectType.IMAGES.value)
139
+ if "video_id" in data:
140
+ self.select_video.select_row_by_value("id", data["video_id"])
141
+ self.radio.set_value(ProjectType.VIDEOS.value)
142
+
143
+ def validate_step(self) -> bool:
144
+ self.validator_text.hide()
145
+ if self.radio.get_value() == ProjectType.IMAGES.value:
146
+ if len(self.select_dataset_for_images.get_selected_ids()) == 0:
147
+ self.validator_text.set(text="Select at least one dataset", status="error")
148
+ self.validator_text.show()
149
+ return False
150
+ if self.radio.get_value() == ProjectType.VIDEOS.value:
151
+ if self.select_dataset_for_video.get_selected_id() is None:
152
+ self.validator_text.set(text="Select a dataset", status="error")
153
+ self.validator_text.show()
154
+ return False
155
+ if len(self.select_video.rows) == 0:
156
+ self.validator_text.set(
157
+ text="No videos found in the selected dataset", status="error"
158
+ )
159
+ self.validator_text.show()
160
+ return False
161
+ if self.select_video.get_selected_row() == []:
162
+ self.validator_text.set(text="Select a video", status="error")
163
+ self.validator_text.show()
164
+ return False
165
+ return True
@@ -0,0 +1,79 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from supervisely.api.api import Api
4
+ from supervisely.app.widgets import Button, Card, Container, DeployModel, Text
5
+
6
+
7
+ class ModelSelector:
8
+ title = "Select Model"
9
+ description = "Connect to deployed model or deploy new model"
10
+ lock_message = "Select previous step to unlock"
11
+
12
+ def __init__(self, api: Api, team_id: int):
13
+ # Init Step
14
+ self.api = api
15
+ self.team_id = team_id
16
+ self.display_widgets: List[Any] = []
17
+ # -------------------------------- #
18
+
19
+ # Init Base Widgets
20
+ self.validator_text = None
21
+ self.button = None
22
+ self.container = None
23
+ self.card = None
24
+ # -------------------------------- #
25
+
26
+ # Init Step Widgets
27
+ self.model: DeployModel = None
28
+ # -------------------------------- #
29
+
30
+ # Model Selector
31
+ self.model = DeployModel(api=self.api, team_id=self.team_id)
32
+ # Add widgets to display ------------ #
33
+ self.display_widgets.extend([self.model])
34
+ # ----------------------------------- #
35
+
36
+ # Base Widgets
37
+ self.validator_text = Text("")
38
+ self.validator_text.hide()
39
+ self.button = Button("Select")
40
+ # Add widgets to display ------------ #
41
+ self.display_widgets.extend([self.validator_text, self.button])
42
+ # ----------------------------------- #
43
+
44
+ # Card Layout
45
+ self.container = Container(self.display_widgets)
46
+ self.card = Card(
47
+ title=self.title,
48
+ description=self.description,
49
+ content=self.container,
50
+ lock_message=self.lock_message,
51
+ )
52
+ self.card.lock()
53
+ # ----------------------------------- #
54
+
55
+ @property
56
+ def widgets_to_disable(self) -> list:
57
+ return [
58
+ self.model,
59
+ self.model.connect_button,
60
+ self.model.deploy_button,
61
+ self.model.stop_button,
62
+ self.model.disconnect_button,
63
+ ]
64
+
65
+ def get_settings(self) -> Dict[str, Any]:
66
+ return self.model.get_deploy_parameters()
67
+
68
+ def load_from_json(self, data):
69
+ self.model.load_from_json(data)
70
+
71
+ def validate_step(self) -> bool:
72
+ self.validator_text.hide()
73
+
74
+ if self.model.model_api is None:
75
+ self.validator_text.set(text="Please connect or deploy a model", status="error")
76
+ self.validator_text.show()
77
+ return False
78
+
79
+ return True
@@ -0,0 +1,139 @@
1
+ from typing import Any, Dict, List
2
+
3
+ from supervisely import logger
4
+ from supervisely.api.api import Api
5
+ from supervisely.app.widgets import (
6
+ Button,
7
+ Card,
8
+ Checkbox,
9
+ Container,
10
+ Field,
11
+ Input,
12
+ Progress,
13
+ ProjectThumbnail,
14
+ Text,
15
+ )
16
+
17
+
18
+ class OutputSelector:
19
+ title = "Select Output"
20
+ description = "Select the output mode"
21
+ lock_message = "Select previous step to unlock"
22
+
23
+ def __init__(self, api: Api):
24
+ # Init Step
25
+ self.api = api
26
+ self.display_widgets: List[Any] = []
27
+ # -------------------------------- #
28
+
29
+ # Init Base Widgets
30
+ self.validator_text = None
31
+ self.start_button = None
32
+ self.stop_button = None
33
+ self.container = None
34
+ self.card = None
35
+ # -------------------------------- #
36
+
37
+ # Init Step Widgets
38
+ self.stop_serving_on_finish = None
39
+ self.stop_self_on_finish = None
40
+ self.project_name_input = None
41
+ self.project_name_field = None
42
+ self.progress = None
43
+ self.project_thumbnail = None
44
+ # -------------------------------- #
45
+
46
+ # TODO: Implement option later
47
+ # Stop Apps on Finish
48
+ # self.stop_serving_on_finish = Checkbox("Stop Serving App on prediction finish", False)
49
+ # self.stop_self_on_finish = Checkbox("Stop Predict App on prediction finish", True)
50
+ # Add widgets to display ------------ #
51
+ # self.display_widgets.extend([self.stop_serving_on_finish, self.stop_self_on_finish])
52
+ # ----------------------------------- #
53
+
54
+ # Project Name
55
+ self.project_name_input = Input(minlength=1, maxlength=255, placeholder="New Project Name")
56
+ self.project_name_field = Field(
57
+ content=self.project_name_input,
58
+ title="New Project Name",
59
+ description="Name of the new project to create for the results. The created project will have the same dataset structure as the input project.",
60
+ )
61
+ # Add widgets to display ------------ #
62
+ self.display_widgets.extend([self.project_name_field])
63
+ # ----------------------------------- #
64
+
65
+ # Base Widgets
66
+ self.validator_text = Text("", status="text")
67
+ self.validator_text.hide()
68
+ self.start_button = Button("Run", icon="zmdi zmdi-play")
69
+ self.stop_button = Button("Stop", icon="zmdi zmdi-stop")
70
+ # Add widgets to display ------------ #
71
+ self.display_widgets.extend([self.start_button, self.validator_text])
72
+ # ----------------------------------- #
73
+
74
+ # Progress
75
+ self.progress = Progress(hide_on_finish=False)
76
+ self.progress.hide()
77
+ # Add widgets to display ------------ #
78
+ self.display_widgets.extend([self.progress])
79
+ # ----------------------------------- #
80
+
81
+ # Result
82
+ self.project_thumbnail = ProjectThumbnail()
83
+ self.project_thumbnail.hide()
84
+ # Add widgets to display ------------ #
85
+ self.display_widgets.extend([self.project_thumbnail])
86
+ # ----------------------------------- #
87
+
88
+ # Card Layout
89
+ self.container = Container(self.display_widgets)
90
+ self.card = Card(
91
+ title=self.title,
92
+ description=self.description,
93
+ content=self.container,
94
+ lock_message=self.lock_message,
95
+ )
96
+ self.card.lock()
97
+ # ----------------------------------- #
98
+
99
+ @property
100
+ def widgets_to_disable(self) -> list:
101
+ return [self.project_name_input]
102
+
103
+ def set_result_thumbnail(self, project_id: int):
104
+ try:
105
+ project_info = self.api.project.get_info_by_id(project_id)
106
+ self.project_thumbnail.set(project_info)
107
+ self.project_thumbnail.show()
108
+ except Exception as e:
109
+ logger.error(f"Failed to set result thumbnail: {str(e)}")
110
+ self.project_thumbnail.hide()
111
+
112
+ def get_settings(self) -> Dict[str, Any]:
113
+ settings = {}
114
+ settings["project_name"] = self.project_name_input.get_value()
115
+ return settings
116
+
117
+ def should_stop_serving_on_finish(self) -> bool:
118
+ if self.stop_serving_on_finish is not None:
119
+ return self.stop_serving_on_finish.is_checked()
120
+ return False
121
+
122
+ def should_stop_self_on_finish(self) -> bool:
123
+ if self.stop_self_on_finish is not None:
124
+ return self.stop_self_on_finish.is_checked()
125
+ return True
126
+
127
+ def load_from_json(self, data):
128
+ project_name = data.get("project_name", None)
129
+ if project_name:
130
+ self.project_name_input.set_value(project_name)
131
+
132
+ def validate_step(self) -> bool:
133
+ self.validator_text.hide()
134
+ if self.project_name_input.get_value() == "":
135
+ self.validator_text.set(text="Project name is required", status="error")
136
+ self.validator_text.show()
137
+ return False
138
+
139
+ return True
@@ -0,0 +1,93 @@
1
+ import os
2
+ from typing import List, Any, Dict
3
+
4
+ from supervisely.api.api import Api
5
+ from supervisely.app.widgets import Button, Container, Card, Text, GridGallery
6
+
7
+
8
+ class Preview:
9
+ title = "Preview"
10
+ description = "Preview the model output"
11
+ lock_message = None
12
+
13
+ def __init__(self, api: Api, static_dir: str):
14
+ # Init Step
15
+ self.api = api
16
+ self.display_widgets: List[Any] = []
17
+ self.static_dir = static_dir
18
+ self.inference_settings = None
19
+ # -------------------------------- #
20
+
21
+ # Init Base Widgets
22
+ self.validator_text = None
23
+ self.button = None
24
+ self.container = None
25
+ self.card = None
26
+ # -------------------------------- #
27
+
28
+ # Init Step Widgets
29
+ self.gallery = None
30
+ # -------------------------------- #
31
+
32
+ # Preview Directory
33
+ self.preview_dir = os.path.join(self.static_dir, "preview")
34
+ os.makedirs(self.preview_dir, exist_ok=True)
35
+ self.preview_path = os.path.join(self.preview_dir, "preview.jpg")
36
+ self.peview_url = f"/static/preview/preview.jpg"
37
+ # ----------------------------------- #
38
+
39
+ # Preview Widget
40
+ self.gallery = GridGallery(
41
+ 2,
42
+ sync_views=True,
43
+ enable_zoom=True,
44
+ resize_on_zoom=True,
45
+ empty_message="Click 'Preview' to see the model output.",
46
+ )
47
+ # Add widgets to display ------------ #
48
+ self.display_widgets.extend([self.gallery])
49
+ # ----------------------------------- #
50
+
51
+ # Base Widgets
52
+ self.validator_text = Text("")
53
+ self.validator_text.hide()
54
+ self.button = Button("Preview", icon="zmdi zmdi-eye")
55
+ # Add widgets to display ------------ #
56
+ self.display_widgets.extend([self.validator_text, self.button])
57
+ # ----------------------------------- #
58
+
59
+ # Card Layout
60
+ self.container = Container(self.display_widgets)
61
+ self.card = Card(
62
+ title="Preview",
63
+ content=self.container,
64
+ lock_message=self.lock_message,
65
+ )
66
+ self.card.lock()
67
+ # ----------------------------------- #
68
+
69
+ @self.button.click
70
+ def button_click():
71
+ self.run_preview()
72
+
73
+ @property
74
+ def widgets_to_disable(self) -> list:
75
+ return [self.gallery]
76
+
77
+ def load_from_json(self, data: Dict[str, Any]) -> None:
78
+ return
79
+
80
+ def get_settings(self) -> Dict[str, Any]:
81
+ return {
82
+ "preview_path": self.preview_path,
83
+ "preview_url": self.peview_url,
84
+ "inference_settings": self.inference_settings,
85
+ }
86
+
87
+ def validate_step(self) -> bool:
88
+ return True
89
+
90
+ def run_preview(self) -> None:
91
+ raise NotImplementedError(
92
+ "run_preview must be implemented by subclasses or injected at runtime"
93
+ )
@@ -0,0 +1,184 @@
1
+ from typing import Any, Dict, List
2
+
3
+ import yaml
4
+
5
+ from supervisely.app.widgets import (
6
+ Button,
7
+ Card,
8
+ Checkbox,
9
+ Container,
10
+ Editor,
11
+ Field,
12
+ Input,
13
+ Select,
14
+ Text,
15
+ )
16
+
17
+
18
+ class InferenceMode:
19
+ FULL_IMAGE = "Full Image"
20
+ SLIDING_WINDOW = "Sliding Window"
21
+
22
+
23
+ class AddPredictionsMode:
24
+ MERGE_WITH_EXISTING_LABELS = "Merge with existing labels"
25
+ REPLACE_EXISTING_LABELS = "Replace existing labels"
26
+ REPLACE_EXISTING_LABELS_AND_SAVE_IMAGE_TAGS = "Replace existing labels and save image tags"
27
+
28
+
29
+ class SettingsSelector:
30
+ title = "Settings Selector"
31
+ description = "Select additional settings for model inference"
32
+ lock_message = "Select previous step to unlock"
33
+
34
+ def __init__(self):
35
+ # Init Step
36
+ self.display_widgets: List[Any] = []
37
+ # -------------------------------- #
38
+
39
+ # Init Base Widgets
40
+ self.validator_text = None
41
+ self.button = None
42
+ self.container = None
43
+ self.card = None
44
+ # -------------------------------- #
45
+
46
+ # Init Step Widgets
47
+ self.inference_mode_selector = None
48
+ self.inference_mode_field = None
49
+ self.model_prediction_suffix_input = None
50
+ self.model_prediction_suffix_field = None
51
+ # self.model_prediction_suffix_checkbox = None
52
+ self.predictions_mode_selector = None
53
+ self.predictions_mode_field = None
54
+ self.inference_settings = None
55
+ # -------------------------------- #
56
+
57
+ # Inference Mode
58
+ self.inference_modes = [InferenceMode.FULL_IMAGE, InferenceMode.SLIDING_WINDOW]
59
+ self.inference_mode_selector = Select(
60
+ items=[Select.Item(mode) for mode in self.inference_modes]
61
+ )
62
+ self.inference_mode_selector.set_value(self.inference_modes[0])
63
+ self.inference_mode_field = Field(
64
+ content=self.inference_mode_selector,
65
+ title="Inference mode",
66
+ description="Select how to process images: full images or using sliding window.",
67
+ )
68
+ # Add widgets to display ------------ #
69
+ self.display_widgets.extend([self.inference_mode_field])
70
+ # ----------------------------------- #
71
+
72
+ # Class / Tag Suffix
73
+ self.model_prediction_suffix_input = Input(
74
+ value="_model", minlength=1, placeholder="Enter suffix e.g: _model"
75
+ )
76
+ self.model_prediction_suffix_field = Field(
77
+ content=self.model_prediction_suffix_input,
78
+ title="Class and tag suffix",
79
+ description=(
80
+ "Suffix that will be added to conflicting class and tag names. "
81
+ "E.g. your project has a class 'person' with shape 'bitmap' and model has class 'person' with shape 'rectangle', "
82
+ "then suffix will be added to the model predictions to avoid conflicts. E.g. 'person_model'."
83
+ ),
84
+ )
85
+ # self.model_prediction_suffix_checkbox = Checkbox("Always add suffix to model predictions")
86
+ # Add widgets to display ------------ #
87
+ self.display_widgets.extend(
88
+ [self.model_prediction_suffix_field] # , self.model_prediction_suffix_checkbox]
89
+ )
90
+ # ----------------------------------- #
91
+
92
+ # Prediction Mode
93
+ self.prediction_modes = [
94
+ AddPredictionsMode.MERGE_WITH_EXISTING_LABELS,
95
+ AddPredictionsMode.REPLACE_EXISTING_LABELS,
96
+ # AddPredictionsMode.REPLACE_EXISTING_LABELS_AND_SAVE_IMAGE_TAGS, # @TODO: Implement later
97
+ ]
98
+ self.predictions_mode_selector = Select(
99
+ items=[Select.Item(mode) for mode in self.prediction_modes]
100
+ )
101
+ self.predictions_mode_selector.set_value(self.prediction_modes[0])
102
+ self.predictions_mode_field = Field(
103
+ content=self.predictions_mode_selector,
104
+ title="Add predictions mode",
105
+ description="Select how to add predictions to the project: by merging with existing labels or by replacing them.",
106
+ )
107
+ # Add widgets to display ------------ #
108
+ self.display_widgets.extend([self.predictions_mode_field])
109
+ # ----------------------------------- #
110
+
111
+ # Inference Settings
112
+ self.inference_settings = Editor("", language_mode="yaml", height_px=300)
113
+ # Add widgets to display ------------ #
114
+ self.display_widgets.extend([self.inference_settings])
115
+ # ----------------------------------- #
116
+
117
+ # Base Widgets
118
+ self.validator_text = Text("")
119
+ self.validator_text.hide()
120
+ self.button = Button("Select")
121
+ # Add widgets to display ------------ #
122
+ self.display_widgets.extend([self.validator_text, self.button])
123
+ # ----------------------------------- #
124
+
125
+ # Card Layout
126
+ self.container = Container(self.display_widgets)
127
+ self.card = Card(
128
+ title=self.title,
129
+ description=self.description,
130
+ content=self.container,
131
+ lock_message=self.lock_message,
132
+ )
133
+ self.card.lock()
134
+ # ----------------------------------- #
135
+
136
+ @property
137
+ def widgets_to_disable(self) -> list:
138
+ return [
139
+ self.inference_mode_selector,
140
+ self.model_prediction_suffix_input,
141
+ # self.model_prediction_suffix_checkbox,
142
+ self.predictions_mode_selector,
143
+ self.inference_settings,
144
+ ]
145
+
146
+ def set_inference_settings(self, settings: Dict[str, Any]):
147
+ if isinstance(settings, str):
148
+ self.inference_settings.set_text(settings)
149
+ else:
150
+ self.inference_settings.set_text(yaml.safe_dump(settings))
151
+
152
+ def get_inference_settings(self) -> Dict:
153
+ settings = yaml.safe_load(self.inference_settings.get_text())
154
+ if settings:
155
+ return settings
156
+ return {}
157
+
158
+ def get_settings(self) -> Dict[str, Any]:
159
+ return {
160
+ "inference_mode": self.inference_mode_selector.get_value(),
161
+ "model_prediction_suffix": self.model_prediction_suffix_input.get_value(),
162
+ "predictions_mode": self.predictions_mode_selector.get_value(),
163
+ "inference_settings": self.get_inference_settings(),
164
+ }
165
+
166
+ def load_from_json(self, data):
167
+ inference_mode = data.get("inference_mode", None)
168
+ if inference_mode:
169
+ self.inference_mode_selector.set_value(inference_mode)
170
+
171
+ model_prediction_suffix = data.get("model_prediction_suffix", None)
172
+ if model_prediction_suffix is not None:
173
+ self.model_prediction_suffix_input.set_value(model_prediction_suffix)
174
+
175
+ predictions_mode = data.get("predictions_mode", None)
176
+ if predictions_mode:
177
+ self.predictions_mode_selector.set_value(predictions_mode)
178
+
179
+ inference_settings = data.get("inference_settings", None)
180
+ if inference_settings is not None:
181
+ self.set_inference_settings(inference_settings)
182
+
183
+ def validate_step(self) -> bool:
184
+ return True