Fahimeh Orvati Nia commited on
Commit
2ff67cd
·
1 Parent(s): 69b6a19
Files changed (1) hide show
  1. sorghum_pipeline/output/manager.py +57 -1
sorghum_pipeline/output/manager.py CHANGED
@@ -153,6 +153,14 @@ class OutputManager:
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
 
@@ -221,4 +229,52 @@ class OutputManager:
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
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ else:
157
+ # Fallback: synthesize a simple size analysis from the mask if available
158
+ mask_for_size = plant_data.get('mask')
159
+ base_img_for_size = plant_data.get('composite')
160
+ if isinstance(mask_for_size, np.ndarray) and mask_for_size.size > 0:
161
+ synthesized = self._create_size_analysis_from_mask(mask_for_size, base_img_for_size)
162
+ titled = self._add_title_banner(synthesized, 'Morphology Size')
163
+ cv2.imwrite(str(results_dir / 'size.size_analysis.png'), titled)
164
  except Exception as e:
165
  logger.error(f"Failed to save size analysis: {e}")
166
 
 
229
  cv2.putText(composed, text, (x+1, y+1), font, font_scale, (0, 0, 0), thickness+1, cv2.LINE_AA)
230
  cv2.putText(composed, text, (x, y), font, font_scale, (0, 80, 0), thickness+1, cv2.LINE_AA)
231
 
232
+ return composed
233
+
234
+ def _create_size_analysis_from_mask(self, mask: np.ndarray, base_image: Any = None) -> np.ndarray:
235
+ """Create a simple size analysis visualization from a binary mask.
236
+ Draws contours and prints pixel area. If base_image is provided, overlays on it; otherwise uses a white canvas.
237
+ """
238
+ if mask is None or mask.size == 0:
239
+ return np.zeros((1, 1, 3), dtype=np.uint8)
240
+
241
+ # Prepare base image
242
+ if isinstance(base_image, np.ndarray) and base_image.size > 0:
243
+ img = base_image
244
+ if img.dtype != np.uint8:
245
+ img = self._normalize_to_uint8(img.astype(np.float64))
246
+ if img.ndim == 2:
247
+ base_bgr = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
248
+ elif img.ndim == 3 and img.shape[2] == 3:
249
+ base_bgr = img.copy()
250
+ elif img.ndim == 3 and img.shape[2] == 4:
251
+ base_bgr = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
252
+ else:
253
+ norm = self._normalize_to_uint8(img.astype(np.float64))
254
+ base_bgr = cv2.cvtColor(norm, cv2.COLOR_GRAY2BGR)
255
+ else:
256
+ h, w = mask.shape[:2]
257
+ base_bgr = np.full((h, w, 3), 255, dtype=np.uint8)
258
+
259
+ # Ensure binary mask
260
+ if mask.ndim == 3 and mask.shape[2] == 3:
261
+ gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
262
+ else:
263
+ gray = mask.astype(np.uint8)
264
+ _, bin_mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
265
+
266
+ # Contours and area
267
+ contours, _ = cv2.findContours(bin_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
268
+ cv2.drawContours(base_bgr, contours, -1, (0, 0, 255), 1)
269
+ area_px = int(cv2.countNonZero(bin_mask))
270
+
271
+ # Bounding box for the largest contour
272
+ if contours:
273
+ largest = max(contours, key=cv2.contourArea)
274
+ x, y, w, h = cv2.boundingRect(largest)
275
+ cv2.rectangle(base_bgr, (x, y), (x + w, y + h), (255, 0, 0), 1)
276
+
277
+ # Put area text
278
+ cv2.putText(base_bgr, f"Area: {area_px} px", (10, 24), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2, cv2.LINE_AA)
279
+
280
+ return base_bgr