Visualizations
329 / 500

329 · Illusions

Color Constancy

Strawberries under cyan light: not a single red pixel, and they still look red.

A still life is rendered once into intrinsic layers (albedo, shading, highlights and object ids), so relighting it with any light on the color wheel is a per-pixel product, plus a tinted haze that grows with the light's saturation the way a colored filter's does, at full frame rate. The 'No red' preset is found by binary search: the least saturated cyan light that leaves zero red pixels anywhere, and the counter checks every pixel's hue to prove it while the loupe reads out gray strawberries. Two models of the brain's correction run on the picture: von Kries white balance divides each channel by the light estimated from the brightest surfaces, and multi-scale retinex subtracts each channel's blurred log surround at three scales. A second scene keeps a striped dress's pixels fixed while the light on the room changes, and the inferred colors flip between white and gold and blue and black.

Try it. Drag the handle on the color wheel to relight the scene, or pick a preset. Hover or touch the photo to read any pixel's true value with the loupe. Choose von Kries or Retinex and drag the divider to compare, Show highlights any red pixels, and The dress switches scenes. Keys: arrows turn the light, V cycles models, R shows red pixels, D switches scenes, 1 to 4 pick presets.

  • Intrinsic image relighting
  • von Kries adaptation
  • Multi-scale retinex
  • Binary search over light color

View the source · one module, plus a small shared runtime for sizing, the animation loop and input

Build your own

Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.

Build a color constancy demo with JavaScript and the HTML canvas element, where strawberries still look red under a light that leaves no red pixels at all. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.

Start simple:
- Make a canvas that fills the window, stays sharp on high-DPI screens (scale by devicePixelRatio), and resizes with the window.
- Paint a small still life into an offscreen 640 x 400 buffer: a pale wall, a white plate, a few red strawberries (cone shapes with yellow seed dots and green leaves), a lemon and a blue mug. Store each pixel's surface color (albedo) and a brightness value from simple sphere shading, not the final color.
- Relight it every time the light changes: final color = albedo x shading x light color, per channel, written into an ImageData and drawn scaled up.
- Add a color wheel I can drag to choose the light's hue and saturation.
- Count the red pixels on screen (hue near 0 degrees, reasonably saturated) and show the count. Find a cyan light where the count reaches zero.

Once that works, make it beautiful:
- Add a magnifying loupe that follows the pointer and shows the exact pixel isolated on a neutral gray card with its RGB values, so I can see that the strawberries are gray.
- Add a von Kries white balance view: estimate the light from the brightest pixels, divide each channel by it, and show it beside the original with a draggable divider.
- Add soft shadows, specular highlights and a gentle vignette so it reads like a photograph.

Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as a retinex model, a 'dress' style ambiguous scene, or a slider for how much of the scene the light estimate can see.
PreviousMoon LanderVector-line lunar descent on a green phosphor tube, with a suicide-burn autopilot. NextKakeya NeedleTurn a needle all the way around in a disk, a deltoid, then sprouting Perron trees.

Related visualizations

  • AfterimageIllusions Stare at a surreal landscape, then see full color in a picture that is pure gray.
  • Lateral InhibitionIllusions Four brightness illusions, each predicted live by a model of retinal ganglion cells.
  • Checker ShadowIllusions Squares A and B are the exact same gray. Move the light and the shadow keeps lying.
  • Dither LabRetro Seven dithering algorithms race on a moving scene in 1-bit, handheld green, CGA and EGA.
  • Light & ShadowPhysics Red, green and blue lights cast crisp, colored shadows through spinning shapes.
  • Chromaticity LabMath Draw any light's spectrum and watch it land on the CIE 1931 horseshoe.
  • Through Other EyesType and image A fruit market, a metro map and test plates as dichromats see them.
  • Pigment MixingSimulation Blue and yellow paint make green here: spectral Kubelka-Munk mixing beside naive RGB.
  • Palette CyclingRetro A waterfall, harbor rain and an aurora, animated without changing a single pixel.

Use ← and → to move between demos. While the canvas has focus, keys go to the demo instead.

← More from Emergent Mind Labs