core/evals/vision_sensorium/synth.py

66 lines
2.3 KiB
Python

"""Deterministic synthetic image fixtures for vision_core_v1."""
from __future__ import annotations
import numpy as np
SIZE = 32
def _flat(rgb: list[float], size: int) -> np.ndarray:
out = np.zeros((size, size, 3), dtype=np.float32)
out[:, :, :] = np.asarray(rgb, dtype=np.float32)
return out
def synthesize(spec: dict) -> np.ndarray:
"""Return a float32 RGB image for a fixture spec."""
size = int(spec.get("size", SIZE))
kind = spec["kind"]
if kind == "flat":
return _flat(list(spec.get("rgb", [0.5, 0.5, 0.5])), size)
if kind == "edge":
out = _flat([0.15, 0.15, 0.15], size)
if spec.get("orientation") == "horizontal":
out[size // 2:, :, :] = 0.9
else:
out[:, size // 2:, :] = 0.9
return out
if kind == "corner":
out = _flat([0.1, 0.1, 0.1], size)
out[4:16, 4:7, :] = 0.95
out[4:7, 4:16, :] = 0.95
out[11:16, 11:16, :] = 0.75
return out
if kind == "blob":
out = _flat([0.2, 0.2, 0.2], size)
yy, xx = np.mgrid[:size, :size]
mask = (xx - size / 2) ** 2 + (yy - size / 2) ** 2 <= (size / 5) ** 2
out[mask, :] = 0.95
return out.astype(np.float32)
if kind == "checker":
period = int(spec.get("period", 4))
yy, xx = np.mgrid[:size, :size]
mask = ((xx // period) + (yy // period)) % 2
out = np.repeat(mask[:, :, None].astype(np.float32), 3, axis=2)
return out
if kind == "ramp":
x = np.linspace(0.0, 1.0, size, dtype=np.float32)
ramp = np.repeat(x[None, :, None], size, axis=0)
return np.repeat(ramp, 3, axis=2)
if kind == "chroma_split":
out = _flat([0.1, 0.1, 0.8], size)
out[:, size // 2:, :] = np.asarray([0.9, 0.15, 0.1], dtype=np.float32)
return out
if kind == "salient_spot":
out = _flat([0.45, 0.45, 0.45], size)
out[size // 2 - 3:size // 2 + 3, size // 2 - 3:size // 2 + 3, :] = 1.0
return out
if kind == "contour_box":
out = _flat([0.2, 0.2, 0.2], size)
out[7:25, 7:11, :] = 1.0
out[7:25, 21:25, :] = 1.0
out[7:11, 7:25, :] = 1.0
out[21:25, 7:25, :] = 1.0
return out
raise ValueError(f"unknown vision fixture kind: {kind!r}")