Spaces:
Paused
Paused
Download src/visualize.py from ahmedsharaf/ClothSeg: direct link, hf CLI and curl.
- Browser
- Download file 12.1 kB
-
https://huggingface.co/spaces/ahmedsharaf/ClothSeg/resolve/main/src/visualize.py
- Command line
-
hf download hf://spaces/ahmedsharaf/ClothSeg/src/visualize.py
-
curl -L -o visualize.py https://huggingface.co/spaces/ahmedsharaf/ClothSeg/resolve/main/src/visualize.py
12.1 kB
| from pathlib import Path | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| from matplotlib.colors import ListedColormap | |
| from matplotlib.patches import Patch | |
| from src.operations import remap_mask, create_overlay, to_binary_clothes, morphological_operations | |
| from src.utils import denormalize_image | |
| Path("assets").mkdir(parents=True, exist_ok=True) | |
| CLASS_NAMES = [ | |
| "Background", | |
| "Upper-Clothes", | |
| "Skirt", | |
| "Pants", | |
| "Dress" | |
| ] | |
| CLASS_COLORS = [ | |
| "#000000", # Background | |
| "#FF0000", # Upper-Clothes | |
| "#00FF00", # Skirt | |
| "#0000FF", # Pants | |
| "#FFFF00", # Dress | |
| ] | |
| SEGMENTATION_CMAP = ListedColormap(CLASS_COLORS) | |
| def colorize_mask(mask): | |
| """ | |
| Convert class-index mask into RGB colored mask. | |
| """ | |
| mask = np.asarray(mask).astype(np.uint8) | |
| colored_mask = np.zeros( | |
| (*mask.shape, 3), | |
| dtype=np.uint8 | |
| ) | |
| colors = [ | |
| (0, 0, 0), # Background | |
| (255, 0, 0), # Upper-Clothes | |
| (0, 255, 0), # Skirt | |
| (0, 0, 255), # Pants | |
| (255, 255, 0), # Dress | |
| ] | |
| for class_id, color in enumerate(colors): | |
| colored_mask[mask == class_id] = color | |
| return colored_mask | |
| def add_segmentation_legend(fig): | |
| legend_elements = [ | |
| Patch( | |
| facecolor=CLASS_COLORS[i], | |
| label=CLASS_NAMES[i] | |
| ) | |
| for i in range(len(CLASS_NAMES)) | |
| ] | |
| fig.legend( | |
| handles=legend_elements, | |
| loc="lower center", | |
| ncol=5, | |
| frameon=False | |
| ) | |
| def visualize_batch(images, masks, num_samples = 4, save_path="assets/visualization_batch.png"): | |
| num_samples = min(num_samples, len(images)) | |
| fig, axes = plt.subplots(2, num_samples, figsize = (4 * num_samples, 8)) | |
| if num_samples == 1: | |
| axes = np.expand_dims(axes, axis = 1) | |
| for i in range(num_samples): | |
| image = images[i].permute(1, 2, 0).cpu().numpy() | |
| image = denormalize_image(image) | |
| axes[0, i].imshow(image) | |
| axes[0, i].set_title("Image") | |
| axes[0, i].axis("off") | |
| mask = masks[i].cpu().numpy() | |
| axes[1, i].imshow(mask, cmap = SEGMENTATION_CMAP, vmin = 0, vmax = 4) | |
| axes[1, i].set_title("Mask") | |
| axes[1, i].axis("off") | |
| plt.tight_layout() | |
| plt.savefig(save_path, dpi=150, bbox_inches="tight") | |
| plt.close() | |
| def visualize_preprocessing_sample(image, mask, label_map, alpha=0.5, save_path="assets/preprocessing.png"): | |
| if hasattr(image, "permute"): | |
| image = image.permute(1, 2, 0).cpu().numpy() | |
| if hasattr(mask, "numpy"): | |
| mask = mask.cpu().numpy() | |
| # If image is uint8 -> convert to [0, 1] | |
| if image.dtype == np.uint8: | |
| image_display = image / 255.0 | |
| else: | |
| image_display = np.clip(image, 0, 1) | |
| remapped_mask = remap_mask(mask, label_map) | |
| overlay = create_overlay((image_display * 255).astype(np.uint8), remapped_mask, alpha=alpha) | |
| fig, axes = plt.subplots(1, 4, figsize=(16, 4)) | |
| axes[0].imshow(image_display) | |
| axes[0].set_title("Original Image") | |
| axes[0].axis("off") | |
| axes[1].imshow(mask, cmap=SEGMENTATION_CMAP, vmin=0, vmax=4) | |
| axes[1].set_title("Original Mask") | |
| axes[1].axis("off") | |
| axes[2].imshow(remapped_mask, cmap=SEGMENTATION_CMAP, vmin=0, vmax=4) | |
| axes[2].set_title("Remapped Mask") | |
| axes[2].axis("off") | |
| axes[3].imshow(overlay) | |
| axes[3].set_title("Overlay") | |
| axes[3].axis("off") | |
| plt.tight_layout() | |
| plt.savefig(save_path, dpi=150, bbox_inches="tight") | |
| plt.close() | |
| def visualize_random_samples(dataset, label_map, num_samples=4, alpha=0.5, save_path="assets/random_samples.png"): | |
| num_samples = min(num_samples, len(dataset)) | |
| indices = np.random.choice(len(dataset), size=num_samples, replace=False) | |
| fig, axes = plt.subplots(num_samples, 4, figsize=(16, 4 * num_samples)) | |
| if num_samples == 1: | |
| axes = np.expand_dims(axes, axis=0) | |
| for row, idx in enumerate(indices): | |
| sample = dataset[idx] | |
| image = sample["pixel_values"].convert("RGB") | |
| image = np.array(image, dtype=np.uint8) | |
| mask = np.array(sample["label"], dtype=np.uint8) | |
| remapped_mask = remap_mask(mask, label_map) | |
| overlay = create_overlay(image, remapped_mask, alpha=alpha) | |
| axes[row, 0].imshow(image) | |
| axes[row, 0].set_title(f"Image #{idx}") | |
| axes[row, 0].axis("off") | |
| axes[row, 1].imshow(mask, cmap="tab10") | |
| axes[row, 1].set_title("Original Mask") | |
| axes[row, 1].axis("off") | |
| axes[row, 2].imshow(remapped_mask, cmap="tab10", vmin=0, vmax=4) | |
| axes[row, 2].set_title("Remapped Mask") | |
| axes[row, 2].axis("off") | |
| axes[row, 3].imshow(overlay) | |
| axes[row, 3].set_title("Overlay") | |
| axes[row, 3].axis("off") | |
| plt.tight_layout() | |
| plt.savefig(save_path, dpi=150, bbox_inches="tight") | |
| plt.close() | |
| def visualize_prediction( | |
| image, | |
| gt_mask, | |
| pred_mask, | |
| opening_kernel=3, | |
| closing_kernel=11, | |
| opening_iterations=1, | |
| closing_iterations=1, | |
| alpha=0.5, | |
| save_path="assets/prediction.png" | |
| ): | |
| # Convert image to numpy | |
| if hasattr(image, "permute"): | |
| image = image.permute(1, 2, 0).cpu().numpy() | |
| # Convert masks to numpy | |
| if hasattr(gt_mask, "numpy"): | |
| gt_mask = gt_mask.cpu().numpy() | |
| if hasattr(pred_mask, "numpy"): | |
| pred_mask = pred_mask.cpu().numpy() | |
| # If image is normalized, convert it back to display range | |
| if image.dtype != np.uint8: | |
| image = np.clip(image, 0, 1) | |
| image = (image * 255).astype(np.uint8) | |
| # Ground Truth | |
| gt_mask = gt_mask.astype(np.uint8) | |
| # Prediction -> Binary | |
| pred_binary = to_binary_clothes(pred_mask) | |
| # Prediction -> Morphological Operations | |
| final_prediction = morphological_operations( | |
| pred_binary, | |
| opening_kernel=opening_kernel, | |
| closing_kernel=closing_kernel, | |
| opening_iterations=opening_iterations, | |
| closing_iterations=closing_iterations | |
| ) | |
| # Overlay | |
| overlay = create_overlay(image, final_prediction, alpha=alpha) | |
| # Visualization | |
| fig, axes = plt.subplots(1, 4, figsize=(16, 4)) | |
| axes[0].imshow(image) | |
| axes[0].set_title("Original Image") | |
| axes[0].axis("off") | |
| axes[1].imshow(gt_mask, cmap="tab10", vmin=0, vmax=4) | |
| axes[1].set_title("Ground Truth") | |
| axes[1].axis("off") | |
| axes[2].imshow(final_prediction, cmap="gray", vmin=0, vmax=1) | |
| axes[2].set_title("Final Prediction") | |
| axes[2].axis("off") | |
| axes[3].imshow(overlay) | |
| axes[3].set_title("Overlay") | |
| axes[3].axis("off") | |
| plt.tight_layout() | |
| plt.savefig(save_path, dpi=150, bbox_inches="tight") | |
| plt.close() | |
| def visualize_test_predictions( | |
| images, | |
| gt_masks, | |
| pred_masks, | |
| num_samples=4, | |
| opening_kernel=3, | |
| closing_kernel=11, | |
| opening_iterations=1, | |
| closing_iterations=1, | |
| alpha=0.5, | |
| save_path="assets/test_predictions.png" | |
| ): | |
| num_samples = min(num_samples, len(images)) | |
| fig, axes = plt.subplots(num_samples, 4, figsize=(16, 4 * num_samples)) | |
| if num_samples == 1: | |
| axes = np.expand_dims(axes, axis=0) | |
| for row in range(num_samples): | |
| image = images[row] | |
| gt_mask = gt_masks[row] | |
| pred_mask = pred_masks[row] | |
| # Convert image | |
| if hasattr(image, "permute"): | |
| image = image.permute(1, 2, 0).cpu().numpy() | |
| if image.dtype != np.uint8: | |
| image = np.clip(image, 0, 1) | |
| image = (image * 255).astype(np.uint8) | |
| # Convert masks | |
| if hasattr(gt_mask, "numpy"): | |
| gt_mask = gt_mask.cpu().numpy() | |
| if hasattr(pred_mask, "numpy"): | |
| pred_mask = pred_mask.cpu().numpy() | |
| gt_mask = gt_mask.astype(np.uint8) | |
| pred_mask = pred_mask.astype(np.uint8) | |
| # Binary prediction | |
| pred_binary = to_binary_clothes(pred_mask) | |
| # Morphological post-processing | |
| final_prediction = morphological_operations( | |
| pred_binary, | |
| opening_kernel=opening_kernel, | |
| closing_kernel=closing_kernel, | |
| opening_iterations=opening_iterations, | |
| closing_iterations=closing_iterations | |
| ) | |
| # Overlay | |
| overlay = create_overlay(image, final_prediction, alpha=alpha) | |
| # Original image | |
| axes[row, 0].imshow(image) | |
| axes[row, 0].set_title("Original Image") | |
| axes[row, 0].axis("off") | |
| # Ground truth | |
| axes[row, 1].imshow(gt_mask, cmap=SEGMENTATION_CMAP, vmin=0, vmax=4) | |
| axes[row, 1].set_title("Ground Truth") | |
| axes[row, 1].axis("off") | |
| # Final prediction | |
| axes[row, 2].imshow(final_prediction, cmap="gray", vmin=0, vmax=1) | |
| axes[row, 2].set_title("Final Prediction") | |
| axes[row, 2].axis("off") | |
| # Overlay | |
| axes[row, 3].imshow(overlay) | |
| axes[row, 3].set_title("Overlay") | |
| axes[row, 3].axis("off") | |
| plt.tight_layout() | |
| plt.savefig(save_path, dpi=150, bbox_inches="tight") | |
| plt.close() | |
| def plot_training_curves(history): | |
| epochs = range(1, len(history["train_loss"]) + 1) | |
| # Loss Curves | |
| plt.figure(figsize=(8, 5)) | |
| plt.plot(epochs, history["train_loss"], label="Train Loss") | |
| plt.plot(epochs, history["val_loss"], label="Validation Loss") | |
| plt.xlabel("Epoch") | |
| plt.ylabel("Loss") | |
| plt.title("Training and Validation Loss") | |
| plt.legend() | |
| plt.grid(True) | |
| plt.tight_layout() | |
| plt.savefig("assets/training_loss.png", dpi=150, bbox_inches="tight") | |
| plt.close() | |
| # Loss Components | |
| plt.figure(figsize=(8, 5)) | |
| plt.plot(epochs, history["train_ce"], label="Train CE") | |
| plt.plot(epochs, history["val_ce"], label="Validation CE") | |
| plt.plot(epochs, history["train_dice_loss"], label="Train Dice Loss") | |
| plt.plot(epochs, history["val_dice_loss"], label="Validation Dice Loss") | |
| plt.xlabel("Epoch") | |
| plt.ylabel("Loss") | |
| plt.title("Loss Components") | |
| plt.legend() | |
| plt.grid(True) | |
| plt.tight_layout() | |
| plt.savefig("assets/training_components.png", dpi=150, bbox_inches="tight") | |
| plt.close() | |
| # Segmentation Metrics | |
| plt.figure(figsize=(8, 5)) | |
| plt.plot(epochs, history["val_miou"], label="mIoU") | |
| plt.plot(epochs, history["val_miou_clothes"], label="mIoU Clothes") | |
| plt.plot(epochs, history["val_dice"], label="Dice") | |
| plt.plot(epochs, history["val_dice_clothes"], label="Dice Clothes") | |
| plt.xlabel("Epoch") | |
| plt.ylabel("Score") | |
| plt.title("Validation Segmentation Metrics") | |
| plt.legend() | |
| plt.grid(True) | |
| plt.tight_layout() | |
| plt.savefig("assets/validation_metrics.png", dpi=150, bbox_inches="tight") | |
| plt.close() | |
| def visualize_inference(image, pred_mask, final_mask, alpha=0.5, save_path="assets/inference_result.png"): | |
| if hasattr(image, "permute"): | |
| image = image.permute(1, 2, 0).cpu().numpy() | |
| if image.dtype != np.uint8: | |
| image = np.clip(image, 0, 1) | |
| image = (image * 255).astype(np.uint8) | |
| if hasattr(pred_mask, "numpy"): | |
| pred_mask = pred_mask.cpu().numpy() | |
| if hasattr(final_mask, "numpy"): | |
| final_mask = final_mask.cpu().numpy() | |
| pred_mask = pred_mask.astype(np.uint8) | |
| final_mask = final_mask.astype(np.uint8) | |
| overlay = create_overlay(image, final_mask, alpha=alpha) | |
| fig, axes = plt.subplots(1, 4, figsize=(16, 4)) | |
| # Original Image | |
| axes[0].imshow(image) | |
| axes[0].set_title("Original Image") | |
| axes[0].axis("off") | |
| # Raw Prediction | |
| colored_pred = colorize_mask(pred_mask) | |
| axes[1].imshow(colored_pred) | |
| axes[1].set_title("Raw Prediction") | |
| axes[1].axis("off") | |
| # Final Prediction | |
| axes[2].imshow(final_mask, cmap="gray", vmin=0, vmax=1) | |
| axes[2].set_title("Final Prediction") | |
| axes[2].axis("off") | |
| # Overlay | |
| axes[3].imshow(overlay) | |
| axes[3].set_title("Overlay") | |
| axes[3].axis("off") | |
| add_segmentation_legend(fig) | |
| plt.tight_layout(rect = [0, 0.08, 1, 1]) | |
| plt.savefig(save_path, dpi=150, bbox_inches="tight") | |
| plt.close() |