Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Apollo Paints — AI Colour Intelligence API

An AI-powered colour matching backend for Apollo Paints & Hardware, an authorized Berger Paints dealer. Customers can describe a mood, upload a photo, or ask for a matching colour palette — and get back real, purchasable shades from a 1,575-entry Berger catalogue.

Live API: https://apollo-paints-api.onrender.com Live site (with chat widget): https://apollopaints.netlify.app


What it does

🎨 Photo → matching shade

Upload any image — a fabric swatch, an inspiration photo, a wall you like elsewhere — and the API detects its dominant colours and matches each one to the closest real shade in the catalogue.

💬 Text → recommended shades

Describe what you want in plain language — "calming blue for a bedroom", "warm orange for a kitchen" — and get back real matching shades. Falls back to an LLM-assisted interpretation for open-ended descriptions the keyword matcher can't parse.

🎯 Colour harmony / palettes

Ask for a matching colour palette and get back a full set built from real colour-wheel theory, every result snapped to an actual catalogue shade:

  • By shade code: "what goes with 1D2827"
  • By description: "complementary colours for a warm terracotta", "palette for a living room"

Returns five labeled groups:

Group What it is
Complementary opposite hue on the colour wheel — high contrast
Analogous neighbouring hues — subtle, cohesive
Triadic three evenly-spaced hues — balanced and vibrant
Split-complementary complementary hue, split either side — contrast with less tension
Tonal ramp lighter/darker versions of the same hue — for trim, ceiling, or accent walls

If a shade code is mentioned, the palette is built directly around that shade. If not, the query is first matched to a base shade (reusing the text-recommendation engine), then the palette is built around whatever that resolves to — so "what goes with" never fails just because no exact code was given.


How it works (no ML training required)

This project deliberately uses deterministic colour science instead of a trained ML model, because colour matching against a fixed catalogue is a nearest-neighbour search problem, not a learning problem:

Feature Technique
Photo colour matching k-means clustering (scikit-learn) to find dominant colours, then nearest-neighbour lookup
Perceptual colour distance RGB → LAB colour space conversion + CIE76 distance (approximates human colour perception far better than raw RGB)
Colour harmony HSL colour-wheel math (complementary/analogous/triadic/split-complementary), snapped to real catalogue entries
Text understanding Keyword/mood lexicon first; Claude (Anthropic API) as a fallback for open-ended queries — the LLM only ever picks a colour direction, never a shade code, so it can't hallucinate a product that doesn't exist

Tech stack

  • Backend: Python, FastAPI, Uvicorn
  • Colour science: NumPy, scikit-learn (k-means), custom LAB/HSL conversion
  • Image handling: Pillow
  • LLM fallback: Anthropic API (Claude)
  • Data source: scraped from Berger Paints' public colour catalogue (requests + BeautifulSoup)
  • Deployment: Render (backend), Netlify (static frontend)
  • Frontend: vanilla HTML/CSS/JS chat widget, no framework

Data pipeline

Berger's catalogue has no public API, so the shade dataset was built by:

  1. Inspecting the live site's HTML structure to locate shade name/code/colour markup
  2. Confirming each colour-family page (Reds, Blues, Greens, etc.) is server-rendered — meaning a plain HTTP scraper works, no headless browser needed
  3. Scraping all 10 category pages with requests + BeautifulSoup, extracting name, code, and hex value for each shade
  4. Output: data/shades.json — 1,575 shades, indexed into LAB colour space once at app startup for fast matching

API reference

Method Endpoint Description
GET /api/shades?family=&q= Browse/search the catalogue
GET /api/shades/{code} Look up a single shade by code
POST /api/match-photo Upload an image, get matching shades
POST /api/match-color Match a given hex to nearest shades
GET /api/recommend?q= Text description → recommended shades
GET /api/harmony/{code} Colour palette built from a shade code
GET /api/harmony?hex= Colour palette built from any hex

Interactive API docs available at /docs (FastAPI auto-generated Swagger UI).


Running locally

git clone https://github.com/uttkarshh07/apollo--paints-api.git
cd apollo--paints-api
pip install -r requirements.txt
uvicorn main:app --reload --port 8000

Open http://localhost:8000/docs to test every endpoint interactively.

Optional — enable the LLM fallback for open-ended text queries:

export ANTHROPIC_API_KEY=your_key_here

Project structure

main.py          — FastAPI app, all routes
color_utils.py   — LAB conversion, nearest-shade matching engine
image_match.py   — photo → dominant colour extraction (k-means)
harmony.py       — colour-wheel math for palette generation
recommend.py     — text-to-shade matching (keyword + LLM fallback)
data/shades.json — the Berger shade catalogue (1,575 entries)

Changelog

  • v1.0 — Photo matching + text-based shade recommendations, deployed on Render + Netlify
  • v1.1 — Added colour harmony/palette generation (/api/harmony), wired into the chat widget with natural-language intent detection (e.g. distinguishing "what goes with X" from a plain shade request)

Notes

  • Shade data is a snapshot from bergerpaints.com's public colour catalogue. Apollo Paints is an authorized Berger dealer, so shade names/codes match what's actually sold in-store.
  • Free-tier hosting (Render) spins down after inactivity — first request after idle time may take 30–50s to respond.

About

AI-powered colour matching API for Apollo Paints — photo colour matching, text-based shade recommendations, and colour harmony suggestions, built on a real 1,575-shade Berger Paints catalogue.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages