VanKee's picture
include performance and modify mosaic class
df29645
raw
history blame
5.37 kB
"""
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