Cinema Color
Intelligence
Upload any film still — or select from the reference library — to extract dominant palettes in LAB space, measure perceptual temperature, palette entropy, and match against 15 director color signatures.
Color grading is one of the least-quantified craft elements in filmmaking. This tool runs the full analysis pipeline in-browser: convert to CIELAB, cluster dominant colors via k-means, compute warm/cool ratios and palette entropy, then compare the resulting fingerprint against director signatures via CIE76 ΔE distance. No data leaves your browser.
Why LAB instead of HSV? HSV hue is intuitive but perceptually non-linear — a 10° shift at orange looks very different from a 10° shift at green. CIELAB's ΔE is perceptually uniform: Euclidean distance in that space predicts perceived difference. That means "are these two directors' palettes meaningfully different?" gets an answer with a real human interpretation. A ΔE of 18 — the mean gap between directors in the full dataset — is well above the just-noticeable difference threshold and comfortably in the "clearly distinct at a glance" range.
The browser tool analyzes a single frame in real-time. The Python pipeline below scales this to entire films — adaptive frame sampling, Pydantic validation, DuckDB ingestion, and dbt aggregation to director-level signatures across a multi-film corpus.
# cinema_extract.py — per-frame palette clustering import cv2, numpy as np from sklearn.cluster import KMeans def extract_palette(frame_bgr, k=5): small = cv2.resize(frame_bgr, (64, 36)) lab = cv2.cvtColor(small, cv2.COLOR_BGR2LAB) pixels = lab.reshape(-1, 3).astype(np.float32) km = KMeans(n_clusters=k, n_init=10, random_state=42) km.fit(pixels) counts = np.bincount(km.labels_, minlength=k) weights = counts / counts.sum() return sorted([ {'L': float(c[0]), 'a': float(c[1]), 'b': float(c[2]), 'weight': float(weights[i])} for i, c in enumerate(km.cluster_centers_) ], key=lambda x: -x['weight'])
Abbreviations and technical terms used throughout this page.