Fahimeh Orvati Nia commited on
Commit
5b8812f
·
1 Parent(s): 916b83d
Files changed (1) hide show
  1. sorghum_pipeline/output/manager.py +51 -5
sorghum_pipeline/output/manager.py CHANGED
@@ -55,7 +55,8 @@ class OutputManager:
55
  try:
56
  mask = plant_data.get('mask')
57
  if isinstance(mask, np.ndarray):
58
- cv2.imwrite(str(results_dir / 'mask.png'), mask)
 
59
  except Exception as e:
60
  logger.error(f"Failed to save mask: {e}")
61
 
@@ -67,7 +68,8 @@ class OutputManager:
67
  overlay = self._create_overlay(base_image, mask)
68
  # Convert BGR→RGB for correct viewing in standard image viewers
69
  overlay_rgb = cv2.cvtColor(overlay, cv2.COLOR_BGR2RGB)
70
- cv2.imwrite(str(results_dir / 'overlay.png'), overlay_rgb)
 
71
  except Exception as e:
72
  logger.error(f"Failed to save overlay: {e}")
73
 
@@ -80,7 +82,8 @@ class OutputManager:
80
  base_image = self._normalize_to_uint8(base_image.astype(np.float64))
81
  # Convert BGR→RGB for human viewing
82
  comp_rgb = cv2.cvtColor(base_image, cv2.COLOR_BGR2RGB)
83
- cv2.imwrite(str(results_dir / 'composite.png'), comp_rgb)
 
84
  except Exception as e:
85
  logger.error(f"Failed to save composite: {e}")
86
 
@@ -105,6 +108,7 @@ class OutputManager:
105
  ax.set_axis_off()
106
  ax.set_facecolor('white')
107
  im = ax.imshow(masked, cmap=cmap, vmin=vmin, vmax=vmax)
 
108
  # add colorbar
109
  cbar = fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
110
  cbar.ax.tick_params(labelsize=8)
@@ -130,6 +134,7 @@ class OutputManager:
130
  ax.set_axis_off()
131
  ax.set_facecolor('white')
132
  im = ax.imshow(img, cmap='gray', vmin=0, vmax=255)
 
133
  cbar = fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
134
  cbar.ax.tick_params(labelsize=8)
135
  plt.tight_layout()
@@ -146,7 +151,8 @@ class OutputManager:
146
  images = morph.get('images', {})
147
  size_img = images.get('size_analysis')
148
  if isinstance(size_img, np.ndarray) and size_img.size > 0:
149
- cv2.imwrite(str(results_dir / 'size.size_analysis.png'), size_img)
 
150
  except Exception as e:
151
  logger.error(f"Failed to save size analysis: {e}")
152
 
@@ -175,4 +181,44 @@ class OutputManager:
175
  normalized = (arr - arr.min()) / (ptp + 1e-6) * 255
176
  else:
177
  normalized = np.zeros_like(arr)
178
- return np.clip(normalized, 0, 255).astype(np.uint8)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  try:
56
  mask = plant_data.get('mask')
57
  if isinstance(mask, np.ndarray):
58
+ titled = self._add_title_banner(mask, 'Mask')
59
+ cv2.imwrite(str(results_dir / 'mask.png'), titled)
60
  except Exception as e:
61
  logger.error(f"Failed to save mask: {e}")
62
 
 
68
  overlay = self._create_overlay(base_image, mask)
69
  # Convert BGR→RGB for correct viewing in standard image viewers
70
  overlay_rgb = cv2.cvtColor(overlay, cv2.COLOR_BGR2RGB)
71
+ titled = self._add_title_banner(overlay_rgb, 'Segmentation Overlay')
72
+ cv2.imwrite(str(results_dir / 'overlay.png'), titled)
73
  except Exception as e:
74
  logger.error(f"Failed to save overlay: {e}")
75
 
 
82
  base_image = self._normalize_to_uint8(base_image.astype(np.float64))
83
  # Convert BGR→RGB for human viewing
