lazylabel-gui 1.1.1__py3-none-any.whl → 1.1.3__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 (35) hide show
  1. lazylabel/__init__.py +1 -1
  2. lazylabel/config/__init__.py +3 -3
  3. lazylabel/config/hotkeys.py +96 -58
  4. lazylabel/config/paths.py +8 -9
  5. lazylabel/config/settings.py +15 -16
  6. lazylabel/core/__init__.py +3 -3
  7. lazylabel/core/file_manager.py +49 -33
  8. lazylabel/core/model_manager.py +9 -11
  9. lazylabel/core/segment_manager.py +21 -22
  10. lazylabel/main.py +1 -0
  11. lazylabel/models/__init__.py +1 -1
  12. lazylabel/models/sam_model.py +24 -19
  13. lazylabel/ui/__init__.py +3 -3
  14. lazylabel/ui/control_panel.py +21 -19
  15. lazylabel/ui/editable_vertex.py +16 -3
  16. lazylabel/ui/hotkey_dialog.py +125 -93
  17. lazylabel/ui/hoverable_polygon_item.py +1 -2
  18. lazylabel/ui/main_window.py +290 -49
  19. lazylabel/ui/photo_viewer.py +4 -7
  20. lazylabel/ui/reorderable_class_table.py +2 -3
  21. lazylabel/ui/right_panel.py +15 -16
  22. lazylabel/ui/widgets/__init__.py +1 -1
  23. lazylabel/ui/widgets/adjustments_widget.py +22 -21
  24. lazylabel/ui/widgets/model_selection_widget.py +28 -21
  25. lazylabel/ui/widgets/settings_widget.py +35 -28
  26. lazylabel/ui/widgets/status_bar.py +2 -2
  27. lazylabel/utils/__init__.py +2 -2
  28. lazylabel/utils/custom_file_system_model.py +3 -2
  29. {lazylabel_gui-1.1.1.dist-info → lazylabel_gui-1.1.3.dist-info}/METADATA +48 -2
  30. lazylabel_gui-1.1.3.dist-info/RECORD +37 -0
  31. lazylabel_gui-1.1.1.dist-info/RECORD +0 -37
  32. {lazylabel_gui-1.1.1.dist-info → lazylabel_gui-1.1.3.dist-info}/WHEEL +0 -0
  33. {lazylabel_gui-1.1.1.dist-info → lazylabel_gui-1.1.3.dist-info}/entry_points.txt +0 -0
  34. {lazylabel_gui-1.1.1.dist-info → lazylabel_gui-1.1.3.dist-info}/licenses/LICENSE +0 -0
  35. {lazylabel_gui-1.1.1.dist-info → lazylabel_gui-1.1.3.dist-info}/top_level.txt +0 -0
@@ -1,26 +1,26 @@
1
1
  """Adjustments widget for sliders and controls."""
2
2
 
3
- from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QSlider, QGroupBox
4
3
  from PyQt6.QtCore import Qt, pyqtSignal
4
+ from PyQt6.QtWidgets import QGroupBox, QLabel, QSlider, QVBoxLayout, QWidget
5
5
 
6
6
 
7
7
  class AdjustmentsWidget(QWidget):
8
8
  """Widget for adjustment controls."""
9
-
9
+
10
10
  annotation_size_changed = pyqtSignal(int)
11
11
  pan_speed_changed = pyqtSignal(int)
12
12
  join_threshold_changed = pyqtSignal(int)
13
-
13
+
14
14
  def __init__(self, parent=None):
15
15
  super().__init__(parent)
16
16
  self._setup_ui()
17
17
  self._connect_signals()
18
-
18
+
19
19
  def _setup_ui(self):
20
20
  """Setup the UI layout."""
21
21
  group = QGroupBox("Adjustments")
22
22
  layout = QVBoxLayout(group)
23
-
23
+
24
24
  # Annotation size
25
25
  self.size_label = QLabel("Annotation Size: 1.0x")
26
26
  self.size_slider = QSlider(Qt.Orientation.Horizontal)
@@ -29,9 +29,9 @@ class AdjustmentsWidget(QWidget):
29
29
  self.size_slider.setToolTip("Adjusts the size of points and lines (Ctrl +/-)")
30
30
  layout.addWidget(self.size_label)
31
31
  layout.addWidget(self.size_slider)
32
-
32
+
33
33
  layout.addSpacing(10)
34
-
34
+
35
35
  # Pan speed
36
36
  self.pan_label = QLabel("Pan Speed: 1.0x")
