lazylabel-gui 1.1.4__py3-none-any.whl → 1.1.5__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.
- lazylabel/core/segment_manager.py +188 -183
- lazylabel/ui/editable_vertex.py +2 -2
- lazylabel/ui/main_window.py +41 -19
- {lazylabel_gui-1.1.4.dist-info → lazylabel_gui-1.1.5.dist-info}/METADATA +1 -1
- {lazylabel_gui-1.1.4.dist-info → lazylabel_gui-1.1.5.dist-info}/RECORD +9 -9
- {lazylabel_gui-1.1.4.dist-info → lazylabel_gui-1.1.5.dist-info}/WHEEL +0 -0
- {lazylabel_gui-1.1.4.dist-info → lazylabel_gui-1.1.5.dist-info}/entry_points.txt +0 -0
- {lazylabel_gui-1.1.4.dist-info → lazylabel_gui-1.1.5.dist-info}/licenses/LICENSE +0 -0
- {lazylabel_gui-1.1.4.dist-info → lazylabel_gui-1.1.5.dist-info}/top_level.txt +0 -0
@@ -1,183 +1,188 @@
|
|
1
|
-
"""Segment management functionality."""
|
2
|
-
|
3
|
-
from typing import Any
|
4
|
-
|
5
|
-
import cv2
|
6
|
-
import numpy as np
|
7
|
-
from PyQt6.QtCore import QPointF
|
8
|
-
|
9
|
-
|
10
|
-
class SegmentManager:
|
11
|
-
"""Manages image segments and classes."""
|
12
|
-
|
13
|
-
def __init__(self):
|
14
|
-
self.segments: list[dict[str, Any]] = []
|
15
|
-
self.class_aliases: dict[int, str] = {}
|
16
|
-
self.next_class_id: int = 0
|
17
|
-
self.active_class_id: int | None = None # Currently active/toggled class
|
18
|
-
|
19
|
-
def clear(self) -> None:
|
20
|
-
"""Clear all segments and reset state."""
|
21
|
-
self.segments.clear()
|
22
|
-
self.class_aliases.clear()
|
23
|
-
self.next_class_id = 0
|
24
|
-
self.active_class_id = None
|
25
|
-
|
26
|
-
def add_segment(self, segment_data: dict[str, Any]) -> None:
|
27
|
-
"""Add a new segment.
|
28
|
-
|
29
|
-
If the segment is a polygon, convert QPointF objects to simple lists
|
30
|
-
for serialization compatibility.
|
31
|
-
"""
|
32
|
-
if "class_id" not in segment_data:
|
33
|
-
# Use active class if available, otherwise use next class ID
|
34
|
-
if self.active_class_id is not None:
|
35
|
-
segment_data["class_id"] = self.active_class_id
|
36
|
-
else:
|
37
|
-
segment_data["class_id"] = self.next_class_id
|
38
|
-
|
39
|
-
# Convert QPointF to list for storage if it's a polygon
|
40
|
-
if
|
41
|
-
segment_data
|
42
|
-
|
43
|
-
]
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
if
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
)
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
self.class_aliases
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
1
|
+
"""Segment management functionality."""
|
2
|
+
|
3
|
+
from typing import Any
|
4
|
+
|
5
|
+
import cv2
|
6
|
+
import numpy as np
|
7
|
+
from PyQt6.QtCore import QPointF
|
8
|
+
|
9
|
+
|
10
|
+
class SegmentManager:
|
11
|
+
"""Manages image segments and classes."""
|
12
|
+
|
13
|
+
def __init__(self):
|
14
|
+
self.segments: list[dict[str, Any]] = []
|
15
|
+
self.class_aliases: dict[int, str] = {}
|
16
|
+
self.next_class_id: int = 0
|
17
|
+
self.active_class_id: int | None = None # Currently active/toggled class
|
18
|
+
|
19
|
+
def clear(self) -> None:
|
20
|
+
"""Clear all segments and reset state."""
|
21
|
+
self.segments.clear()
|
22
|
+
self.class_aliases.clear()
|
23
|
+
self.next_class_id = 0
|
24
|
+
self.active_class_id = None
|
25
|
+
|
26
|
+
def add_segment(self, segment_data: dict[str, Any]) -> None:
|
27
|
+
"""Add a new segment.
|
28
|
+
|
29
|
+
If the segment is a polygon, convert QPointF objects to simple lists
|
30
|
+
for serialization compatibility.
|
31
|
+
"""
|
32
|
+
if "class_id" not in segment_data:
|
33
|
+
# Use active class if available, otherwise use next class ID
|
34
|
+
if self.active_class_id is not None:
|
35
|
+
segment_data["class_id"] = self.active_class_id
|
36
|
+
else:
|
37
|
+
segment_data["class_id"] = self.next_class_id
|
38
|
+
|
39
|
+
# Convert QPointF to list for storage if it's a polygon and contains QPointF objects
|
40
|
+
if (
|
41
|
+
segment_data.get("type") == "Polygon"
|
42
|
+
and segment_data.get("vertices")
|
43
|
+
and segment_data["vertices"]
|
44
|
+
and isinstance(segment_data["vertices"][0], QPointF)
|
45
|
+
):
|
46
|
+
segment_data["vertices"] = [
|
47
|
+
[p.x(), p.y()] for p in segment_data["vertices"]
|
48
|
+
]
|
49
|
+
|
50
|
+
self.segments.append(segment_data)
|
51
|
+
self._update_next_class_id()
|
52
|
+
|
53
|
+
def delete_segments(self, indices: list[int]) -> None:
|
54
|
+
"""Delete segments by indices."""
|
55
|
+
for i in sorted(indices, reverse=True):
|
56
|
+
if 0 <= i < len(self.segments):
|
57
|
+
del self.segments[i]
|
58
|
+
self._update_next_class_id()
|
59
|
+
|
60
|
+
def assign_segments_to_class(self, indices: list[int]) -> None:
|
61
|
+
"""Assign selected segments to a class."""
|
62
|
+
if not indices:
|
63
|
+
return
|
64
|
+
|
65
|
+
existing_class_ids = [
|
66
|
+
self.segments[i]["class_id"]
|
67
|
+
for i in indices
|
68
|
+
if i < len(self.segments) and self.segments[i].get("class_id") is not None
|
69
|
+
]
|
70
|
+
|
71
|
+
if existing_class_ids:
|
72
|
+
target_class_id = min(existing_class_ids)
|
73
|
+
else:
|
74
|
+
target_class_id = self.next_class_id
|
75
|
+
|
76
|
+
for i in indices:
|
77
|
+
if i < len(self.segments):
|
78
|
+
self.segments[i]["class_id"] = target_class_id
|
79
|
+
|
80
|
+
self._update_next_class_id()
|
81
|
+
|
82
|
+
def get_unique_class_ids(self) -> list[int]:
|
83
|
+
"""Get sorted list of unique class IDs."""
|
84
|
+
return sorted(
|
85
|
+
{
|
86
|
+
seg.get("class_id")
|
87
|
+
for seg in self.segments
|
88
|
+
if seg.get("class_id") is not None
|
89
|
+
}
|
90
|
+
)
|
91
|
+
|
92
|
+
def rasterize_polygon(
|
93
|
+
self, vertices: list[QPointF], image_size: tuple[int, int]
|
94
|
+
) -> np.ndarray | None:
|
95
|
+
"""Convert polygon vertices to binary mask."""
|
96
|
+
if not vertices:
|
97
|
+
return None
|
98
|
+
|
99
|
+
h, w = image_size
|
100
|
+
points_np = np.array([[p.x(), p.y()] for p in vertices], dtype=np.int32)
|
101
|
+
mask = np.zeros((h, w), dtype=np.uint8)
|
102
|
+
cv2.fillPoly(mask, [points_np], 1)
|
103
|
+
return mask.astype(bool)
|
104
|
+
|
105
|
+
def create_final_mask_tensor(
|
106
|
+
self, image_size: tuple[int, int], class_order: list[int]
|
107
|
+
) -> np.ndarray:
|
108
|
+
"""Create final mask tensor for saving."""
|
109
|
+
h, w = image_size
|
110
|
+
id_map = {old_id: new_id for new_id, old_id in enumerate(class_order)}
|
111
|
+
num_final_classes = len(class_order)
|
112
|
+
final_mask_tensor = np.zeros((h, w, num_final_classes), dtype=np.uint8)
|
113
|
+
|
114
|
+
for seg in self.segments:
|
115
|
+
class_id = seg.get("class_id")
|
116
|
+
if class_id not in id_map:
|
117
|
+
continue
|
118
|
+
|
119
|
+
new_channel_idx = id_map[class_id]
|
120
|
+
|
121
|
+
if seg["type"] == "Polygon":
|
122
|
+
# Convert stored list of lists back to QPointF objects for rasterization
|
123
|
+
qpoints = [QPointF(p[0], p[1]) for p in seg["vertices"]]
|
124
|
+
mask = self.rasterize_polygon(qpoints, image_size)
|
125
|
+
else:
|
126
|
+
mask = seg.get("mask")
|
127
|
+
|
128
|
+
if mask is not None:
|
129
|
+
final_mask_tensor[:, :, new_channel_idx] = np.logical_or(
|
130
|
+
final_mask_tensor[:, :, new_channel_idx], mask
|
131
|
+
)
|
132
|
+
|
133
|
+
return final_mask_tensor
|
134
|
+
|
135
|
+
def reassign_class_ids(self, new_order: list[int]) -> None:
|
136
|
+
"""Reassign class IDs based on new order."""
|
137
|
+
id_map = {old_id: new_id for new_id, old_id in enumerate(new_order)}
|
138
|
+
|
139
|
+
for seg in self.segments:
|
140
|
+
old_id = seg.get("class_id")
|
141
|
+
if old_id in id_map:
|
142
|
+
seg["class_id"] = id_map[old_id]
|
143
|
+
|
144
|
+
# Update aliases
|
145
|
+
new_aliases = {
|
146
|
+
id_map[old_id]: self.class_aliases.get(old_id, str(old_id))
|
147
|
+
for old_id in new_order
|
148
|
+
if old_id in self.class_aliases
|
149
|
+
}
|
150
|
+
self.class_aliases = new_aliases
|
151
|
+
self._update_next_class_id()
|
152
|
+
|
153
|
+
def set_class_alias(self, class_id: int, alias: str) -> None:
|
154
|
+
"""Set alias for a class."""
|
155
|
+
self.class_aliases[class_id] = alias
|
156
|
+
|
157
|
+
def get_class_alias(self, class_id: int) -> str:
|
158
|
+
"""Get alias for a class."""
|
159
|
+
return self.class_aliases.get(class_id, str(class_id))
|
160
|
+
|
161
|
+
def set_active_class(self, class_id: int | None) -> None:
|
162
|
+
"""Set the active class ID."""
|
163
|
+
self.active_class_id = class_id
|
164
|
+
|
165
|
+
def get_active_class(self) -> int | None:
|
166
|
+
"""Get the active class ID."""
|
167
|
+
return self.active_class_id
|
168
|
+
|
169
|
+
def toggle_active_class(self, class_id: int) -> bool:
|
170
|
+
"""Toggle a class as active. Returns True if now active, False if deactivated."""
|
171
|
+
if self.active_class_id == class_id:
|
172
|
+
self.active_class_id = None
|
173
|
+
return False
|
174
|
+
else:
|
175
|
+
self.active_class_id = class_id
|
176
|
+
return True
|
177
|
+
|
178
|
+
def _update_next_class_id(self) -> None:
|
179
|
+
"""Update the next available class ID."""
|
180
|
+
all_ids = {
|
181
|
+
seg.get("class_id")
|
182
|
+
for seg in self.segments
|
183
|
+
if seg.get("class_id") is not None
|
184
|
+
}
|
185
|
+
if not all_ids:
|
186
|
+
self.next_class_id = 0
|
187
|
+
else:
|
188
|
+
self.next_class_id = max(all_ids) + 1
|
lazylabel/ui/editable_vertex.py
CHANGED
@@ -55,8 +55,8 @@ class EditableVertexItem(QGraphicsEllipseItem):
|
|
55
55
|
"type": "move_vertex",
|
56
56
|
"segment_index": self.segment_index,
|
57
57
|
"vertex_index": self.vertex_index,
|
58
|
-
"old_pos": self.initial_pos,
|
59
|
-
"new_pos": self.pos(),
|
58
|
+
"old_pos": [self.initial_pos.x(), self.initial_pos.y()],
|
59
|
+
"new_pos": [self.pos().x(), self.pos().y()],
|
60
60
|
}
|
61
61
|
)
|
62
62
|
self.initial_pos = None
|
lazylabel/ui/main_window.py
CHANGED
@@ -912,7 +912,7 @@ class MainWindow(QMainWindow):
|
|
912
912
|
return
|
913
913
|
|
914
914
|
new_segment = {
|
915
|
-
"vertices":
|
915
|
+
"vertices": [[p.x(), p.y()] for p in self.polygon_points],
|
916
916
|
"type": "Polygon",
|
917
917
|
"mask": None,
|
918
918
|
}
|
@@ -1070,7 +1070,9 @@ class MainWindow(QMainWindow):
|
|
1070
1070
|
elif action_type == "move_polygon":
|
1071
1071
|
initial_vertices = last_action.get("initial_vertices")
|
1072
1072
|
for i, vertices in initial_vertices.items():
|
1073
|
-
self.segment_manager.segments[i]["vertices"] =
|
1073
|
+
self.segment_manager.segments[i]["vertices"] = [
|
1074
|
+
[p[0], p[1]] for p in vertices
|
1075
|
+
]
|
1074
1076
|
self._update_polygon_item(i)
|
1075
1077
|
self._display_edit_handles()
|
1076
1078
|
self._highlight_selected_segments()
|
@@ -1079,13 +1081,27 @@ class MainWindow(QMainWindow):
|
|
1079
1081
|
segment_index = last_action.get("segment_index")
|
1080
1082
|
vertex_index = last_action.get("vertex_index")
|
1081
1083
|
old_pos = last_action.get("old_pos")
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1084
|
+
if (
|
1085
|
+
segment_index is not None
|
1086
|
+
and vertex_index is not None
|
1087
|
+
and old_pos is not None
|
1088
|
+
):
|
1089
|
+
if segment_index < len(self.segment_manager.segments):
|
1090
|
+
self.segment_manager.segments[segment_index]["vertices"][
|
1091
|
+
vertex_index
|
1092
|
+
] = old_pos
|
1093
|
+
self._update_polygon_item(segment_index)
|
1094
|
+
self._display_edit_handles()
|
1095
|
+
self._highlight_selected_segments()
|
1096
|
+
self._show_notification("Undid: Move Vertex")
|
1097
|
+
else:
|
1098
|
+
self._show_warning_notification(
|
1099
|
+
"Cannot undo: Segment no longer exists"
|
1100
|
+
)
|
1101
|
+
self.redo_history.pop() # Remove from redo history if segment is gone
|
1102
|
+
else:
|
1103
|
+
self._show_warning_notification("Cannot undo: Missing vertex data")
|
1104
|
+
self.redo_history.pop() # Remove from redo history if data is incomplete
|
1089
1105
|
|
1090
1106
|
# Add more undo logic for other action types here in the future
|
1091
1107
|
else:
|
@@ -1147,8 +1163,7 @@ class MainWindow(QMainWindow):
|
|
1147
1163
|
for i, vertices in final_vertices.items():
|
1148
1164
|
if i < len(self.segment_manager.segments):
|
1149
1165
|
self.segment_manager.segments[i]["vertices"] = [
|
1150
|
-
[
|
1151
|
-
for v in [QPointF(p[0], p[1]) for p in vertices]
|
1166
|
+
[p[0], p[1]] for p in vertices
|
1152
1167
|
]
|
1153
1168
|
self._update_polygon_item(i)
|
1154
1169
|
self._display_edit_handles()
|
@@ -1178,10 +1193,10 @@ class MainWindow(QMainWindow):
|
|
1178
1193
|
self._show_warning_notification(
|
1179
1194
|
"Cannot redo: Segment no longer exists"
|
1180
1195
|
)
|
1181
|
-
self.action_history.pop()
|
1196
|
+
self.action_history.pop() # Remove from action history if segment is gone
|
1182
1197
|
else:
|
1183
1198
|
self._show_warning_notification("Cannot redo: Missing vertex data")
|
1184
|
-
self.action_history.pop()
|
1199
|
+
self.action_history.pop() # Remove from action history if data is incomplete
|
1185
1200
|
else:
|
1186
1201
|
self._show_warning_notification(
|
1187
1202
|
f"Redo for action '{action_type}' not implemented."
|
@@ -1321,7 +1336,7 @@ class MainWindow(QMainWindow):
|
|
1321
1336
|
selected_indices = self.right_panel.get_selected_segment_indices()
|
1322
1337
|
self.drag_initial_vertices = {
|
1323
1338
|
i: [
|
1324
|
-
|
1339
|
+
[p.x(), p.y()] if isinstance(p, QPointF) else p
|
1325
1340
|
for p in self.segment_manager.segments[i]["vertices"]
|
1326
1341
|
]
|
1327
1342
|
for i in selected_indices
|
@@ -1360,7 +1375,7 @@ class MainWindow(QMainWindow):
|
|
1360
1375
|
self.drag_start_pos = pos
|
1361
1376
|
self.rubber_band_rect = QGraphicsRectItem()
|
1362
1377
|
self.rubber_band_rect.setPen(
|
1363
|
-
QPen(Qt.GlobalColor.red,
|
1378
|
+
QPen(Qt.GlobalColor.red, self.line_thickness, Qt.PenStyle.DashLine)
|
1364
1379
|
)
|
1365
1380
|
self.viewer.scene().addItem(self.rubber_band_rect)
|
1366
1381
|
elif self.mode == "selection" and event.button() == Qt.MouseButton.LeftButton:
|
@@ -1371,9 +1386,13 @@ class MainWindow(QMainWindow):
|
|
1371
1386
|
if self.mode == "edit" and self.is_dragging_polygon:
|
1372
1387
|
delta = event.scenePos() - self.drag_start_pos
|
1373
1388
|
for i, initial_verts in self.drag_initial_vertices.items():
|
1374
|
-
# initial_verts are
|
1389
|
+
# initial_verts are lists, convert to QPointF for addition with delta
|
1375
1390
|
self.segment_manager.segments[i]["vertices"] = [
|
1376
|
-
[
|
1391
|
+
[
|
1392
|
+
(QPointF(p[0], p[1]) + delta).x(),
|
1393
|
+
(QPointF(p[0], p[1]) + delta).y(),
|
1394
|
+
]
|
1395
|
+
for p in initial_verts
|
1377
1396
|
]
|
1378
1397
|
self._update_polygon_item(i)
|
1379
1398
|
self._display_edit_handles() # Redraw handles at new positions
|
@@ -1395,7 +1414,10 @@ class MainWindow(QMainWindow):
|
|
1395
1414
|
if self.mode == "edit" and self.is_dragging_polygon:
|
1396
1415
|
# Record the action for undo
|
1397
1416
|
final_vertices = {
|
1398
|
-
i:
|
1417
|
+
i: [
|
1418
|
+
[p.x(), p.y()] if isinstance(p, QPointF) else p
|
1419
|
+
for p in self.segment_manager.segments[i]["vertices"]
|
1420
|
+
]
|
1399
1421
|
for i in self.drag_initial_vertices
|
1400
1422
|
}
|
1401
1423
|
self.action_history.append(
|
@@ -1431,7 +1453,7 @@ class MainWindow(QMainWindow):
|
|
1431
1453
|
polygon.append(rect.bottomLeft())
|
1432
1454
|
|
1433
1455
|
new_segment = {
|
1434
|
-
"vertices": list(polygon),
|
1456
|
+
"vertices": [[p.x(), p.y()] for p in list(polygon)],
|
1435
1457
|
"type": "Polygon", # Bounding boxes are stored as polygons
|
1436
1458
|
"mask": None,
|
1437
1459
|
}
|
@@ -7,16 +7,16 @@ lazylabel/config/settings.py,sha256=Ud27cSadJ7M4l30XN0KrxZ3ixAOPXTUhj-SvvanMjaI,
|
|
7
7
|
lazylabel/core/__init__.py,sha256=FmRjop_uIBSJwKMGhaZ-3Iwu34LkoxTuD-hnq5vbTSY,232
|
8
8
|
lazylabel/core/file_manager.py,sha256=Blo55jXW-uGVLrreGRmlHUtK2yTbyj3jsTKkfjD0z7k,4796
|
9
9
|
lazylabel/core/model_manager.py,sha256=P3IahI0xUk6-F7Y5U4r5RpnUQSelJqX2KBtcmUGNeNY,3368
|
10
|
-
lazylabel/core/segment_manager.py,sha256=
|
10
|
+
lazylabel/core/segment_manager.py,sha256=M6kHcYeiub3WqL01NElCvKOc2GNmf72LUM1W8XwSaxc,6465
|
11
11
|
lazylabel/models/__init__.py,sha256=fIlk_0DuZfiClcm0XlZdimeHzunQwBmTMI4PcGsaymw,91
|
12
12
|
lazylabel/models/sam_model.py,sha256=89v99hpD0ngAAQKiuRyIib0E-5u9zTDJcubtmxxG-PM,7878
|
13
13
|
lazylabel/ui/__init__.py,sha256=4qDIh9y6tABPmD8MAMGZn_G7oSRyrcHt2HkjoWgbGH4,268
|
14
14
|
lazylabel/ui/control_panel.py,sha256=UlETN2IZv1l2xiaWPQvdalaK_f9YQf9iiB1Jb_EEgfs,9260
|
15
|
-
lazylabel/ui/editable_vertex.py,sha256=
|
15
|
+
lazylabel/ui/editable_vertex.py,sha256=nAFC2UuFfbvMbGBbAiLWA77cS5-Hn3a08xe1_QLz2yk,2449
|
16
16
|
lazylabel/ui/hotkey_dialog.py,sha256=ZlZoPvY822ke8YkbCy22o2RUjxtkXSoEOg8eVETIKpQ,15118
|
17
17
|
lazylabel/ui/hoverable_pixelmap_item.py,sha256=kJFOp7WXiyHpNf7l73TZjiob85jgP30b5MZvu_z5L3c,728
|
18
18
|
lazylabel/ui/hoverable_polygon_item.py,sha256=aclUwd0P8H8xbcep6GwhnfaVs1zSkqeZKAL-xeDyMiU,1222
|
19
|
-
lazylabel/ui/main_window.py,sha256=
|
19
|
+
lazylabel/ui/main_window.py,sha256=h0wfVjQRskiTIq6X-Wd7OvM-PfOdKEKdFcwgx0iRIj0,79831
|
20
20
|
lazylabel/ui/numeric_table_widget_item.py,sha256=dQUlIFu9syCxTGAHVIlmbgkI7aJ3f3wmDPBz1AGK9Bg,283
|
21
21
|
lazylabel/ui/photo_viewer.py,sha256=4n2zSpFAnausCoIU-wwWDHDo6vsNp_RGIkhDyhuM2_A,1997
|
22
22
|
lazylabel/ui/reorderable_class_table.py,sha256=sxHhQre5O_MXLDFgKnw43QnvXXoqn5xRKMGitgO7muI,2371
|
@@ -29,9 +29,9 @@ lazylabel/ui/widgets/status_bar.py,sha256=wTbMQNEOBfmtNj8EVFZS_lxgaemu-CbRXeZzEQ
|
|
29
29
|
lazylabel/utils/__init__.py,sha256=V6IR5Gim-39HgM2NyTVT-n8gy3mjilCSFW9y0owN5nc,179
|
30
30
|
lazylabel/utils/custom_file_system_model.py,sha256=-3EimlybvevH6bvqBE0qdFnLADVtayylmkntxPXK0Bk,4869
|
31
31
|
lazylabel/utils/utils.py,sha256=sYSCoXL27OaLgOZaUkCAhgmKZ7YfhR3Cc5F8nDIa3Ig,414
|
32
|
-
lazylabel_gui-1.1.
|
33
|
-
lazylabel_gui-1.1.
|
34
|
-
lazylabel_gui-1.1.
|
35
|
-
lazylabel_gui-1.1.
|
36
|
-
lazylabel_gui-1.1.
|
37
|
-
lazylabel_gui-1.1.
|
32
|
+
lazylabel_gui-1.1.5.dist-info/licenses/LICENSE,sha256=kSDEIgrWAPd1u2UFGGpC9X71dhzrlzBFs8hbDlENnGE,1092
|
33
|
+
lazylabel_gui-1.1.5.dist-info/METADATA,sha256=2MNsqA48WN9e7YJMg864WZYGMZixitm3XtMnD2uZin4,9506
|
34
|
+
lazylabel_gui-1.1.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
35
|
+
lazylabel_gui-1.1.5.dist-info/entry_points.txt,sha256=Hd0WwEG9OPTa_ziYjiD0aRh7R6Fupt-wdQ3sspdc1mM,54
|
36
|
+
lazylabel_gui-1.1.5.dist-info/top_level.txt,sha256=YN4uIyrpDBq1wiJaBuZLDipIzyZY0jqJOmmXiPIOUkU,10
|
37
|
+
lazylabel_gui-1.1.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|