|
"""
|
|
Image Corruption Utilities for Anomaly Detection Testing
|
|
Simple functions to corrupt images and test anomaly detection
|
|
"""
|
|
|
|
import torch
|
|
import numpy as np
|
|
from PIL import Image, ImageFilter, ImageEnhance
|
|
import matplotlib.pyplot as plt
|
|
import random
|
|
from torchvision import transforms
|
|
|
|
|
|
def corrupt_image(image_path, corruption_type='random', intensity=1.0, save_path=None):
|
|
"""
|
|
Apply corruption to an image
|
|
|
|
Args:
|
|
image_path: Path to the input image or PIL Image object
|
|
corruption_type: Type of corruption ('noise', 'blur', 'brightness', 'contrast', 'saturation', 'random')
|
|
intensity: Intensity of corruption (0.1 = light, 1.0 = normal, 2.0 = heavy)
|
|
save_path: Optional path to save corrupted image
|
|
|
|
Returns:
|
|
PIL Image: Corrupted image
|
|
"""
|
|
|
|
if isinstance(image_path, str):
|
|
image = Image.open(image_path).convert('RGB')
|
|
else:
|
|
image = image_path.convert('RGB')
|
|
|
|
if corruption_type == 'random':
|
|
corruption_type = random.choice(['noise', 'blur', 'brightness', 'contrast', 'saturation'])
|
|
print(f"Applied random corruption: {corruption_type}")
|
|
|
|
if corruption_type == 'noise':
|
|
|
|
img_array = np.array(image).astype(np.float32) / 255.0
|
|
noise = np.random.normal(0, 0.1 * intensity, img_array.shape)
|
|
corrupted_array = np.clip(img_array + noise, 0, 1)
|
|
corrupted_image = Image.fromarray((corrupted_array * 255).astype(np.uint8))
|
|
|
|
elif corruption_type == 'blur':
|
|
|
|
radius = 1.0 * intensity
|
|
corrupted_image = image.filter(ImageFilter.GaussianBlur(radius=radius))
|
|
|
|
elif corruption_type == 'brightness':
|
|
|
|
enhancer = ImageEnhance.Brightness(image)
|
|
factor = 0.5 + (0.5 * intensity)
|
|
corrupted_image = enhancer.enhance(factor)
|
|
|
|
elif corruption_type == 'contrast':
|
|
|
|
enhancer = ImageEnhance.Contrast(image)
|
|
factor = 0.3 + (0.7 * intensity)
|
|
corrupted_image = enhancer.enhance(factor)
|
|
|
|
elif corruption_type == 'saturation':
|
|
|
|
enhancer = ImageEnhance.Color(image)
|
|
factor = 0.2 + (0.8 * intensity)
|
|
corrupted_image = enhancer.enhance(factor)
|
|
|
|
else:
|
|
raise ValueError(f"Unknown corruption type: {corruption_type}")
|
|
|
|
|
|
if save_path:
|
|
corrupted_image.save(save_path)
|
|
print(f"Corrupted image saved to: {save_path}")
|
|
|
|
return corrupted_image
|
|
|
|
|
|
def compare_images(original_path, corruption_types=['noise', 'blur', 'brightness'], intensity=1.0):
|
|
"""
|
|
Compare original image with different corruptions
|
|
|
|
Args:
|
|
original_path: Path to original image
|
|
corruption_types: List of corruption types to apply
|
|
intensity: Corruption intensity
|
|
"""
|
|
|
|
original = Image.open(original_path)
|
|
|
|
|
|
fig, axes = plt.subplots(1, len(corruption_types) + 1, figsize=(4 * (len(corruption_types) + 1), 4))
|
|
if len(corruption_types) == 0:
|
|
axes = [axes]
|
|
|
|
|
|
axes[0].imshow(original)
|
|
axes[0].set_title('Original')
|
|
axes[0].axis('off')
|
|
|
|
|
|
for i, corruption_type in enumerate(corruption_types):
|
|
corrupted = corrupt_image(original_path, corruption_type, intensity)
|
|
axes[i + 1].imshow(corrupted)
|
|
axes[i + 1].set_title(f'{corruption_type.title()} (intensity: {intensity})')
|
|
axes[i + 1].axis('off')
|
|
|
|
plt.tight_layout()
|
|
plt.show()
|
|
|
|
|
|
def test_corruption_detection(detector, image_path, corruption_types=['noise', 'blur', 'brightness'], intensity=1.0):
|
|
"""
|
|
Test anomaly detection on original vs corrupted images
|
|
|
|
Args:
|
|
detector: SimpleAnomalyDetector instance
|
|
image_path: Path to test image
|
|
corruption_types: List of corruption types to test
|
|
intensity: Corruption intensity
|
|
"""
|
|
print(f"π Testing anomaly detection on: {image_path}")
|
|
print("=" * 60)
|
|
|
|
|
|
original_error = detector.calculate_reconstruction_error(image_path)
|
|
print(f"Original image error: {original_error:.6f}")
|
|
|
|
|
|
for corruption_type in corruption_types:
|
|
corrupted_image = corrupt_image(image_path, corruption_type, intensity)
|
|
corrupted_error = detector.calculate_reconstruction_error(corrupted_image)
|
|
multiplier = corrupted_error / original_error if original_error > 0 else float('inf')
|
|
|
|
print(f"{corruption_type.title():12} error: {corrupted_error:.6f} ({multiplier:.2f}x original)")
|
|
|
|
print("\nπ‘ Higher reconstruction error = more anomalous/corrupted")
|
|
|
|
|
|
def quick_corruption_test(image_path, save_corrupted=False):
|
|
"""
|
|
Quick test of all corruption types on a single image
|
|
|
|
Args:
|
|
image_path: Path to test image
|
|
save_corrupted: Whether to save corrupted images
|
|
"""
|
|
corruption_types = ['noise', 'blur', 'brightness', 'contrast', 'saturation']
|
|
|
|
print(f"π§ͺ Testing all corruption types on: {image_path}")
|
|
print("=" * 50)
|
|
|
|
for corruption_type in corruption_types:
|
|
save_path = f"corrupted_{corruption_type}.png" if save_corrupted else None
|
|
corrupted = corrupt_image(image_path, corruption_type, intensity=1.0, save_path=save_path)
|
|
print(f"β
{corruption_type.title()} corruption applied")
|
|
|
|
print(f"\nπ‘ Use compare_images() to visualize all corruptions side by side")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("β
Image corruption utilities loaded!")
|
|
print("\nAvailable functions:")
|
|
print("- corrupt_image(image_path, corruption_type, intensity)")
|
|
print("- compare_images(image_path, corruption_types, intensity)")
|
|
print("- test_corruption_detection(detector, image_path, corruption_types, intensity)")
|
|
print("- quick_corruption_test(image_path, save_corrupted)") |