37
37
  self.pan_slider = QSlider(Qt.Orientation.Horizontal)
@@ -42,9 +42,9 @@ class AdjustmentsWidget(QWidget):
42
42
  )
43
43
  layout.addWidget(self.pan_label)
44
44
  layout.addWidget(self.pan_slider)
45
-
45
+
46
46
  layout.addSpacing(10)
47
-
47
+
48
48
  # Polygon join threshold
49
49
  self.join_label = QLabel("Polygon Join Distance: 2px")
50
50
  self.join_slider = QSlider(Qt.Orientation.Horizontal)
@@ -53,55 +53,56 @@ class AdjustmentsWidget(QWidget):
53
53
  self.join_slider.setToolTip("The pixel distance to 'snap' a polygon closed.")
54
54
  layout.addWidget(self.join_label)
55
55
  layout.addWidget(self.join_slider)
56
-
56
+
57
57
  # Main layout
58
58
  main_layout = QVBoxLayout(self)
59
59
  main_layout.setContentsMargins(0, 0, 0, 0)
60
60
  main_layout.addWidget(group)
61
-
61
+
62
62
  def _connect_signals(self):
63
63
  """Connect internal signals."""
64
64
  self.size_slider.valueChanged.connect(self._on_size_changed)
65
65
  self.pan_slider.valueChanged.connect(self._on_pan_changed)
66
66
  self.join_slider.valueChanged.connect(self._on_join_changed)
67
-
67
+
68
68
  def _on_size_changed(self, value):
69
69
  """Handle annotation size change."""
70
70
  multiplier = value / 10.0
71
71
  self.size_label.setText(f"Annotation Size: {multiplier:.1f}x")
72
72
  self.annotation_size_changed.emit(value)
73
-
73
+
74
74
  def _on_pan_changed(self, value):
75
75
  """Handle pan speed change."""
76
76
  multiplier = value / 10.0
77
77
  self.pan_label.setText(f"Pan Speed: {multiplier:.1f}x")
78
78
  self.pan_speed_changed.emit(value)
79
-
79
+
80
80
  def _on_join_changed(self, value):
81
81
  """Handle join threshold change."""
82
82
  self.join_label.setText(f"Polygon Join Distance: {value}px")
83
83
  self.join_threshold_changed.emit(value)
84
-
84
+
85
85
  def get_annotation_size(self):
86
86
  """Get current annotation size value."""
87
87
  return self.size_slider.value()
88
-
88
+
89
89
  def set_annotation_size(self, value):
90
90
  """Set annotation size value."""
91
91
  self.size_slider.setValue(value)
92
-
92
+
93
93
  def get_pan_speed(self):
94
94
  """Get current pan speed value."""
95
95
  return self.pan_slider.value()
96
-
96
+
97
97
  def set_pan_speed(self, value):
98
98
  """Set pan speed value."""
99
99
  self.pan_slider.setValue(value)
100
-
100
+
101
101
  def get_join_threshold(self):
102
102
  """Get current join threshold value."""
103
103
  return self.join_slider.value()
104
-
104
+
105
105
  def set_join_threshold(self, value):
106
106
  """Set join threshold value."""
107
- self.join_slider.setValue(value)
107
+ self.join_slider.setValue(value)
108
+ self.join_label.setText(f"Polygon Join Distance: {value}px")
@@ -1,94 +1,101 @@
1
1
  """Model selection widget."""
2
2
 
3
- from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QComboBox, QGroupBox
4
3
  from PyQt6.QtCore import pyqtSignal
5
- from typing import List, Tuple
4
+ from PyQt6.QtWidgets import (
5
+ QComboBox,
6
+ QGroupBox,
7
+ QHBoxLayout,
8
+ QLabel,
9
+ QPushButton,
10
+ QVBoxLayout,
11
+ QWidget,
12
+ )
6
13
 
7
14
 
8
15
  class ModelSelectionWidget(QWidget):
9
16
  """Widget for model selection and management."""
10
-
17
+
11
18
  browse_requested = pyqtSignal()
12
19
  refresh_requested = pyqtSignal()
13
20
  model_selected = pyqtSignal(str)
14
-
21
+
15
22
  def __init__(self, parent=None):
16
23
  super().__init__(parent)
17
24
  self._setup_ui()
18
25
  self._connect_signals()
19
-
26
+
20
27
  def _setup_ui(self):
21
28
  """Setup the UI layout."""
22
29
  group = QGroupBox("Model Selection")
23
30
  layout = QVBoxLayout(group)
