""" Seamless check for 2:1 equirectangular skybox: compare left vs right edge. Returns MSE and a simple pass/fail (low MSE = more seamless). """ from pathlib import Path import numpy as np from PIL import Image def check_seamless(image_path: str, column_width: int = 5) -> dict: """ Load image, compare left and right edge columns. Equirectangular wraps, so left and right should match for a seamless skybox. Returns dict with mse, passed (bool), and message. """ path = Path(image_path) if not path.is_file(): return { "mse": float("inf"), "passed": False, "message": f"Image file not found: {path.name}", } img = np.array(Image.open(image_path).convert("RGB")) h, w = img.shape[:2] if w < 2 * column_width: return { "mse": float("inf"), "passed": False, "message": f"Image width {w} too small for column width {column_width}", } left = img[:, :column_width].astype(np.float32) right = img[:, -column_width:].astype(np.float32) mse = float(np.mean((left - right) ** 2)) # Heuristic: MSE < 100 often looks reasonably seamless passed = mse < 100 message = ( f"Left/right edge MSE = {mse:.2f}. " + ("Seamless (edges match)." if passed else "Edges differ (consider 360° model).") ) return {"mse": mse, "passed": passed, "message": message}