"""Resolution, color-space, statistics, and histogram helpers.""" from __future__ import annotations import matplotlib.pyplot as plt import numpy as np import cv2 from filters.builtin import ensure_rgb def low_resolution_pair(image: np.ndarray, percent: int = 25) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: img = ensure_rgb(image) h, w = img.shape[:2] small = cv2.resize(img, (max(1, w * percent // 100), max(1, h * percent // 100)), interpolation=cv2.INTER_AREA) low_rgb = cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST) high_gray = cv2.cvtColor(cv2.cvtColor(img, cv2.COLOR_RGB2GRAY), cv2.COLOR_GRAY2RGB) low_gray = cv2.cvtColor(cv2.cvtColor(low_rgb, cv2.COLOR_RGB2GRAY), cv2.COLOR_GRAY2RGB) return img, low_rgb, high_gray, low_gray def pixel_preview(image: np.ndarray, x: int = 0, y: int = 0, size: int = 6) -> list[list[str]]: img = ensure_rgb(image) y0, x0 = max(0, y), max(0, x) crop = img[y0 : y0 + size, x0 : x0 + size] return [[str(tuple(int(v) for v in px)) for px in row] for row in crop] def stats(image: np.ndarray) -> dict[str, float | int | list[int]]: img = ensure_rgb(image) return {"shape": list(img.shape), "mean": float(img.mean()), "std": float(img.std()), "min": int(img.min()), "max": int(img.max())} def histogram_figure(high_rgb: np.ndarray, low_rgb: np.ndarray): fig, axes = plt.subplots(1, 2, figsize=(10, 4), tight_layout=True) for ax, img, title in [(axes[0], high_rgb, "High resolution"), (axes[1], low_rgb, "Low resolution")]: for idx, color in enumerate(["red", "green", "blue"]): ax.hist(img[..., idx].ravel(), bins=64, range=(0, 255), color=color, alpha=0.35) gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) ax.hist(gray.ravel(), bins=64, range=(0, 255), color="black", alpha=0.35) ax.set_title(title) ax.set_xlabel("Intensity") ax.set_ylabel("Pixels") return fig