ClothSeg / src /visualize.py
ahmedsharaf's picture
Deploy ClothSeg Streamlit App
b157024
Raw History Blame Contribute Delete
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()