| | """ |
| | 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) |
| |
|
| | |
| | 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): |
| | hist_orig = cv2.calcHist([orig_array[:, :, channel]], [0], None, [256], [0, 256]) |
| | hist_mosaic = cv2.calcHist([mosaic_array[:, :, channel]], [0], None, [256], [0, 256]) |
| |
|
| | |
| | hist_orig = hist_orig.flatten() / np.sum(hist_orig) |
| | hist_mosaic = hist_mosaic.flatten() / np.sum(hist_mosaic) |
| |
|
| | |
| | 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) |
| |
|
| | |
| | orig_gray = np.array(original.convert('L')) |
| | mosaic_gray = np.array(mosaic_resized.convert('L')) |
| |
|
| | |
| | orig_edges = cv2.Canny(orig_gray, 50, 150) |
| | mosaic_edges = cv2.Canny(mosaic_gray, 50, 150) |
| |
|
| | |
| | intersection = np.logical_and(orig_edges, mosaic_edges).sum() |
| | union = np.logical_or(orig_edges, mosaic_edges).sum() |
| |
|
| | if union == 0: |
| | return 1.0 |
| |
|
| | 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) |
| |
|
| | |
| | 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}") |
| | |
| | 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" |
| |
|
| | |
| | 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 = 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 |