24
-
31
+
25
32
  # Buttons
26
33
  button_layout = QHBoxLayout()
27
34
  self.btn_browse = QPushButton("Browse Models")
28
35
  self.btn_browse.setToolTip("Browse for a folder containing .pth model files")
29
36
  self.btn_refresh = QPushButton("Refresh")
30
37
  self.btn_refresh.setToolTip("Refresh the list of available models")
31
-
38
+
32
39
  button_layout.addWidget(self.btn_browse)
33
40
  button_layout.addWidget(self.btn_refresh)
34
41
  layout.addLayout(button_layout)
35
-
42
+
36
43
  # Model combo
37
44
  layout.addWidget(QLabel("Available Models:"))
38
45
  self.model_combo = QComboBox()
39
46
  self.model_combo.setToolTip("Select a .pth model file to use")
40
47
  self.model_combo.addItem("Default (vit_h)")
41
48
  layout.addWidget(self.model_combo)
42
-
49
+
43
50
  # Current model label
44
51
  self.current_model_label = QLabel("Current: Default SAM Model")
45
52
  self.current_model_label.setWordWrap(True)
46
53
  self.current_model_label.setStyleSheet("color: #90EE90; font-style: italic;")
47
54
  layout.addWidget(self.current_model_label)
48
-
55
+
49
56
  # Main layout
50
57
  main_layout = QVBoxLayout(self)
51
58
  main_layout.setContentsMargins(0, 0, 0, 0)
52
59
  main_layout.addWidget(group)
53
-
60
+
54
61
  def _connect_signals(self):
55
62
  """Connect internal signals."""
56
63
  self.btn_browse.clicked.connect(self.browse_requested)
57
64
  self.btn_refresh.clicked.connect(self.refresh_requested)
58
65
  self.model_combo.currentTextChanged.connect(self.model_selected)
59
-
60
- def populate_models(self, models: List[Tuple[str, str]]):
66
+
67
+ def populate_models(self, models: list[tuple[str, str]]):
61
68
  """Populate the models combo box.
62
-
69
+
63
70
  Args:
64
71
  models: List of (display_name, full_path) tuples
65
72
  """
66
73
  self.model_combo.blockSignals(True)
67
74
  self.model_combo.clear()
68
-
75
+
69
76
  # Add default option
70
77
  self.model_combo.addItem("Default (vit_h)")
71
-
78
+
72
79
  # Add custom models
73
80
  for display_name, full_path in models:
74
81
  self.model_combo.addItem(display_name, full_path)
75
-
82
+
76
83
  self.model_combo.blockSignals(False)
77
-
84
+
78
85
  def set_current_model(self, model_name: str):
79
86
  """Set the current model display."""
80
87
  self.current_model_label.setText(model_name)
81
-
88
+
82
89
  def get_selected_model_path(self) -> str:
83
90
  """Get the path of the currently selected model."""
84
91
  current_index = self.model_combo.currentIndex()
85
92
  if current_index <= 0: # Default option
86
93
  return ""
87
94
  return self.model_combo.itemData(current_index) or ""
88
-
95
+
89
96
  def reset_to_default(self):
90
97
  """Reset selection to default model."""
91
98
  self.model_combo.blockSignals(True)
92
99
  self.model_combo.setCurrentIndex(0)
93
100
  self.model_combo.blockSignals(False)
94
- self.set_current_model("Current: Default SAM Model")
101
+ self.set_current_model("Current: Default SAM Model")
@@ -1,24 +1,24 @@
1
1
  """Settings widget for save options."""
2
2
 
3
- from PyQt6.QtWidgets import QWidget, QVBoxLayout, QCheckBox, QGroupBox
4
3
  from PyQt6.QtCore import pyqtSignal
4
+ from PyQt6.QtWidgets import QCheckBox, QGroupBox, QVBoxLayout, QWidget
5
5
 
6
6
 
7
7
  class SettingsWidget(QWidget):
8
8
  """Widget for application settings."""
9
-
9
+
10
10
  settings_changed = pyqtSignal()
11
-
11
+
12
12
  def __init__(self, parent=None):
13
13
  super().__init__(parent)
14
14
  self._setup_ui()
15
15
  self._connect_signals()
16
-
16
+
17
17
  def _setup_ui(self):
18
18
  """Setup the UI layout."""
19
19
  group = QGroupBox("Settings")
20
20
  layout = QVBoxLayout(group)
21
-
21
+
22
22
  # Auto-save
