|
|
""" |
|
|
Utility functions for segmentation visualization and I/O. |
|
|
""" |
|
|
|
|
|
import numpy as np |
|
|
import cv2 |
|
|
from PIL import Image |
|
|
from typing import Tuple |
|
|
|
|
|
|
|
|
def visualize_mask( |
|
|
image: Image.Image, |
|
|
mask: np.ndarray, |
|
|
alpha: float = 0.5, |
|
|
color: Tuple[int, int, int] = (255, 0, 0) |
|
|
) -> Image.Image: |
|
|
""" |
|
|
Overlay segmentation mask on image. |
|
|
|
|
|
Args: |
|
|
image: PIL Image |
|
|
mask: Binary mask (H, W) |
|
|
alpha: Transparency (0-1) |
|
|
color: RGB color tuple for mask |
|
|
|
|
|
Returns: |
|
|
Image with mask overlay |
|
|
""" |
|
|
|
|
|
img_array = np.array(image) |
|
|
|
|
|
|
|
|
colored_mask = np.zeros_like(img_array) |
|
|
colored_mask[mask > 0.5] = color |
|
|
|
|
|
|
|
|
result = cv2.addWeighted(img_array, 1.0, colored_mask, alpha, 0) |
|
|
|
|
|
return Image.fromarray(result) |
|
|
|
|
|
|
|
|
def save_mask(mask: np.ndarray, output_path: str): |
|
|
""" |
|
|
Save mask as image (white for ROI, black for background). |
|
|
|
|
|
Args: |
|
|
mask: Binary mask array (H, W) |
|
|
output_path: Path to save mask image |
|
|
""" |
|
|
mask_img = (mask * 255).astype(np.uint8) |
|
|
Image.fromarray(mask_img).save(output_path) |
|
|
|
|
|
|
|
|
def load_mask(mask_path: str) -> np.ndarray: |
|
|
""" |
|
|
Load mask from image file. |
|
|
|
|
|
Args: |
|
|
mask_path: Path to mask image |
|
|
|
|
|
Returns: |
|
|
Binary mask as numpy array (H, W) with values 0 or 1 |
|
|
""" |
|
|
mask_img = Image.open(mask_path).convert('L') |
|
|
mask = np.array(mask_img).astype(np.float32) / 255.0 |
|
|
return mask |
|
|
|
|
|
|
|
|
def calculate_roi_stats(mask: np.ndarray) -> dict: |
|
|
""" |
|
|
Calculate statistics about ROI coverage. |
|
|
|
|
|
Args: |
|
|
mask: Binary mask (H, W) |
|
|
|
|
|
Returns: |
|
|
Dictionary with statistics: |
|
|
- roi_pixels: Number of ROI pixels |
|
|
- total_pixels: Total number of pixels |
|
|
- roi_percentage: Percentage of image covered by ROI |
|
|
""" |
|
|
roi_pixels = int(np.sum(mask > 0.5)) |
|
|
total_pixels = int(mask.size) |
|
|
roi_percentage = (roi_pixels / total_pixels) * 100 |
|
|
|
|
|
return { |
|
|
'roi_pixels': roi_pixels, |
|
|
'total_pixels': total_pixels, |
|
|
'roi_percentage': roi_percentage |
|
|
} |
|
|
|