Skip to main content
colorscope

Clustering

Cluster extracted colors into meaningful groups using k-means in OKLab space. A leather swatch might yield 15 shades of brown — clustering reduces them to the 3-4 groups a designer actually cares about.

Source: 12 extracted colors

Suggested: 2 (elbow method)

Clustered into 2 groups:

#c6a18161%
#44353319%
const k = suggestK(colors); // 2 const clusters = clusterColors(colors, 2);
import { clusterColors, suggestK } from "colorscope/analysis";

Functions

clusterColors

Cluster colors into k groups using k-means in OKLab space.

function clusterColors(
  colors: readonly QuantizedColor[],
  k: number,
  maxIterations?: number
): ColorCluster[]
ParamTypeDefaultDescription
colorsreadonly QuantizedColor[]Colors to cluster
knumberNumber of clusters
maxIterationsnumber20Maximum k-means iterations

Returns: Array of k clusters sorted by proportion descending. Uses k-means++ seeding for stable results.

const clusters = clusterColors(terrazzoPalette, 5);
clusters.forEach(c => {
  console.log(`${oklabToHex(c.centroid)} — ${c.members.length} colors, ${(c.proportion * 100).toFixed(0)}%`);
});
// #8B6B4A — 5 colors, 35%  (warm browns)
// #6B7B7E — 4 colors, 22%  (cool grays)
// ...

suggestK

Suggest optimal number of clusters using the elbow method.

function suggestK(colors: readonly QuantizedColor[], maxK?: number): number
ParamTypeDefaultDescription
colorsreadonly QuantizedColor[]Colors to analyze
maxKnumber8Maximum k to test

Returns: Suggested number of clusters (1 to maxK). Computes inertia for each k and finds the "knee" in the curve.

const k = suggestK(terrazzoPalette); // 5
const clusters = clusterColors(terrazzoPalette, k);

Types

ColorCluster

interface ColorCluster {
  centroid: OKLab;            // Cluster center in OKLab space
  members: QuantizedColor[];  // Colors assigned to this cluster
  proportion: number;         // Sum of member proportions
}