23
23
  self.chk_auto_save = QCheckBox("Auto-Save on Navigate")
24
24
  self.chk_auto_save.setToolTip(
@@ -26,7 +26,7 @@ class SettingsWidget(QWidget):
26
26
  )
27
27
  self.chk_auto_save.setChecked(True)
28
28
  layout.addWidget(self.chk_auto_save)
29
-
29
+
30
30
  # Save NPZ
31
31
  self.chk_save_npz = QCheckBox("Save .npz")
32
32
  self.chk_save_npz.setChecked(True)
@@ -34,7 +34,7 @@ class SettingsWidget(QWidget):
34
34
  "Save the final mask as a compressed NumPy NPZ file."
35
35
  )
36
36
  layout.addWidget(self.chk_save_npz)
37
-
37
+
38
38
  # Save TXT
39
39
  self.chk_save_txt = QCheckBox("Save .txt")
40
40
  self.chk_save_txt.setChecked(True)
@@ -42,7 +42,7 @@ class SettingsWidget(QWidget):
42
42
  "Save bounding box annotations in YOLO TXT format."
43
43
  )
44
44
  layout.addWidget(self.chk_save_txt)
45
-
45
+
46
46
  # YOLO with aliases
47
47
  self.chk_yolo_use_alias = QCheckBox("Save YOLO with Class Aliases")
48
48
  self.chk_yolo_use_alias.setToolTip(
@@ -51,7 +51,7 @@ class SettingsWidget(QWidget):
51
51
  )
52
52
  self.chk_yolo_use_alias.setChecked(True)
53
53
  layout.addWidget(self.chk_yolo_use_alias)
54
-
54
+
55
55
  # Save class aliases
56
56
  self.chk_save_class_aliases = QCheckBox("Save Class Aliases (.json)")
57
57
  self.chk_save_class_aliases.setToolTip(
@@ -59,48 +59,55 @@ class SettingsWidget(QWidget):
59
59
  )
60
60
  self.chk_save_class_aliases.setChecked(False)
61
61
  layout.addWidget(self.chk_save_class_aliases)
62
-
62
+
63
63
  # Main layout
64
64
  main_layout = QVBoxLayout(self)
65
65
  main_layout.setContentsMargins(0, 0, 0, 0)
66
66
  main_layout.addWidget(group)
67
-
67
+
68
68
  def _connect_signals(self):
69
69
  """Connect internal signals."""
70
70
  self.chk_save_npz.stateChanged.connect(self._handle_save_checkbox_change)
71
71
  self.chk_save_txt.stateChanged.connect(self._handle_save_checkbox_change)
72
-
72
+
73
73
  # Connect all checkboxes to settings changed signal
74
- for checkbox in [self.chk_auto_save, self.chk_save_npz, self.chk_save_txt,
75
- self.chk_yolo_use_alias, self.chk_save_class_aliases]:
74
+ for checkbox in [
75
+ self.chk_auto_save,
76
+ self.chk_save_npz,
77
+ self.chk_save_txt,
78
+ self.chk_yolo_use_alias,
79
+ self.chk_save_class_aliases,
80
+ ]:
76
81
  checkbox.stateChanged.connect(self.settings_changed)
77
-
82
+
78
83
  def _handle_save_checkbox_change(self):
79
84
  """Ensure at least one save format is selected."""
80
85
  is_npz_checked = self.chk_save_npz.isChecked()
81
86
  is_txt_checked = self.chk_save_txt.isChecked()
82
-
87
+
83
88
  if not is_npz_checked and not is_txt_checked:
84
89
  sender = self.sender()
85
90
  if sender == self.chk_save_npz:
86
91
  self.chk_save_txt.setChecked(True)
87
92
  else:
88
93
  self.chk_save_npz.setChecked(True)
89
-
94
+
90
95
  def get_settings(self):
91
96
  """Get current settings as dictionary."""
92
97
  return {
93
- 'auto_save': self.chk_auto_save.isChecked(),
94
- 'save_npz': self.chk_save_npz.isChecked(),
95
- 'save_txt': self.chk_save_txt.isChecked(),
96
- 'yolo_use_alias': self.chk_yolo_use_alias.isChecked(),
97
- 'save_class_aliases': self.chk_save_class_aliases.isChecked(),
98
+ "auto_save": self.chk_auto_save.isChecked(),
99
+ "save_npz": self.chk_save_npz.isChecked(),
100
+ "save_txt": self.chk_save_txt.isChecked(),
101
+ "yolo_use_alias": self.chk_yolo_use_alias.isChecked(),
102
+ "save_class_aliases": self.chk_save_class_aliases.isChecked(),
98
103
  }
