The algorithm
Ranking paintings by colour, in a way that matches what you see.
Most of the interesting decisions here are about the gap between what a computer measures and what a person perceives. This page shows the maths, the numbers it produces, and the things it cannot tell you.
1,500
Public-domain works
7,485
Palette swatches
35,928
Precomputed edges
0
Requests while you browse
01
Colour space
Why RGB is the wrong ruler
The obvious implementation clusters pixels in RGB and is quietly wrong. Distance in RGB is arithmetic, not perceptual. Both pairs below sit within a point of the same distance apart in RGB — and only one of them looks different.
- Distance in RGB
- 39.1
- Perceptual ΔE
- 0.52
Indistinguishable. You would call these the same colour.
- Distance in RGB
- 40.2
- Perceptual ΔE
- 38.99
Plainly different — a plum and a forest green.
So every pixel is converted to CIELAB, which is roughly perceptually uniform: a fixed step corresponds to roughly the same visible change anywhere in the space.
That conversion has a step people skip. sRGB is gamma-encoded, and the encoding must be undone before any colour maths. Skipping it still produces plausible-looking numbers, which is exactly why the mistake survives review.
02
Extraction
Five colours, weighted by how much canvas they cover
Each image is downsampled to 100 pixels on its long edge — palette does not need resolution — converted to LAB, and clustered with k-means at k=5 on a fixed seed. Each cluster centre becomes a swatch, stored with its share of the canvas.
- #b73a16 · 43%
- #943318 · 21%
- #f4e5d6 · 16%
- #dd916d · 14%
- #67403a · 8%
The fixed seed matters more than it looks. Fixed, the result is reproducible and a re-sync produces a diff you can read. Unfixed, every run churns out slightly different numbers and nothing can be verified.
The source record ships a single dominant colour of its own. Chroma computes its own anyway: one value is not a palette, and the share each colour covers is the part that makes ranking feel right.
03
Ranking
What a ΔE actually looks like
Works are scored against their nearest palette entry using CIEDE2000, the current CIE standard for perceptual difference. Plain Euclidean distance in LAB is closer to right than RGB but still misjudges saturated blues badly — and blue is everywhere in painting.
- #1a3a6b
Reference
- #1e3d6e
ΔE 1.0
The threshold of noticing
- #0a3160
ΔE 3.0
Visible side by side
- #00214e
ΔE 8.0
Clearly a different shade
- #5b72a9
ΔE 19.9
Related, not the same
- #96abe6
ΔE 44.9
A different colour entirely
Distance alone is not enough. A 2% fleck of exactly the right blue would beat a canvas that is largely that blue. So each score carries a penalty for how little of the canvas the matched colour covers — up to a full 20 ΔE for a colour covering none of it.
That figure was chosen by comparing real results, not by taste. The multiplicative version put a sage-green landscape with a 9% navy fleck above paintings that are actually navy. Because the penalty makes the score no longer a true ΔE, every result shows the real perceptual distance and the coverage separately, rather than the blended number that produced the order.
04
The honest part
What “similar in palette” does not mean
The similarity on every artwork page compares five colours and their proportions. That is all it compares. It has no idea what is depicted, when it was made, or how it is composed — two portraits and a landscape can share a palette exactly.
That is why the interface says similar in palette and never “similar artwork” or “you might also like”. Implying the system understands subject matter would be a claim it cannot support. Embeddings from an image model would give genuine similarity of subject and composition; that is a later phase, and until it exists the wording stays accurate.
05
Verification
How the maths is checked
The colour conversion is tested against published sRGB-to-CIELAB reference values, and CIEDE2000 against the complete Sharma–Wu–Dalal verification table — all 31 pairs, to four decimal places. That table exists precisely because the formula is easy to get subtly wrong: it contains the near-neutral cases where hue wraps around, and the saturated blues where the rotation term matters.
Extraction is asserted to be deterministic for a fixed seed, population shares to sum to one, and a greyscale image to yield low-chroma swatches — which is the end-to-end check that the gamma step and white point are right.
06
The images
A grid that never jumps
Width and height are stored when a work is first collected, so every tile reserves its exact aspect ratio before a single byte of image arrives. Cumulative layout shift is asserted to be zero in the end-to-end tests, on desktop and mobile — measured, not hoped for.
A tiny blurred preview ships inline with each record, so a tile is never blank and survives the picture failing to load. Images are requested at a few fixed widths matched to how large they actually render, and each is served through this site’s own route: your browser contacts exactly one host.
07
The data
Nothing is fetched while you browse
A command-line sync collects metadata, extracts palettes, and precomputes the similarity graph ahead of time. Pages read a local database, so a page view cannot spend an upstream request no matter how much traffic arrives.
Works come from The Art Institute of Chicago’s open-access collection, filtered to public-domain works with an image. Works shown are in the public domain. Metadata is made available under CC0.
There are no accounts, so boards live in your browser’s own storage and nowhere else. Nothing you save is uploaded.