| |
| """ |
| Developed by Nikhil Nageshwar Inturi |
| |
| This module provides PlotGenerator to process all masks in a directory: |
| - For each mask, find its image by matching name stem, then output: |
| 1) a binary mask PNG, |
| 2) an overlay PNG with colored mask + boundaries. |
| """ |
|
|
| import matplotlib.pyplot as plt |
| import numpy as np |
| from PIL import Image |
| from skimage.segmentation import find_boundaries |
| from pathlib import Path |
| import logging |
|
|
| class PlotGenerator: |
| """ |
| Process every .npy mask in mask_dir and generate |
| corresponding plots using images from image_dir. |
| """ |
|
|
| def __init__( |
| self, |
| image_dir: Path, |
| mask_dir: Path, |
| output_dir: Path, |
| overlay_color: tuple[int,int,int] = (238,144,144), |
| boundary_color: tuple[int,int,int] = (100,100,255), |
| alpha: float = 0.5 |
| ) -> None: |
| self.image_dir = Path(image_dir) |
| self.mask_dir = Path(mask_dir) |
| self.output_dir = Path(output_dir) |
| self.overlay_color = np.array(overlay_color, dtype=np.uint8) |
| self.boundary_color = np.array(boundary_color, dtype=np.uint8) |
| self.alpha = alpha |
| self.logger = logging.getLogger(self.__class__.__name__) |
| self.output_dir.mkdir(parents=True, exist_ok=True) |
|
|
| def run(self) -> None: |
| mask_paths = list(self.mask_dir.glob("*.npy")) |
| if not mask_paths: |
| self.logger.warning(f"No .npy masks found in {self.mask_dir}") |
| return |
|
|
| for mask_path in mask_paths: |
| stem = mask_path.stem |
| img_candidates = list(self.image_dir.glob(f"{stem}*.png")) |
| if not img_candidates: |
| self.logger.warning(f"No image found for mask '{stem}'") |
| continue |
| image_path = img_candidates[0] |
|
|
| img = np.array(Image.open(image_path).convert("RGB")) |
| mask = np.load(mask_path) |
|
|
| |
| binary = (mask > 0).astype(np.uint8) |
| plt.figure(figsize=(10,10)) |
| plt.imshow(binary, cmap='gray') |
| plt.axis('off') |
| plt.title(f"{stem} - Binary Mask") |
| out_gray = self.output_dir / f"{stem}_binary.png" |
| plt.savefig(out_gray, bbox_inches='tight', dpi=300) |
| plt.close() |
| self.logger.info(f"Saved binary mask plot: {out_gray.name}") |
|
|
| |
| overlay = img.copy() |
| mask_bool = mask > 0 |
| overlay[mask_bool] = ( |
| (1 - self.alpha) * img[mask_bool] + self.alpha * self.overlay_color |
| ).astype(np.uint8) |
| boundaries = find_boundaries(mask_bool, mode='outer') |
| overlay[boundaries] = self.boundary_color |
|
|
| plt.figure(figsize=(10,10)) |
| plt.imshow(overlay) |
| plt.axis('off') |
| plt.title(f"{stem} - Mask Overlay") |
| out_overlay = self.output_dir / f"{stem}_overlay.png" |
| plt.savefig(out_overlay, bbox_inches='tight', dpi=300) |
| plt.close() |
| self.logger.info(f"Saved overlay plot: {out_overlay.name}") |
|
|
|
|
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
|
|
|
|
|
|
| |
| |
|
|
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
|
|
| |
| |
|
|
|
|
|
|
|
|
| |
| |
|
|
| |
| |
| |
|
|
|
|
|
|
|
|
|
|
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| |
| |
|
|
| |
| |
|
|
| |
| |
|
|
| |
| |
|
|
| |
| |
|
|
| |
| |
|
|
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| |
|
|