99
-
104
+
100
105
  def set_settings(self, settings):
101
106
  """Set settings from dictionary."""
102
- self.chk_auto_save.setChecked(settings.get('auto_save', True))
103
- self.chk_save_npz.setChecked(settings.get('save_npz', True))
104
- self.chk_save_txt.setChecked(settings.get('save_txt', True))
105
- self.chk_yolo_use_alias.setChecked(settings.get('yolo_use_alias', True))
106
- self.chk_save_class_aliases.setChecked(settings.get('save_class_aliases', False))
107
+ self.chk_auto_save.setChecked(settings.get("auto_save", True))
108
+ self.chk_save_npz.setChecked(settings.get("save_npz", True))
109
+ self.chk_save_txt.setChecked(settings.get("save_txt", True))
110
+ self.chk_yolo_use_alias.setChecked(settings.get("yolo_use_alias", True))
111
+ self.chk_save_class_aliases.setChecked(
112
+ settings.get("save_class_aliases", False)
113
+ )
@@ -1,8 +1,8 @@
1
1
  """Status bar widget for displaying active messages."""
2
2
 
3
- from PyQt6.QtWidgets import QStatusBar, QLabel
4
- from PyQt6.QtCore import QTimer, pyqtSignal, Qt
3
+ from PyQt6.QtCore import Qt, QTimer
5
4
  from PyQt6.QtGui import QFont
5
+ from PyQt6.QtWidgets import QLabel, QStatusBar
6
6
 
7
7
 
8
8
  class StatusBar(QStatusBar):
@@ -1,6 +1,6 @@
1
1
  """Utility modules."""
2
2
 
3
- from .utils import mask_to_pixmap
4
3
  from .custom_file_system_model import CustomFileSystemModel
4
+ from .utils import mask_to_pixmap
5
5
 
6
- __all__ = ['mask_to_pixmap', 'CustomFileSystemModel']
6
+ __all__ = ["mask_to_pixmap", "CustomFileSystemModel"]
@@ -1,6 +1,7 @@
1
1
  from pathlib import Path
2
- from PyQt6.QtCore import Qt, QModelIndex, QDir
3
- from PyQt6.QtGui import QFileSystemModel, QBrush, QColor
2
+
3
+ from PyQt6.QtCore import QDir, QModelIndex, Qt
4
+ from PyQt6.QtGui import QBrush, QColor, QFileSystemModel
4
5
 
5
6
 
6
7
  class CustomFileSystemModel(QFileSystemModel):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lazylabel-gui
3
- Version: 1.1.1
3
+ Version: 1.1.3
4
4
  Summary: An image segmentation GUI for generating ML ready mask tensors and annotations.
5
5
  Author-email: "Deniz N. Cakan" <deniz.n.cakan@gmail.com>
6
6
  License: MIT License
@@ -45,6 +45,12 @@ Requires-Dist: opencv-python>=4.11.0.86
45
45
  Requires-Dist: scipy>=1.15.3
46
46
  Requires-Dist: requests>=2.32.4
47
47
  Requires-Dist: tqdm>=4.67.1
48
+ Provides-Extra: dev
49
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
50
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
51
+ Requires-Dist: pytest-mock>=3.10.0; extra == "dev"
52
+ Requires-Dist: pytest-qt>=4.2.0; extra == "dev"
53
+ Requires-Dist: ruff>=0.8.0; extra == "dev"
48
54
  Dynamic: license-file
49
55
 
50
56
  # <img src="https://raw.githubusercontent.com/dnzckn/LazyLabel/main/src/lazylabel/demo_pictures/logo2.png" alt="LazyLabel Logo" style="height:60px; vertical-align:middle;" /> <img src="https://raw.githubusercontent.com/dnzckn/LazyLabel/main/src/lazylabel/demo_pictures/logo_black.png" alt="LazyLabel Cursive" style="height:60px; vertical-align:middle;" />
