Spaces:
Sleeping
Sleeping
| """ | |
| Visualization module for anomaly detection results. | |
| This module provides functions to create visual outputs including heatmaps, | |
| overlays, and predicted mask visualizations. | |
| """ | |
| import cv2 | |
| import numpy as np | |
| from config import HEATMAP_ALPHA, OVERLAY_ALPHA | |
| def create_overlay(image: np.ndarray, heatmap: np.ndarray, model_name: str) -> np.ndarray: | |
| """ | |
| Create an overlay of the heatmap on the original image. | |
| Args: | |
| image: Original image in RGB format (H, W, 3) | |
| heatmap: Normalized heatmap (H, W) in range [0, 1] | |
| model_name: Name of the model for model-specific handling | |
| Returns: | |
| Overlay image in RGB format (H, W, 3) | |
| """ | |
| image_resized = cv2.resize(image, (256, 256)) | |
| # Convert heatmap to uint8 and apply colormap | |
| heatmap_uint8 = (heatmap * 255).astype(np.uint8) | |
| heatmap_color = cv2.applyColorMap(heatmap_uint8, cv2.COLORMAP_JET) | |
| heatmap_color = cv2.cvtColor(heatmap_color, cv2.COLOR_BGR2RGB) | |
| # Model-specific handling for EfficientAD padding | |
| if model_name == "efficientad": | |
| # Mask out zero values (padding) to show original image | |
| mask_0 = (heatmap == 0)[..., np.newaxis] | |
| overlay = np.where(mask_0, image_resized, cv2.addWeighted(image_resized, OVERLAY_ALPHA, heatmap_color, HEATMAP_ALPHA, 0)) | |
| else: | |
| overlay = cv2.addWeighted(image_resized, OVERLAY_ALPHA, heatmap_color, HEATMAP_ALPHA, 0) | |
| return overlay | |
| def create_mask_visualization(image: np.ndarray, mask: np.ndarray) -> np.ndarray: | |
| """ | |
| Create a visualization of the predicted mask overlaid on the image. | |
| Args: | |
| image: Original image in RGB format (H, W, 3) | |
| mask: Binary mask (H, W) where non-zero values indicate anomaly | |
| Returns: | |
| Visualization image with semi-transparent red mask and contours | |
| """ | |
| image_resized = cv2.resize(image, (256, 256)) | |
| vis_img = image_resized.copy() | |
| if np.any(mask): | |
| # Create a red color mask | |
| color_mask = np.zeros_like(image_resized) | |
| color_mask[mask > 0] = [255, 0, 0] # RGB Red | |
| # Blend with original image | |
| vis_img = cv2.addWeighted(vis_img, 0.7, color_mask, 0.3, 0) | |
| # Draw contours | |
| contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) | |
| cv2.drawContours(vis_img, contours, -1, (255, 255, 255), 2) | |
| return vis_img | |
| def draw_bounding_boxes(overlay: np.ndarray, mask_vis: np.ndarray, bboxes: list): | |
| """ | |
| Draw bounding boxes on both overlay and mask visualization images. | |
| Args: | |
| overlay: Overlay image to draw on (modified in-place) | |
| mask_vis: Mask visualization image to draw on (modified in-place) | |
| bboxes: List of bounding boxes [x1, y1, x2, y2] | |
| """ | |
| for (x1, y1, x2, y2) in bboxes: | |
| # Green boxes on overlay | |
| cv2.rectangle(overlay, (x1, y1), (x2, y2), (0, 255, 0), 2) | |
| # Blue boxes on mask visualization | |
| cv2.rectangle(mask_vis, (x1, y1), (x2, y2), (255, 0, 0), 2) | |
| def create_heatmap_color(heatmap: np.ndarray, model_name: str) -> np.ndarray: | |
| """ | |
| Create a colored heatmap image suitable for display. | |
| Args: | |
| heatmap: Normalized heatmap (H, W) in range [0, 1] | |
| model_name: Name of the model for model-specific handling | |
| Returns: | |
| Colored heatmap in RGB format (H, W, 3) | |
| """ | |
| heatmap_uint8 = (heatmap * 255).astype(np.uint8) | |
| heatmap_color = cv2.applyColorMap(heatmap_uint8, cv2.COLORMAP_JET) | |
| heatmap_color = cv2.cvtColor(heatmap_color, cv2.COLOR_BGR2RGB) | |
| # For EfficientAD, make padding (zero values) black | |
| if model_name == "efficientad": | |
| heatmap_color[heatmap == 0] = [0, 0, 0] | |
| return heatmap_color | |
| def create_visuals( | |
| image: np.ndarray, | |
| heatmap: np.ndarray, | |
| mask: np.ndarray, | |
| bboxes: list, | |
| model_name: str | |
| ) -> tuple: | |
| """ | |
| Create all visualization outputs for a single inference result. | |
| Args: | |
| image: Original input image in RGB format | |
| heatmap: Normalized heatmap (H, W) | |
| mask: Binary mask (H, W) | |
| bboxes: List of bounding boxes | |
| model_name: Name of the model | |
| Returns: | |
| tuple: (original_resized, heatmap_color, overlay, mask_vis) | |
| """ | |
| # Resize original image to 256x256 | |
| original_resized = cv2.resize(image, (256, 256)) | |
| # Create heatmap visualization | |
| heatmap_color = create_heatmap_color(heatmap, model_name) | |
| # Create overlay | |
| overlay = create_overlay(image, heatmap, model_name) | |
| # Create mask visualization | |
| mask_vis = create_mask_visualization(image, mask) | |
| # Draw bounding boxes on overlay and mask visualization | |
| draw_bounding_boxes(overlay, mask_vis, bboxes) | |
| return original_resized, heatmap_color, overlay, mask_vis | |