imagebaker 0.0.49__py3-none-any.whl → 0.0.51__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,174 @@
1
+ from imagebaker.core.defs import PredictionResult
2
+
3
+ import cv2
4
+ import numpy as np
5
+ from typing import List
6
+
7
+
8
+ def annotate_detection(
9
+ image: np.ndarray,
10
+ results: List[PredictionResult],
11
+ color_map: dict[str, tuple[int, int, int]],
12
+ box_thickness: int = 2,
13
+ font_face: int = cv2.FONT_HERSHEY_SIMPLEX,
14
+ text_scale: float = 0.5,
15
+ text_thickness: int = 1,
16
+ ) -> np.ndarray:
17
+ """
18
+ Draw bounding boxes and labels on the image
19
+
20
+ Args:
21
+ image: The original image as a numpy array
22
+ results: List of PredictionResult objects
23
+
24
+ Returns:
25
+ Annotated image as a numpy array
26
+ """
27
+ annotated_image = image.copy()
28
+
29
+ for result in results:
30
+ # Extract data from result
31
+ box = result.rectangle # [x1, y1, x2, y2]
32
+ score = result.score
33
+ class_name = result.class_name
34
+
35
+ if not box:
36
+ continue
37
+
38
+ # Get color for this class
39
+ color = color_map.get(
40
+ result.class_name, (0, 255, 0)
41
+ ) # Default to green if not found
42
+
43
+ # Draw bounding box
44
+ cv2.rectangle(
45
+ annotated_image,
46
+ (box[0], box[1]),
47
+ (box[2], box[3]),
48
+ color,
49
+ box_thickness,
50
+ )
51
+
52
+ # Prepare label text with class name and score
53
+ label_text = f"{class_name}: {score:.2f}"
54
+
55
+ # Calculate text size to create background rectangle
56
+ (text_width, text_height), baseline = cv2.getTextSize(
57
+ label_text,
58
+ font_face,
59
+ text_scale,
60
+ text_thickness,
61
+ )
62
+
63
+ # Draw text background
64
+ cv2.rectangle(
65
+ annotated_image,
66
+ (box[0], box[1] - text_height - 5),
67
+ (box[0] + text_width, box[1]),
68
+ color,
69
+ -1, # Fill the rectangle
70
+ )
71
+
72
+ # Draw text
73
+ cv2.putText(
74
+ annotated_image,
75
+ label_text,
76
+ (box[0], box[1] - 5),
77
+ font_face,
78
+ text_scale,
79
+ (255, 255, 255), # White text
80
+ text_thickness,
81
+ )
82
+
83
+ return annotated_image
84
+
85
+
86
+ def annotate_segmentation(
87
+ image: np.ndarray,
88
+ results: List[PredictionResult],
89
+ color_map: dict[int, tuple[int, int, int]],
90
+ contour_thickness: int = 2,
91
+ mask_opacity: float = 0.5,
92
+ font_face: int = cv2.FONT_HERSHEY_SIMPLEX,
93
+ text_scale: float = 0.5,
94
+ text_thickness: int = 1,
95
+ ) -> np.ndarray:
96
+ """
97
+ Draw segmentation masks and contours on the image
98
+ """
99
+ annotated_image = image.copy()
100
+ mask_overlay = np.zeros_like(image)
101
+
102
+ for i, result in enumerate(results):
103
+ if (result.polygon is not None) or not result.mask:
104
+ continue
105
+
106
+ # Get color for this mask
107
+ color_idx = i % len(color_map)
108
+ color = color_map[color_idx]
109
+
110
+ # Create mask from polygons
111
+ mask = np.zeros((image.shape[0], image.shape[1]), dtype=np.uint8)
112
+ for poly in result.polygon:
113
+ poly_np = np.array(poly, dtype=np.int32).reshape((-1, 1, 2))
114
+ cv2.fillPoly(mask, [poly_np], 1)
115
+
116
+ # Apply color to mask overlay
117
+ color_mask = np.zeros_like(image)
118
+ color_mask[mask == 1] = color
119
+ mask_overlay = cv2.addWeighted(mask_overlay, 1.0, color_mask, 1.0, 0)
120
+
121
+ # Draw contours
122
+ for poly in result.polygon:
123
+ poly_np = np.array(poly, dtype=np.int32).reshape((-1, 1, 2))
124
+ cv2.polylines(
125
+ annotated_image,
126
+ [poly_np],
127
+ True,
128
+ color,
129
+ contour_thickness,
130
+ )
131
+
132
+ # Add label text
133
+ label_position = (
134
+ result.polygon[0][0] if result.polygon and result.polygon[0] else [10, 10]
135
+ )
136
+ label_text = f"{result.class_id}: {result.score:.2f}"
137
+
138
+ # Draw text background
139
+ (text_width, text_height), baseline = cv2.getTextSize(
140
+ label_text,
141
+ font_face,
142
+ text_scale,
143
+ text_thickness,
144
+ )
145
+
146
+ cv2.rectangle(
147
+ annotated_image,
148
+ (label_position[0], label_position[1] - text_height - 5),
149
+ (label_position[0] + text_width, label_position[1]),
150
+ color,
151
+ -1, # Fill the rectangle
152
+ )
153
+
154
+ # Draw text
155
+ cv2.putText(
156
+ annotated_image,
157
+ label_text,
158
+ (label_position[0], label_position[1] - 5),
159
+ font_face,
160
+ text_scale,
161
+ (255, 255, 255), # White text
162
+ text_thickness,
163
+ )
164
+
165
+ # Blend mask overlay with original image
166
+ annotated_image = cv2.addWeighted(
167
+ annotated_image,
168
+ 1.0,
169
+ mask_overlay,
170
+ mask_opacity,
171
+ 0,
172
+ )
173
+
174
+ return annotated_image
@@ -175,9 +175,15 @@ class MainWindow(QMainWindow):
175
175
  self.status_bar.showMessage(status_text)