84
  comp_rgb = cv2.cvtColor(base_image, cv2.COLOR_BGR2RGB)
85
+ titled = self._add_title_banner(comp_rgb, 'Composite (Segmentation Input)')
86
+ cv2.imwrite(str(results_dir / 'composite.png'), titled)
87
  except Exception as e:
88
  logger.error(f"Failed to save composite: {e}")
89
 
 
108
  ax.set_axis_off()
109
  ax.set_facecolor('white')
110
  im = ax.imshow(masked, cmap=cmap, vmin=vmin, vmax=vmax)
111
+ ax.set_title(f"{name}", fontsize=12, fontweight='bold', pad=8)
112
  # add colorbar
113
  cbar = fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
114
  cbar.ax.tick_params(labelsize=8)
 
134
  ax.set_axis_off()
135
  ax.set_facecolor('white')
136
  im = ax.imshow(img, cmap='gray', vmin=0, vmax=255)
137
+ ax.set_title('Texture: LBP (Green Band)', fontsize=12, fontweight='bold', pad=8)
138
  cbar = fig.colorbar(im, ax=ax, fraction=0.046, pad=0.04)
139
  cbar.ax.tick_params(labelsize=8)
140
  plt.tight_layout()
 
151
  images = morph.get('images', {})
152
  size_img = images.get('size_analysis')
153
  if isinstance(size_img, np.ndarray) and size_img.size > 0:
154
+ titled = self._add_title_banner(size_img, 'Morphology Size')
155
+ cv2.imwrite(str(results_dir / 'size.size_analysis.png'), titled)
156
  except Exception as e:
157
  logger.error(f"Failed to save size analysis: {e}")
158
 
 
181
  normalized = (arr - arr.min()) / (ptp + 1e-6) * 255
182
  else:
183
  normalized = np.zeros_like(arr)
184
+ return np.clip(normalized, 0, 255).astype(np.uint8)
185
+
186
+ def _add_title_banner(self, image: np.ndarray, title: str) -> np.ndarray:
187
+ """Add a top banner with centered title text to an image using OpenCV.
188
+ Supports grayscale or color images; returns a BGR image.
189
+ """
190
+ if image is None or image.size == 0:
191
+ return image
192
+
193
+ # Ensure 3-channel BGR for drawing
194
+ if image.ndim == 2:
195
+ base_bgr = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
196
+ elif image.ndim == 3 and image.shape[2] == 3:
197
+ base_bgr = image.copy()
198
+ elif image.ndim == 3 and image.shape[2] == 4:
199
+ base_bgr = cv2.cvtColor(image, cv2.COLOR_BGRA2BGR)
200
+ else:
201
+ # Fallback: normalize to uint8 then convert to BGR
202
+ norm = self._normalize_to_uint8(image.astype(np.float64))
203
+ base_bgr = cv2.cvtColor(norm, cv2.COLOR_GRAY2BGR)
204
+
205
+ h, w = base_bgr.shape[:2]
206
+ banner_height = max(30, int(0.08 * h))
207
+ banner = np.full((banner_height, w, 3), (245, 245, 245), dtype=np.uint8)
208
+
209
+ # Compose banner + image
210
+ composed = np.vstack([banner, base_bgr])
211
+
212
+ # Put centered title text
213
+ font = cv2.FONT_HERSHEY_SIMPLEX
214
+ font_scale = max(0.5, min(1.0, w / 800.0))
215
+ thickness = 1
216
+ text = str(title)
217
+ (tw, th), baseline = cv2.getTextSize(text, font, font_scale, thickness)
218
+ x = max(5, (w - tw) // 2)
219
+ y = (banner_height + th) // 2
220
+ # Slight shadow for readability
221
+ cv2.putText(composed, text, (x+1, y+1), font, font_scale, (0, 0, 0), thickness+1, cv2.LINE_AA)
222
+ cv2.putText(composed, text, (x, y), font, font_scale, (0, 80, 0), thickness+1, cv2.LINE_AA)
223
+
224
+ return composed