Color Scheme
Image Processing
Algorithm Design
Color Extraction
Computer Vision

Algorithm challenge Generate color scheme from an image

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Generating a usable color scheme from an image is not just a matter of picking the most common pixels. A good palette algorithm usually balances dominant colors, removes noise, and chooses representative colors that are visually distinct enough to be useful in design.

Define What a "Color Scheme" Means

Before choosing an algorithm, be clear about the goal. A palette for UI design is usually not the same as a raw histogram of image pixels.

Typical goals include:

  • one dominant base color
  • one or two secondary colors
  • one accent color
  • optional light and dark support colors

That means the algorithm should usually optimize for usefulness, not just raw frequency.

A Practical Pipeline

A strong practical pipeline looks like this:

  1. resize the image to reduce work
  2. convert to a color space that behaves better perceptually
  3. remove very transparent or irrelevant pixels if needed
  4. cluster colors
  5. sort clusters by weight
  6. filter near-duplicates and overly dull candidates
  7. choose dominant, secondary, and accent colors from the remaining set

This is much better than simply taking the top n most frequent RGB values, which often produces many nearly identical shades.

Why LAB or HSV Helps

RGB is fine for storage and display, but it is not the best space for deciding whether two colors feel similar. A palette extractor often works better in a space such as LAB or HSV because:

  • brightness can be handled separately from chroma
  • near-duplicate shades are easier to detect
  • perceptual distance is easier to reason about

You can still convert the chosen colors back to RGB or hex at the end.

A K-Means Example in Python

One practical solution is to cluster image pixels and use the cluster centers as candidate colors.

python
1from PIL import Image
2import numpy as np
3from sklearn.cluster import KMeans
4
5
6def extract_palette(path, k=6, resize_to=200):
7    image = Image.open(path).convert("RGB")
8    image.thumbnail((resize_to, resize_to))
9
10    pixels = np.array(image).reshape(-1, 3)
11
12    model = KMeans(n_clusters=k, random_state=42, n_init=10)
13    labels = model.fit_predict(pixels)
14    centers = model.cluster_centers_.astype(int)
15
16    counts = np.bincount(labels)
17    order = np.argsort(counts)[::-1]
18
19    palette = []
20    for index in order:
21        color = tuple(centers[index])
22        palette.append(color)
23
24    return palette
25
26
27palette = extract_palette("example.jpg")
28print(palette)

This gives you a reasonable starting palette, but it is only the middle of the solution. You still need to decide which clusters are visually useful.

Remove Near-Duplicates

A common failure mode is getting several clusters that are almost the same color. A simple distance-based filter improves the result.

python
1import math
2
3
4def color_distance(c1, c2):
5    return math.sqrt(sum((a - b) ** 2 for a, b in zip(c1, c2)))
6
7
8def dedupe_palette(colors, min_distance=40):
9    chosen = []
10    for color in colors:
11        if all(color_distance(color, existing) >= min_distance for existing in chosen):
12            chosen.append(color)
13    return chosen
14
15
16raw_palette = extract_palette("example.jpg", k=8)
17palette = dedupe_palette(raw_palette)
18print(palette)

This keeps the palette from filling up with slightly different versions of the same blue or gray.

Choose an Accent Color Deliberately

The most common color is not always the best accent color. In many images, the dominant color is a neutral background or a large low-saturation surface.

A useful heuristic is:

  • dominant color by cluster size
  • accent color by high saturation and meaningful coverage

That often produces a palette that feels more like a designer's palette rather than a compression artifact.

You can approximate this by converting each candidate to HSV and preferring colors with stronger saturation for accent selection.

Handle Problem Images

Some images are difficult on purpose:

  • very dark images
  • mostly grayscale images
  • noisy photographs
  • images with a single overwhelming background color

In those cases, a good extractor may need extra rules, such as:

  • ignore nearly black and nearly white pixels for accent selection
  • downweight extremely common background colors
  • require a minimum saturation for accent candidates

These heuristics are often what separate a useful palette tool from a basic clustering demo.

Output as Hex Values

For design tools, hex output is usually more practical than RGB tuples.

python
1def to_hex(color):
2    return '#{:02x}{:02x}{:02x}'.format(*color)
3
4print([to_hex(c) for c in palette])

That makes the output easy to drop into CSS, design tokens, or front-end theme systems.

Common Pitfalls

One common mistake is clustering raw full-resolution images without resizing, which wastes time without improving palette quality much.

Another pitfall is treating the most frequent colors as the final scheme without removing near-duplicates.

A third issue is staying entirely in RGB when the algorithm really needs a more perceptual way to compare colors.

Finally, a palette that mirrors the image too literally may still be bad for design. Good extraction often needs rules for contrast, saturation, and usability.

Summary

  • A useful image-based color scheme is more than a raw list of frequent pixels.
  • A practical algorithm resizes the image, clusters colors, filters near-duplicates, and chooses representative colors deliberately.
  • K-means is a strong baseline for extracting dominant candidate colors.
  • Accent colors often need saturation-aware selection rather than simple frequency ranking.
  • The best palette algorithms combine clustering with design-oriented heuristics.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design