176
176
 
177
177
  def closeEvent(self, event):
178
- # Clean up tabs first
179
- if hasattr(self, "layerify_tab"):
180
- self.layerify_tab.deleteLater()
181
- if hasattr(self, "baker_tab"):
182
- self.baker_tab.deleteLater()
183
- super().closeEvent(event)
178
+ logger.info("Closing the application.")
179
+ if self.layerify_config.cleanup_on_exit:
180
+ import shutil
181
+
182
+ if self.layerify_config.bake_dir.exists():
183
+ shutil.rmtree(self.layerify_config.bake_dir)
184
+ logger.info(f"Deleted bake directory: {self.layerify_config.bake_dir}")
185
+ if self.layerify_config.cache_dir.exists():
186
+ shutil.rmtree(self.layerify_config.cache_dir)
187
+ logger.info(
188
+ f"Deleted cache directory: {self.layerify_config.cache_dir}"
189
+ )
@@ -49,10 +49,23 @@ class BakerWorker(QObject):
49
49
  top_left = QPointF(sys.maxsize, sys.maxsize)
50
50
  bottom_right = QPointF(-sys.maxsize, -sys.maxsize)
51
51
 
52
+ # contains all states in currenct step
52
53
  for state in states:
53
54
  layer = self._get_layer(state.layer_id)
54
55
  if layer and layer.visible and not layer.image.isNull():
56
+ update_opacities = False
57
+ logger.debug(
58
+ f"Updating layer {layer.layer_name} with state: {state}"
59
+ )
60
+
61
+ if (
62
+ layer.edge_width != state.edge_width
63
+ or layer.edge_opacity != state.edge_opacity
64
+ ):
65
+ update_opacities = True
55
66
  layer.layer_state = state
67
+ if update_opacities:
68
+ layer._apply_edge_opacity()
56
69
  layer.update()
57
70
 
58
71
  transform = QTransform()
@@ -211,6 +224,8 @@ class BakerWorker(QObject):
211
224
  self.finished.emit(results)
212
225
 
213
226
  except Exception as e:
