Spaces:
Running
Running
| import cv2 | |
| import numpy as np | |
| def compute_delta_e(img1: np.ndarray, img2: np.ndarray, | |
| mask: np.ndarray | None = None) -> float: | |
| """ | |
| Compute mean CIE76 ΔE between two images in CIE LAB colour space. | |
| Optional mask restricts the computation to a region. | |
| """ | |
| assert img1.shape == img2.shape, "Images must have the same shape" | |
| lab1 = cv2.cvtColor(img1, cv2.COLOR_BGR2LAB).astype(np.float64) | |
| lab2 = cv2.cvtColor(img2, cv2.COLOR_BGR2LAB).astype(np.float64) | |
| # Rescale to physical LAB values | |
| lab1[:, :, 0] *= 100.0 / 255.0 | |
| lab2[:, :, 0] *= 100.0 / 255.0 | |
| lab1[:, :, 1:] -= 128 | |
| lab2[:, :, 1:] -= 128 | |
| de = np.sqrt(((lab1 - lab2) ** 2).sum(axis=2)) | |
| if mask is not None: | |
| region = de[mask > 0] | |
| return float(region.mean()) if region.size > 0 else 0.0 | |
| return float(de.mean()) | |
| def compute_iou(mask1: np.ndarray, mask2: np.ndarray) -> float: | |
| """ | |
| Compute Intersection over Union for two binary masks. | |
| Masks can be uint8 (0/255) or bool. | |
| """ | |
| m1 = (mask1 > 0) | |
| m2 = (mask2 > 0) | |
| intersection = (m1 & m2).sum() | |
| union = (m1 | m2).sum() | |
| return float(intersection) / float(union + 1e-6) | |
| def compute_alignment_error(lm1: np.ndarray, lm2: np.ndarray) -> float: | |
| """ | |
| Compute mean pixel error between two landmark sets. | |
| Returns mean Euclidean distance in pixels. | |
| """ | |
| if lm1 is None or lm2 is None: | |
| return float("inf") | |
| n = min(len(lm1), len(lm2)) | |
| return float(np.linalg.norm(lm1[:n] - lm2[:n], axis=1).mean()) | |
| def compute_ssim(img1: np.ndarray, img2: np.ndarray) -> float: | |
| """Compute Structural Similarity Index (SSIM) between two images.""" | |
| try: | |
| from skimage.metrics import structural_similarity as ssim | |
| gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) | |
| gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) | |
| score, _ = ssim(gray1, gray2, full=True) | |
| return float(score) | |
| except Exception: | |
| return 0.0 | |
| def compute_psnr(img1: np.ndarray, img2: np.ndarray) -> float: | |
| """Compute Peak Signal-to-Noise Ratio.""" | |
| mse = ((img1.astype(np.float64) - img2.astype(np.float64)) ** 2).mean() | |
| if mse == 0: | |
| return float("inf") | |
| return 20.0 * np.log10(255.0 / np.sqrt(mse)) | |