VanKee's picture
include performance and modify mosaic class
df29645
"""
Performance metrics for comparing original and mosaic images
"""
import numpy as np
from PIL import Image
from skimage.metrics import structural_similarity as ssim
import cv2
def resize_to_match(original, mosaic):
"""Resize mosaic to match original image dimensions"""
return mosaic.resize(original.size, Image.BICUBIC)
def calculate_mse(original, mosaic):
"""
Calculate Mean Squared Error between two images
Lower values indicate better similarity (0 = perfect match)
"""
mosaic_resized = resize_to_match(original, mosaic)
orig_array = np.array(original, dtype=np.float32)
mosaic_array = np.array(mosaic_resized, dtype=np.float32)
mse = np.mean((orig_array - mosaic_array) ** 2)
return float(mse)
def calculate_ssim(original, mosaic):
"""
Calculate Structural Similarity Index
Range: [-1, 1], higher values indicate better similarity (1 = perfect match)
"""
mosaic_resized = resize_to_match(original, mosaic)
# Convert to grayscale for SSIM calculation
orig_gray = np.array(original.convert('L'))
mosaic_gray = np.array(mosaic_resized.convert('L'))
ssim_value = ssim(orig_gray, mosaic_gray)
return float(ssim_value)
def calculate_histogram_correlation(original, mosaic):
"""
Calculate histogram correlation for each RGB channel
Range: [-1, 1], higher values indicate better similarity
"""
mosaic_resized = resize_to_match(original, mosaic)
orig_array = np.array(original)
mosaic_array = np.array(mosaic_resized)
correlations = []
for channel in range(3): # RGB channels
hist_orig = cv2.calcHist([orig_array[:, :, channel]], [0], None, [256], [0, 256])
hist_mosaic = cv2.calcHist([mosaic_array[:, :, channel]], [0], None, [256], [0, 256])
# Normalize histograms
hist_orig = hist_orig.flatten() / np.sum(hist_orig)
hist_mosaic = hist_mosaic.flatten() / np.sum(hist_mosaic)
# Calculate correlation
correlation = np.corrcoef(hist_orig, hist_mosaic)[0, 1]
correlations.append(correlation)
return float(np.mean(correlations))
def calculate_edge_similarity(original, mosaic):
"""
Calculate edge similarity using Canny edge detection
Range: [0, 1], higher values indicate better similarity
"""
mosaic_resized = resize_to_match(original, mosaic)
# Convert to grayscale
orig_gray = np.array(original.convert('L'))
mosaic_gray = np.array(mosaic_resized.convert('L'))
# Apply Canny edge detection
orig_edges = cv2.Canny(orig_gray, 50, 150)
mosaic_edges = cv2.Canny(mosaic_gray, 50, 150)
# Calculate intersection over union (IoU) of edges
intersection = np.logical_and(orig_edges, mosaic_edges).sum()
union = np.logical_or(orig_edges, mosaic_edges).sum()
if union == 0:
return 1.0 # No edges in either image
edge_similarity = intersection / union
return float(edge_similarity)
def calculate_all_metrics(original, mosaic):
"""
Calculate all performance metrics and return as dictionary
"""
metrics = {}
try:
metrics['MSE'] = calculate_mse(original, mosaic)
metrics['SSIM'] = calculate_ssim(original, mosaic)
metrics['Histogram_Correlation'] = calculate_histogram_correlation(original, mosaic)
metrics['Edge_Similarity'] = calculate_edge_similarity(original, mosaic)
# Calculate overall quality score
metrics['Overall_Quality'] = (
metrics['SSIM'] * 0.4 +
metrics['Histogram_Correlation'] * 0.3 +
metrics['Edge_Similarity'] * 0.3
)
except Exception as e:
print(f"Error calculating metrics: {e}")
# Return default values if calculation fails
metrics = {
'MSE': float('nan'),
'SSIM': float('nan'),
'Histogram_Correlation': float('nan'),
'Edge_Similarity': float('nan'),
'Overall_Quality': float('nan')
}
return metrics
def format_metrics_report(metrics):
"""
Format metrics into a readable report string
"""
if not metrics:
return "No metrics calculated"
report = "Performance Metrics:\n\n"
# Core metrics
mse = metrics.get('MSE', float('nan'))
ssim_val = metrics.get('SSIM', float('nan'))
hist_corr = metrics.get('Histogram_Correlation', float('nan'))
edge_sim = metrics.get('Edge_Similarity', float('nan'))
if not np.isnan(mse):
report += f"MSE: {mse:.2f} (lower is better)\n"
if not np.isnan(ssim_val):
report += f"SSIM: {ssim_val:.4f} (higher is better)\n"
if not np.isnan(hist_corr):
report += f"Histogram Correlation: {hist_corr:.4f} (higher is better)\n"
if not np.isnan(edge_sim):
report += f"Edge Similarity: {edge_sim:.4f} (higher is better)\n\n"
# Overall quality
overall = metrics.get('Overall_Quality', float('nan'))
if not np.isnan(overall):
report += f"Overall Quality Score: {overall:.4f}\n"
if overall > 0.8:
report += "Quality: Excellent"
elif overall > 0.6:
report += "Quality: Good"
elif overall > 0.4:
report += "Quality: Fair"
elif overall > 0.2:
report += "Quality: Poor"
else:
report += "Quality: Very Poor"
return report