Anvit25's picture
Update readme
5d2a222 verified
Image Color Classifier — README
Classify an image as rust, zinc, or normal using simple, fast color-space heuristics (OpenCV + NumPy).
You get three ways to use it:
a FastAPI server (/classify/ endpoint)
a Gradio web UI for quick testing
CLI tools to generate color reports and classify offline
Features
Heuristic color analysis in CIELab:
rustish_ratio → fraction of pixels with elevated a* (reddish/brownish)
zincish_ratio → fraction of pixels with elevated b* (yellowish)
Dominant colors via K-Means (palette + relative shares)
Three thresholds you can tune: rust_thr, zinc_thr, and lab_delta
Repository Layout
.
├─ api.py # FastAPI app exposing /classify/
├─ app.py # Gradio demo UI
├─ classify.py # (named 'app.py' in your message) classify from *_color_report.json
├─ color.py # Report generator (stats + palette + heuristics)
├─ main.py # CLI variant (stats + palette + heuristics + classification)
├─ requirements.txt # Python deps (fix the typos—see below)
└─ color_out/ # (created at runtime) reports and palette images
⚠️ Fix your requirements.txt:
Replace:
"fastapi[all]"
opencv-python-headless
numpy
gardio
With:
fastapi[all]
uvicorn
opencv-python-headless
numpy
gradio
Quickstart
1) Environment
python -m venv .venv
# Windows
.venv\Scripts\activate
# macOS/Linux
source .venv/bin/activate
pip install -r requirements.txt
2) Run the FastAPI server
uvicorn api:app --host 127.0.0.1 --port 8000
Endpoint: POST /classify/
Body: multipart form with file field file (image)
Query params (optional):
k (int, default 3) — number of dominant colors
rust_thr (float, default 0.01)
zinc_thr (float, default 0.02)
lab_delta (float, default 6.0)
cURL example:
curl -X POST "http://127.0.0.1:8000/classify/?k=3&rust_thr=0.01&zinc_thr=0.02&lab_delta=6.0" \
-F "file=@/path/to/sample.jpg"
Response (JSON):
{
"filename": "sample.jpg",
"classification": "rust",
"rustish_ratio": 0.0342,
"zincish_ratio": 0.0051,
"top_colors_rgb": [[183, 98, 72], [220, 210, 205], [120, 85, 70]],
"top_colors_share": [0.62, 0.25, 0.13]
}
OpenAPI docs at: http://127.0.0.1:8000/docs
3) Run the Gradio demo
python gradio_app.py
Upload an image, tweak sliders, and see the JSON output instantly.
Parameters mirrored: k, rust_thr, zinc_thr, lab_delta.
4) CLI workflows
You have two report generators and one “classify from JSON” helper.
Pick either color.py or main.py to generate a report.
A) Generate a detailed report with color.py
Creates:
Stats in RGB/HSV/Lab
Dominant color palette image
Heuristic ratios
python color.py --img /path/to/img.jpg --k 3 --resize_max 1200 --outdir color_out \
--rust_thr 0.01 --zinc_thr 0.02 --lab_delta 6.0
Outputs:
color_out/<name>_palette.png
color_out/<name>_color_report.json (includes classification)
B) Alternative generator main.py
Similar to color.py, also prints a short console summary.
python main.py --img /path/to/img.jpg --k 3 --resize_max 1200 --outdir color_out
Outputs:
color_out/<name>_palette.png
color_out/<name>_color_report.json
C) Classify an existing report with classify.py
(Your message labeled this file as app.py—the code shows it’s a JSON classifier.)
python classify.py --report color_out/<name>_color_report.json \
--rust_thr 0.01 --zinc_thr 0.02
Console output:
{
"file": "img.jpg",
"rustish_ratio": 0.0342,
"zincish_ratio": 0.0051,
"classification": "rust"
}
How it works (short)
Convert image to CIELab: L*, a*, b* (OpenCV uses a scaled 8-bit Lab).
Compute medians of a* and b*, add lab_delta (e.g., 6.0) to form thresholds.
Rustish = fraction of pixels with a* > median(a*) + lab_delta.
Zincish = fraction with b* > median(b*) + lab_delta.
Decision rule:
If zincish_ratio > zinc_thr → zinc
Else if rustish_ratio > rust_thr → rust
Else → normal
These are simple heuristics for quick screening, not robust material detection.
Tuning tips
Increase lab_delta to be stricter (fewer pixels count as rustish/zincish).
Decrease thresholds rust_thr / zinc_thr to make classification more sensitive.
For large images, set --resize_max to speed up K-Means and stats.
Notes & gotchas
Color spaces: OpenCV reads images as BGR; conversions are handled internally.
Lighting & WB: Results vary with illumination and white balance. Try to keep input lighting consistent.
Performance: k=3 works well for speed. Increase for richer palettes at a compute cost.
Headless environments: Using opencv-python-headless avoids GUI dependencies.
Example programmatic use (Python)
import cv2 as cv
from api import rust_zinc_indicators, classify_from_ratios, dominant_colors_kmeans
bgr = cv.imread("sample.jpg", cv.IMREAD_COLOR)
inds = rust_zinc_indicators(bgr, delta=6.0)
label = classify_from_ratios(inds["rustish_ratio"], inds["zincish_ratio"],
rust_thr=0.01, zinc_thr=0.02)
palette = dominant_colors_kmeans(bgr, k=3)
print(label, inds, palette[:1])
Troubleshooting
Invalid image file. Could not decode image.
The upload wasn’t a valid image. Try a supported format (JPG/PNG).
ModuleNotFoundError / import errors:
Re-check your virtualenv and pip install -r requirements.txt.
Uvicorn not found:
Add uvicorn to requirements.txt and pip install -r requirements.txt.
License
Add your preferred license (e.g., MIT) as LICENSE.