@@ -142,7 +148,8 @@ Inspired by [LabelMe](https://github.com/wkentaro/labelme?tab=readme-ov-file#ins
142
148
  |---|---|
143
149
  | `L-Click` | Add positive point (Point Mode) or polygon vertex. |
144
150
  | `R-Click` | Add negative point (Point Mode). |
145
- | `Ctrl + Z` | Undo last point. |
151
+ | `Ctrl + Z` | Undo last action. |
152
+ | `Ctrl + Y` / `Ctrl + Shift + Z` | Redo last action. |
146
153
  | `Spacebar` | Finalize and save current AI segment. |
147
154
  | `Enter` | **Save final mask for the current image to a `.npz` file.** |
148
155
  | `M` | **Merge** selected segments into a single class. |
@@ -191,6 +198,45 @@ LazyLabel includes a comprehensive hotkey management system:
191
198
 
192
199
  For complete hotkey documentation, see [HOTKEY_FEATURE.md](src/lazylabel/HOTKEY_FEATURE.md).
193
200
 
201
+ ## Development
202
+
203
+ ### Code Quality
204
+ This project uses Ruff for linting and formatting:
205
+
206
+ ```bash
207
+ # Activate virtual environment first
208
+ & e:\venv\lazylabel\Scripts\Activate.ps1
209
+
210
+ # Run linter
211
+ ruff check .
212
+
213
+ # Fix auto-fixable issues
214
+ ruff check --fix .
215
+
216
+ # Format code
217
+ ruff format .
218
+
219
+ # Check if code is properly formatted
220
+ ruff format --check .
221
+ ```
222
+
223
+ ### Testing
224
+
225
+ Run tests using pytest:
226
+
227
+ ```bash
228
+ # Run all tests
229
+ python -m pytest
230
+
231
+ # Run tests with coverage
232
+ python -m pytest --cov=lazylabel --cov-report=html --cov-report=term-missing
233
+
234
+ # Run specific test file
235
+ python -m pytest tests/unit/ui/test_undo_redo.py -v
236
+ ```
237
+
238
+ The HTML coverage report will be generated in `htmlcov/` directory.
239
+
194
240
  ---
195
241
 
196
242
  ## ☕ Support LazyLabel
@@ -0,0 +1,37 @@
1
+ lazylabel/__init__.py,sha256=0yitHZYNNuF4Rqj7cqE0TrfDV8zhzKD3A5W1vOymHK4,199
2
+ lazylabel/main.py,sha256=AQ-SKj8korOa2rKviFaA1kC-c03VPmVN2xU2qk36764,768
3
+ lazylabel/config/__init__.py,sha256=TnDXH0yx0zy97FfjpiVPHleMgMrM5YwWrUbvevSNJjg,263
4
+ lazylabel/config/hotkeys.py,sha256=Aq5pH2ED91A0wayQD58Vy0gjmajlV4-ra7Vd-IgZr38,8114
5
+ lazylabel/config/paths.py,sha256=ZVKbtaNOxmYO4l6JgsY-8DXaE_jaJfDg2RQJJn3-5nw,1275
6
+ lazylabel/config/settings.py,sha256=Ud27cSadJ7M4l30XN0KrxZ3ixAOPXTUhj-SvvanMjaI,1787
7
+ lazylabel/core/__init__.py,sha256=FmRjop_uIBSJwKMGhaZ-3Iwu34LkoxTuD-hnq5vbTSY,232
8
+ lazylabel/core/file_manager.py,sha256=Blo55jXW-uGVLrreGRmlHUtK2yTbyj3jsTKkfjD0z7k,4796
9
+ lazylabel/core/model_manager.py,sha256=P3IahI0xUk6-F7Y5U4r5RpnUQSelJqX2KBtcmUGNeNY,3368
10
+ lazylabel/core/segment_manager.py,sha256=h7ikOZXpV-JwutiWK9xYGWctTaNHJKMeWau9ANml1tY,5913
11
+ lazylabel/models/__init__.py,sha256=fIlk_0DuZfiClcm0XlZdimeHzunQwBmTMI4PcGsaymw,91
12
+ lazylabel/models/sam_model.py,sha256=89v99hpD0ngAAQKiuRyIib0E-5u9zTDJcubtmxxG-PM,7878
13
+ lazylabel/ui/__init__.py,sha256=4qDIh9y6tABPmD8MAMGZn_G7oSRyrcHt2HkjoWgbGH4,268
14
+ lazylabel/ui/control_panel.py,sha256=iyn6v-GvdSabd0Lk7n6S8p_svuTrqsG0jUOZBGhjqAc,8925
15
+ lazylabel/ui/editable_vertex.py,sha256=xzc5QdFJJXiy035C3HgR4ph-tuJu8245l-Ar7aBvVv8,2399
16
+ lazylabel/ui/hotkey_dialog.py,sha256=ZlZoPvY822ke8YkbCy22o2RUjxtkXSoEOg8eVETIKpQ,15118
17
+ lazylabel/ui/hoverable_pixelmap_item.py,sha256=kJFOp7WXiyHpNf7l73TZjiob85jgP30b5MZvu_z5L3c,728
18
+ lazylabel/ui/hoverable_polygon_item.py,sha256=aclUwd0P8H8xbcep6GwhnfaVs1zSkqeZKAL-xeDyMiU,1222
19
+ lazylabel/ui/main_window.py,sha256=BQh1OsHxZ_ukjcF4HzcJAAzLqNJENBBHZGpB2bYoXbo,75311
20
+ lazylabel/ui/numeric_table_widget_item.py,sha256=dQUlIFu9syCxTGAHVIlmbgkI7aJ3f3wmDPBz1AGK9Bg,283
21
+ lazylabel/ui/photo_viewer.py,sha256=4n2zSpFAnausCoIU-wwWDHDo6vsNp_RGIkhDyhuM2_A,1997
22
+ lazylabel/ui/reorderable_class_table.py,sha256=sxHhQre5O_MXLDFgKnw43QnvXXoqn5xRKMGitgO7muI,2371
23
+ lazylabel/ui/right_panel.py,sha256=F407BhQSNTKi_9IIqdZZgjSMiUmxOIcNO-7UtWWbbdk,12279
24
+ lazylabel/ui/widgets/__init__.py,sha256=bYjLRTqWdi4hcPfSSXmXuT-0c5Aee7HnnQurv_k5bfY,314
25
+ lazylabel/ui/widgets/adjustments_widget.py,sha256=xM43q1khpvRIHslPfI6bukzjx9J0mPgHUdNKCmp3rtM,3912
26
+ lazylabel/ui/widgets/model_selection_widget.py,sha256=kMPaBMfdfnEVH-Be1d5OxLEuioO0c04FZT1Hr904axM,3497
27
+ lazylabel/ui/widgets/settings_widget.py,sha256=2T7A5t1g9oIRx6KsxWk--Reuft9DYeqH1rRI9ME18HQ,4347
28
+ lazylabel/ui/widgets/status_bar.py,sha256=wTbMQNEOBfmtNj8EVFZS_lxgaemu-CbRXeZzEQDaVz8,4014
29
+ lazylabel/utils/__init__.py,sha256=V6IR5Gim-39HgM2NyTVT-n8gy3mjilCSFW9y0owN5nc,179
30
+ lazylabel/utils/custom_file_system_model.py,sha256=-3EimlybvevH6bvqBE0qdFnLADVtayylmkntxPXK0Bk,4869
31
+ lazylabel/utils/utils.py,sha256=sYSCoXL27OaLgOZaUkCAhgmKZ7YfhR3Cc5F8nDIa3Ig,414
32
+ lazylabel_gui-1.1.3.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
33
+ lazylabel_gui-1.1.3.dist-info/METADATA,sha256=i0c3l4ODbKROaIHXpX9y9kttfEbVOU1A3j7NoNONsmo,9506
34
+ lazylabel_gui-1.1.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
+ lazylabel_gui-1.1.3.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
36
+ lazylabel_gui-1.1.3.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
37
+ lazylabel_gui-1.1.3.dist-info/RECORD,,
@@ -1,37 +0,0 @@
1
- lazylabel/__init__.py,sha256=XTAPk-88MdkJX5IKg0f51CxNlARQ-SZIiqLneV6B3II,197
2
- lazylabel/main.py,sha256=U0_bYNiVmmwdhRgBOryRZE91sunDQYEJTGGMNFubj1M,766
3
- lazylabel/config/__init__.py,sha256=ahAF6cneEVmq2zyGwydGgGAOzJKkv_aumq5cWmokOms,261
4
- lazylabel/config/hotkeys.py,sha256=LrQ4nmLWVOZvNOe4mEARFU3Wd3bZ7nvvsxGeFY6N9wA,7618
5
- lazylabel/config/paths.py,sha256=d6lJ0rwdlnLjrhR5fIzb3Pc9Fhl4lsGIf2IZNmi4vZ8,1320
6
- lazylabel/config/settings.py,sha256=IkUGz-FdDapF71k_LRpUOLHScglGeYjdLbbELGJ4hOs,1860
7
- lazylabel/core/__init__.py,sha256=YIj3IAI6Er5nN7gSuo9E8eoQKbBbSq2Jy2prtU8Fp50,230
8
- lazylabel/core/file_manager.py,sha256=cXaSPSUiqTm57hfpUxkuzgqApOZCK1RAJdfjmKRJKRA,4734
9
- lazylabel/core/model_manager.py,sha256=pLTmQlVfambA3y4aypHu_jn_WrW0ZrMu_8j023mr_EM,3435
10
- lazylabel/core/segment_manager.py,sha256=kLEj5S-fEmoXIiJ2Em97GJlre8OOpSotX5bIWMrBCvE,6006
11
- lazylabel/models/__init__.py,sha256=qH0EvkWsou0boS85yM6DfRhJnrPOLc-QzWI0grAwnRI,89
12
- lazylabel/models/sam_model.py,sha256=lMakV3_B-hNJ3BXy1sErkSzH9YvDsColevXLGaeLnP4,7762
13
- lazylabel/ui/__init__.py,sha256=i5hgblzrydTkFSJDiFyfRZMNl4Z4J2dumuwx3bWEPvA,266
14
- lazylabel/ui/control_panel.py,sha256=Pfv4D3V9oBkTWWzTE944JAUCa0by7jv9h3EruKnJLVM,8894
15
- lazylabel/ui/editable_vertex.py,sha256=pMuXvlCkbguUsFisEzj3bC2UZ_xKqfGuM8kyPug5yws,1852
16
- lazylabel/ui/hotkey_dialog.py,sha256=3QkthYil_SWYWxRGL_U8cZCsQ4y-6SExQZXJuE5aO8s,15252
17
- lazylabel/ui/hoverable_pixelmap_item.py,sha256=kJFOp7WXiyHpNf7l73TZjiob85jgP30b5MZvu_z5L3c,728
18
- lazylabel/ui/hoverable_polygon_item.py,sha256=hQKax3vzhtrdB5ThwTINjOCwOYy718zw5YZPLCfLnGM,1251
19
- lazylabel/ui/main_window.py,sha256=zjpTH-RqBx5mJ1i1Y0CC8KepgQF28mIJDYc68CUoBIk,64488
20
- lazylabel/ui/numeric_table_widget_item.py,sha256=dQUlIFu9syCxTGAHVIlmbgkI7aJ3f3wmDPBz1AGK9Bg,283
21
- lazylabel/ui/photo_viewer.py,sha256=PNgm0gU2gnIqvRkrGlQugdobGsKwAi3m3X6ZF487lCo,2055
22
- lazylabel/ui/reorderable_class_table.py,sha256=4c-iuSkPcmk5Aey5n2zz49O85x9TQPujKG-JLxtuBCo,2406
23
- lazylabel/ui/right_panel.py,sha256=7ksUM7eItHrdXWkuDHohXEShdYYR2FYx-zeSmbfi620,12454
24
- lazylabel/ui/widgets/__init__.py,sha256=5wJ09bTPlhqHyBIXGDeXiNJf33YelKKLu0aPrar9AxU,314
25
- lazylabel/ui/widgets/adjustments_widget.py,sha256=Az8GZgu4Uvhm6nEnwjiYDyShOqwieinjFnTOiUfxdzo,3940
26
- lazylabel/ui/widgets/model_selection_widget.py,sha256=X3qVH90yCaCpLDauj-DLWJgAwAkAVQrzhG9X5mESa-o,3590
27
- lazylabel/ui/widgets/settings_widget.py,sha256=8zhjLxUxqFqxqMYDzkXWD1Ye5V-a7HNhPjPJjYBxeZw,4361
28
- lazylabel/ui/widgets/status_bar.py,sha256=71paNOXlxXmWbCG6luyciXRmqC7DNFYDi_Eo2HDzjOg,4026
29
- lazylabel/utils/__init__.py,sha256=SX_aZvmFojIJ4Lskat9ly0dmFBXgN7leBdmc68aDLpg,177
30
- lazylabel/utils/custom_file_system_model.py,sha256=zK0Z4LY2hzYVtycDWsCLEhXZ0zKZz-Qy5XGwHYrqazQ,4867
31
- lazylabel/utils/utils.py,sha256=sYSCoXL27OaLgOZaUkCAhgmKZ7YfhR3Cc5F8nDIa3Ig,414
32
- lazylabel_gui-1.1.1.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
33
- lazylabel_gui-1.1.1.dist-info/METADATA,sha256=RMI2kMGM08gRUJqkKXrMNbkKvmNDawmvjRCutT_Y0bM,8473
34
- lazylabel_gui-1.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
35
- lazylabel_gui-1.1.1.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
36
- lazylabel_gui-1.1.1.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
37
- lazylabel_gui-1.1.1.dist-info/RECORD,,