File size: 5,369 Bytes
df29645 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
"""
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 |