227
+ import traceback
228
+
214
229
  logger.error(f"Error in BakerWorker: {e}")
215
230
  self.error.emit(str(e))
216
231
  traceback.print_exc()
@@ -235,9 +250,14 @@ class BakerWorker(QObject):
235
250
  new_annotation.points = ann.points
236
251
  elif ann.rectangle:
237
252
  xywhs = mask_to_rectangles(alpha_channel, merge_rectangles=True)
238
- new_annotation.rectangle = QRectF(
239
- xywhs[0][0], xywhs[0][1], xywhs[0][2], xywhs[0][3]
240
- )
253
+ if len(xywhs) == 0:
254
+ logger.info("No rectangles found")
255
+ # return None
256
+ else:
257
+ logger.info(f"Found {len(xywhs)} rectangles")
258
+ new_annotation.rectangle = QRectF(
259
+ xywhs[0][0], xywhs[0][1], xywhs[0][2], xywhs[0][3]
260
+ )
241
261
  elif ann.polygon:
242
262
  polygon = mask_to_polygons(alpha_channel, merge_polygons=True)
243
263
  poly = QPolygonF([QPointF(p[0], p[1]) for p in polygon[0]])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: imagebaker
3
- Version: 0.0.49
3
+ Version: 0.0.51
4
4
  Summary: A package for baking images.
5
5
  Home-page: https://github.com/q-viper/Image-Baker
6
6
  Author: Ramkrishna Acharya
