lazylabel-gui 1.3.3__py3-none-any.whl → 1.3.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.
@@ -0,0 +1,129 @@
1
+ """Worker thread for updating SAM model in background."""
2
+
3
+ import cv2
4
+ import numpy as np
5
+ from PyQt6.QtCore import Qt, QThread, pyqtSignal
6
+ from PyQt6.QtGui import QPixmap
7
+
8
+
9
+ class SAMUpdateWorker(QThread):
10
+ """Worker thread for updating SAM model in background."""
11
+
12
+ finished = pyqtSignal()
13
+ error = pyqtSignal(str)
14
+
15
+ def __init__(
16
+ self,
17
+ model_manager,
18
+ image_path,
19
+ operate_on_view,
20
+ current_image=None,
21
+ parent=None,
22
+ ):
23
+ super().__init__(parent)
24
+ self.model_manager = model_manager
25
+ self.image_path = image_path
26
+ self.operate_on_view = operate_on_view
27
+ self.current_image = current_image # Numpy array of current modified image
28
+ self._should_stop = False
29
+ self.scale_factor = 1.0 # Track scaling factor for coordinate transformation
30
+
31
+ def stop(self):
32
+ """Request the worker to stop."""
33
+ self._should_stop = True
34
+
35
+ def get_scale_factor(self):
36
+ """Get the scale factor used for image resizing."""
37
+ return self.scale_factor
38
+
39
+ def run(self):
40
+ """Run SAM update in background thread."""
41
+ try:
42
+ if self._should_stop:
43
+ return
44
+
45
+ if self.operate_on_view and self.current_image is not None:
46
+ # Use the provided modified image
47
+ if self._should_stop:
48
+ return
49
+
50
+ # Optimize image size for faster SAM processing
51
+ image = self.current_image
52
+ original_height, original_width = image.shape[:2]
53
+ max_size = 1024
54
+
55
+ if original_height > max_size or original_width > max_size:
56
+ # Calculate scaling factor
57
+ self.scale_factor = min(
58
+ max_size / original_width, max_size / original_height
59
+ )
60
+ new_width = int(original_width * self.scale_factor)
61
+ new_height = int(original_height * self.scale_factor)
62
+
63
+ # Resize using OpenCV for speed
64
+ image = cv2.resize(
65
+ image, (new_width, new_height), interpolation=cv2.INTER_AREA
66
+ )
67
+ else:
68
+ self.scale_factor = 1.0
69
+
70
+ if self._should_stop:
71
+ return
72
+
73
+ # Set image from numpy array (FIXED: use resized image, not original)
74
+ self.model_manager.set_image_from_array(image)
75
+ else:
76
+ # Load original image
77
+ pixmap = QPixmap(self.image_path)
78
+ if pixmap.isNull():
79
+ self.error.emit("Failed to load image")
80
+ return
81
+
82
+ if self._should_stop:
83
+ return
84
+
85
+ original_width = pixmap.width()
86
+ original_height = pixmap.height()
87
+
88
+ # Optimize image size for faster SAM processing
89
+ max_size = 1024
90
+ if original_width > max_size or original_height > max_size:
91
+ # Calculate scaling factor
92
+ self.scale_factor = min(
93
+ max_size / original_width, max_size / original_height
94
+ )
95
+
96
+ # Scale down while maintaining aspect ratio
97
+ scaled_pixmap = pixmap.scaled(
98
+ max_size,
99
+ max_size,
100
+ Qt.AspectRatioMode.KeepAspectRatio,
101
+ Qt.TransformationMode.SmoothTransformation,
102
+ )
103
+
104
+ # Convert to numpy array for SAM
105
+ qimage = scaled_pixmap.toImage()
106
+ width = qimage.width()
107
+ height = qimage.height()
108
+ ptr = qimage.bits()
109
+ ptr.setsize(height * width * 4)
110
+ arr = np.array(ptr).reshape(height, width, 4)
111
+ # Convert RGBA to RGB
112
+ image_array = arr[:, :, :3]
113
+
114
+ if self._should_stop:
115
+ return
116
+
117
+ # FIXED: Use the resized image array, not original path
118
+ self.model_manager.set_image_from_array(image_array)
119
+ else:
120
+ self.scale_factor = 1.0
121
+ # For images that don't need resizing, use original path
122
+ self.model_manager.set_image_from_path(self.image_path)
123
+
124
+ if not self._should_stop:
125
+ self.finished.emit()
126
+
127
+ except Exception as e:
128
+ if not self._should_stop:
129
+ self.error.emit(str(e))
@@ -0,0 +1,61 @@
1
+ """Worker thread for initializing single-view SAM model in background."""
2
+
3
+ import os
4
+
5
+ from PyQt6.QtCore import QThread, pyqtSignal
6
+
7
+
8
+ class SingleViewSAMInitWorker(QThread):
9
+ """Worker thread for initializing single-view SAM model in background."""
10
+
11
+ model_initialized = pyqtSignal(object) # model_instance
12
+ finished = pyqtSignal()
13
+ error = pyqtSignal(str)
14
+ progress = pyqtSignal(str) # status message
15
+
16
+ def __init__(self, model_manager, default_model_type, custom_model_path=None):
17
+ super().__init__()
18
+ self.model_manager = model_manager
19
+ self.default_model_type = default_model_type
20
+ self.custom_model_path = custom_model_path
21
+ self._should_stop = False
22
+
23
+ def stop(self):
24
+ """Stop the worker gracefully."""
25
+ self._should_stop = True
26
+
27
+ def run(self):
28
+ """Initialize SAM model in background."""
29
+ try:
30
+ if self._should_stop:
31
+ return
32
+
33
+ if self.custom_model_path:
34
+ # Load custom model
35
+ model_name = os.path.basename(self.custom_model_path)
36
+ self.progress.emit(f"Loading {model_name}...")
37
+
38
+ success = self.model_manager.load_custom_model(self.custom_model_path)
39
+ if not success:
40
+ raise Exception(f"Failed to load custom model: {model_name}")
41
+
42
+ sam_model = self.model_manager.sam_model
43
+ else:
44
+ # Initialize the default model
45
+ self.progress.emit("Initializing AI model...")
46
+ sam_model = self.model_manager.initialize_default_model(
47
+ self.default_model_type
48
+ )
49
+
50
+ if self._should_stop:
51
+ return
52
+
53
+ if sam_model and sam_model.is_loaded:
54
+ self.model_initialized.emit(sam_model)
55
+ self.progress.emit("AI model initialized")
56
+ else:
57
+ self.error.emit("Model failed to load")
58
+
59
+ except Exception as e:
60
+ if not self._should_stop:
61
+ self.error.emit(f"Failed to load AI model: {str(e)}")