@@ -35,7 +35,7 @@ Requires-Dist: mkdocs-awesome-pages-plugin; extra == "docs"
35
35
  ![code size in bytes](https://img.shields.io/github/languages/code-size/q-viper/image-baker)
36
36
  <!-- ![Tests](https://github.com/q-viper/SmokeSim/actions/workflows/test-on-push.yml/badge.svg) -->
37
37
  ![Code Formatting](https://github.com/q-viper/image-baker/actions/workflows/black-formatter.yml/badge.svg)
38
-
38
+ [![PyPI version](https://img.shields.io/pypi/v/imagebaker.svg)](https://pypi.org/imagebaker/)
39
39
 
40
40
  <p align="center">
41
41
  <img src="assets/demo.gif" alt="Centered Demo" />
@@ -112,6 +112,9 @@ After cloning and going to the project directory, the following code should work
112
112
  * **Ctrl + D**: Draw Mode on Baker Tab. Drawing can happen on a selected or main layer.
113
113
  * **Ctrl + E**: Erase Mode on Baker Tab.
114
114
  * **Wheel**: Change the size of the drawing pointer.
115
+ * **Q**: Point mode on annotation.
116
+ * **W**: Polygon mode on annotation.
117
+ * **E**: Rectangle mode on annotation.
115
118
 
116
119
  ## Demo
117
120
  ### Annotation Page
@@ -0,0 +1,43 @@
1
+ imagebaker/__init__.py,sha256=zrrxwyzuqVNeIu3rVPrOGYf6SCd5kWsoGcdqqUfsYX4,258
2
+ imagebaker/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ imagebaker/core/configs/__init__.py,sha256=iyR_GOVMFw3XJSm7293YfyTnaLZa7pLQMfn5tGxVofI,31
4
+ imagebaker/core/configs/configs.py,sha256=hm0CHfMVTD9353wB61Df9bVUb898zQVIFjdoXELdJcc,5694
5
+ imagebaker/core/defs/__init__.py,sha256=NqV7gYIlRkaS7nx_UTNPSNZbdPrx4w-VurKOKyRLbKY,28
6
+ imagebaker/core/defs/defs.py,sha256=oZCkgqHgvE_yupUzD5IB_ZMoRhyTh0EdCR8Gmh6TMsI,8505
7
+ imagebaker/core/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ imagebaker/core/plugins/base_plugin.py,sha256=ROa1HTwV5LgGL-40CHKk_5MZYI5QAT1MzpYO7Fx-9P0,1084
9
+ imagebaker/core/plugins/cosine_plugin.py,sha256=IXBfvaoxrvf-hytg_dT1zFmOfDbcWXBZ7NvIFPJ2tWQ,1251
10
+ imagebaker/layers/__init__.py,sha256=q1kUDHhUXEGBOdu6CHDfqCnE2mraLHRqh0DFHYTbnRY,158
11
+ imagebaker/layers/annotable_layer.py,sha256=xkV6KTXN8-N6Wu3QAj5nQDMPZ4bRr673_fu5QuRKBj8,37128
12
+ imagebaker/layers/base_layer.py,sha256=1K7Nt6OPITrILj-p4I6Jf0eaesCpdeecOXGj_8oAQb8,30650
13
+ imagebaker/layers/canvas_layer.py,sha256=6quVe_Ieyz14zPL92xTfrinAT7X4yb9iyEl-f9SnQZU,42116
14
+ imagebaker/list_views/__init__.py,sha256=Aa9slE6do8eYgZp77wrofpd_mlBDwxgF3adMyHYFanE,144
15
+ imagebaker/list_views/annotation_list.py,sha256=w6jNMyo3nxhQKZx8MyusNvxs_R6Pj-b-YBI5e0APZVM,7528
16
+ imagebaker/list_views/canvas_list.py,sha256=JYSYR0peGyJFJ6amL1894KsUHETPUkR3qAWdGL50Lbc,6717
17
+ imagebaker/list_views/image_list.py,sha256=EX2YmoTRffBXTbbVnuflbdsxZQD8fgM2StSxg1a9ANA,5389
18
+ imagebaker/list_views/layer_list.py,sha256=fLx3Ry72fas1W5y_V84hSp41ARneogQN3qjfYTOcpxY,14476
19
+ imagebaker/list_views/layer_settings.py,sha256=0WVSCm_RSBKo4pCkYU5c2OYjb_sW8x0UUfFC4So26jQ,9752
20
+ imagebaker/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ imagebaker/models/base_model.py,sha256=4RyS4vShqWFHhdQDwYluwTPnRPEXjpZl9UjYY_w8NL0,4203
22
+ imagebaker/tabs/__init__.py,sha256=ijg7MA17RvcHA2AuZE4OgRJXWxjecaUAlfASKAoCQ6Q,86
23
+ imagebaker/tabs/baker_tab.py,sha256=yFQRiNmLIua5BvgW7Ysj5FrNbTLhGxqGRTRCABxeTtw,20493
24
+ imagebaker/tabs/layerify_tab.py,sha256=F3BK5XsVCteB-2zyFBKqeWyHgIif5cU3TBEMbuDH3QM,37415
25
+ imagebaker/utils/__init__.py,sha256=I1z5VVEf6QPOMvVkgVHDauQ9ew7tcTVguV4Kdi3Lk4Y,130
26
+ imagebaker/utils/image.py,sha256=2-wbwD3PMwefgswge0drFM1XfXE7yQ64lqZZ5PwyCWs,3165
27
+ imagebaker/utils/state_utils.py,sha256=Y2JVRGVfsoffwfA2lsCcqHwIxH_jOrEJAdH-oWfe2XE,3841
28
+ imagebaker/utils/transform_mask.py,sha256=k8MfTgM5-_U2TvDHQHRelz-leGFX6OcsllV6-J4BKfw,3651
29
+ imagebaker/utils/utils.py,sha256=MnJ4flxxwZbjROWJ5iKHnJxPSSMbfWRbF9GKfVcKutA,840
30
+ imagebaker/utils/vis.py,sha256=f7c44gm6g9ja5hgVeXKfOhHzxHdzXcIUwKiA1RZU_F8,4736
31
+ imagebaker/window/__init__.py,sha256=FIxtUR1qnbQMYzppQv7tEfv1-ueHhpu0Z7xuWZR794w,44
32
+ imagebaker/window/app.py,sha256=e6FGO_BnvkiQC9JN3AmqkgbF72zzZS0hc7PFc43QiVc,4725
33
+ imagebaker/window/main_window.py,sha256=-CP7q6xzkhv9Cl5RwUft1Rv8nIAuj_SLOiZDS2x6QJ4,7374
34
+ imagebaker/workers/__init__.py,sha256=XfXENwAYyNg9q_zR-gOsYJGjzwg_iIb_gING8ydnp9c,154
35
+ imagebaker/workers/baker_worker.py,sha256=_jWeyYAGoO2mfxXDn7fBm9tIA69OITewDVN0hSAt3Jc,11532
36
+ imagebaker/workers/layerify_worker.py,sha256=EOqKvhdACtf3y5Ljy6M7MvddAjlZW5DNfBFMtNPD-us,3223
37
+ imagebaker/workers/model_worker.py,sha256=Tlg6_D977iK-kuGCNdQY4OnGiP8QqWY7adpRNXZw4rA,1636
38
+ imagebaker-0.0.51.dist-info/LICENSE,sha256=1vkysFPOnT7y4LsoFTv9YsopIrQvBc2l6vUOfv4KKLc,1082
39
+ imagebaker-0.0.51.dist-info/METADATA,sha256=1DumEPL4LyKVeuV_tDwyepZ9PsreraeKSTEJBernVmw,6940
40
+ imagebaker-0.0.51.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
41
+ imagebaker-0.0.51.dist-info/entry_points.txt,sha256=IDjZHJCiiHpH5IUTByT2en0nMbnnnlrJZ5FPFehUvQM,61
42
+ imagebaker-0.0.51.dist-info/top_level.txt,sha256=Gg-eILTlqJXwVQr0saSwsx3-H4SPdZ2agBZaufe194s,11
43
+ imagebaker-0.0.51.dist-info/RECORD,,
@@ -1,41 +0,0 @@
1
- imagebaker/__init__.py,sha256=ep22Ki-KljDvYzGvAfrDe9UU77GWgfoAsLd7t0S273c,130
2
- imagebaker/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- imagebaker/core/configs/__init__.py,sha256=iyR_GOVMFw3XJSm7293YfyTnaLZa7pLQMfn5tGxVofI,31
4
- imagebaker/core/configs/configs.py,sha256=uyUhoHA9-Ult-vVtnLX-JNmeUght4mUUV80yKWzUO_o,5100
5
- imagebaker/core/defs/__init__.py,sha256=NqV7gYIlRkaS7nx_UTNPSNZbdPrx4w-VurKOKyRLbKY,28
6
- imagebaker/core/defs/defs.py,sha256=nIg2ZQADbpcyC0ZOl54L14yLZ38-SUnfMkklCDfhN3E,8257
7
- imagebaker/core/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
- imagebaker/core/plugins/base_plugin.py,sha256=ROa1HTwV5LgGL-40CHKk_5MZYI5QAT1MzpYO7Fx-9P0,1084
9
- imagebaker/core/plugins/cosine_plugin.py,sha256=IXBfvaoxrvf-hytg_dT1zFmOfDbcWXBZ7NvIFPJ2tWQ,1251
10
- imagebaker/layers/__init__.py,sha256=q1kUDHhUXEGBOdu6CHDfqCnE2mraLHRqh0DFHYTbnRY,158
11
- imagebaker/layers/annotable_layer.py,sha256=ZjDqNMEqB78iEAThotfksv8-xIK6NCr52fI26Rv6CXA,36627
12
- imagebaker/layers/base_layer.py,sha256=uncseSxTbLKnV84hAPbJLDbBMV0nu1gQ4N-SLHoGB6s,25486
13
- imagebaker/layers/canvas_layer.py,sha256=47R-g3NAzAQ720tWrIZUYIAupxImdORVYK5BFIRopqo,40414
14
- imagebaker/list_views/__init__.py,sha256=Aa9slE6do8eYgZp77wrofpd_mlBDwxgF3adMyHYFanE,144
15
- imagebaker/list_views/annotation_list.py,sha256=HGV6lGlkFjvJvvGnCcLuX1kkfXA0GL8wKo8jOXSBXec,7527
16
- imagebaker/list_views/canvas_list.py,sha256=JYSYR0peGyJFJ6amL1894KsUHETPUkR3qAWdGL50Lbc,6717
17
- imagebaker/list_views/image_list.py,sha256=NInkc893FGU7L6oSxy8KrWql-i6RB0BqvkroPAASjVw,4912
18
- imagebaker/list_views/layer_list.py,sha256=fLx3Ry72fas1W5y_V84hSp41ARneogQN3qjfYTOcpxY,14476
19
- imagebaker/list_views/layer_settings.py,sha256=38E39z-rEdl0YSe2C_k4wd5CgHPETQeJE5VvJLfFQ-k,8454
20
- imagebaker/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- imagebaker/models/base_model.py,sha256=ZfZ_VgP-jzfmEAdOycVtOYkr03m8EyXWdmK0-50MxIk,4197
22
- imagebaker/tabs/__init__.py,sha256=ijg7MA17RvcHA2AuZE4OgRJXWxjecaUAlfASKAoCQ6Q,86
23
- imagebaker/tabs/baker_tab.py,sha256=kIVoF4w_Ch1YNdHtHsNZKfr46tZWBDSj5xrrEkF1piM,20752
24
- imagebaker/tabs/layerify_tab.py,sha256=2IEdRyYHhNdY2696YiLcnWWKYN6gYwcKH6jsffYiL5M,32304
25
- imagebaker/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- imagebaker/utils/image.py,sha256=fq7g3DqSdjF9okxZ3fe5kF4Hxn32rqhvVqxy8yI5bnI,3067
27
- imagebaker/utils/state_utils.py,sha256=sI0R3ht4W_kQGwOpzUdBjy6M4PaKaAQlj-_MM6pidfM,3584
28
- imagebaker/utils/transform_mask.py,sha256=k8MfTgM5-_U2TvDHQHRelz-leGFX6OcsllV6-J4BKfw,3651
29
- imagebaker/window/__init__.py,sha256=FIxtUR1qnbQMYzppQv7tEfv1-ueHhpu0Z7xuWZR794w,44
30
- imagebaker/window/app.py,sha256=e6FGO_BnvkiQC9JN3AmqkgbF72zzZS0hc7PFc43QiVc,4725
31
- imagebaker/window/main_window.py,sha256=gpJ7DDuPmxhHh_6Rv3YH2J_1AqG7-NM8R3tKNYhFT3E,7030
32
- imagebaker/workers/__init__.py,sha256=XfXENwAYyNg9q_zR-gOsYJGjzwg_iIb_gING8ydnp9c,154
33
- imagebaker/workers/baker_worker.py,sha256=JyV1Hu4mzbYhmogc7K3U24adklmT3x3V0ZNMxe7iT-w,10697
34
- imagebaker/workers/layerify_worker.py,sha256=EOqKvhdACtf3y5Ljy6M7MvddAjlZW5DNfBFMtNPD-us,3223
35
- imagebaker/workers/model_worker.py,sha256=Tlg6_D977iK-kuGCNdQY4OnGiP8QqWY7adpRNXZw4rA,1636
36
- imagebaker-0.0.49.dist-info/LICENSE,sha256=1vkysFPOnT7y4LsoFTv9YsopIrQvBc2l6vUOfv4KKLc,1082
37
- imagebaker-0.0.49.dist-info/METADATA,sha256=BldoEWej9PUXnJVw_rpJEYFnjXosJIXWKJB2oY9ZLyI,6736
38
- imagebaker-0.0.49.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
39
- imagebaker-0.0.49.dist-info/entry_points.txt,sha256=IDjZHJCiiHpH5IUTByT2en0nMbnnnlrJZ5FPFehUvQM,61
40
- imagebaker-0.0.49.dist-info/top_level.txt,sha256=Gg-eILTlqJXwVQr0saSwsx3-H4SPdZ2agBZaufe194s,11
41
- imagebaker-0.0.49.dist-info/RECORD,,