Spaces:
Sleeping
A newer version of the Gradio SDK is available: 6.14.0
Methodology
Problem Framing
Classify an input image into one of {rust, zinc, normal} using fast, interpretable color cues. We rely on CIELab chroma tendencies:
Rustish surfaces skew a* positive (reddish/brownish).
Zincish surfaces skew b* positive (yellowish).
The method is heuristic (no material guarantees) but is fast, parameter-tunable, and explainable.
Pipeline Overview
Input → Preprocess → Color Analysis → Heuristic Ratios → Rule-based Classification → (Optional) Palette Visualization
Read & (optional) Resize
Load as BGR (cv.imread / bytes→cv.imdecode).
If max(H, W) > resize_max, downscale with INTER_AREA to speed up.
Color Space Transforms
BGR → RGB, BGR → HSV, BGR → Lab (OpenCV 8-bit Lab).
Compute per-space statistics (channel means/stds) for explainability.
Dominant Colors (K-Means)
Flatten pixels to N×3 (BGR float32).
Run cv.kmeans with KMEANS_PP_CENTERS, termination criteria (eps + max_iter).
Sort clusters by frequency to produce a palette (with shares) and a palette image.
Heuristic Indicators (Lab)
Split Lab: L*, a*, b*.
Compute medians: a_med, b_med.
Define thresholds: a_thr = a_med + Δ, b_thr = b_med + Δ where Δ = lab_delta (default 6.0).
Ratios: rustish_ratio = mean(a* > a_thr) zincish_ratio = mean(b* > b_thr)
Rule-based Classification
If zincish_ratio > zinc_thr ⇒ zinc
Else if rustish_ratio > rust_thr ⇒ rust
Else ⇒ normal
Outputs
Class label, rustish_ratio, zincish_ratio
Top k RGB colors and their shares
(CLI) JSON report + palette image
Parameters & Defaults
k (clusters): 3 — palette granularity vs. speed.
lab_delta (Δ): 6.0 — sensitivity around median; higher = stricter.
rust_thr: 0.01 — minimum fraction of above-threshold a* pixels.
zinc_thr: 0.02 — minimum fraction of above-threshold b* pixels.
resize_max: 1200 — longest side cap for speed (CLI).
Tuning tips: • Increase lab_delta to reduce false positives. • Decrease rust_thr/zinc_thr to increase sensitivity. • Keep k=3..5 unless you need very fine palettes.
Implementation Mapping
FastAPI (api.py): /classify/ accepts an image + query params → returns JSON with classification, ratios, and palette.
Gradio (gradio_app.py): Interactive UI with sliders for k, thresholds, and lab_delta.
CLI (reports):
color.py / main.py → stats + palette + heuristics (+ classification in color.py).
classify.py → reads a *_color_report.json and applies thresholds to output a label.
All core logic is shared: color conversions, K-Means, Lab heuristics, and the rule-based decision.
Complexity & Performance
K-Means: ~O(N × k × iters), where N = pixels after optional resize.
Heuristics: O(N) on the Lab channels.
Typical runtime: Sub-second to a few seconds on commodity CPUs for ≤2MP images with k=3.
Evaluation Protocol (Recommended)
Dataset: Curate labeled images for rust, zinc, normal under varied lighting/backgrounds.
Split: Train-free method; still use dev set to tune lab_delta, rust_thr, zinc_thr; hold out a test set.
Metrics: Accuracy, per-class precision/recall/F1; confusion matrix to catch “rust↔zinc” confusions.
Stress Tests: Vary illumination, white balance, exposure; add clutter/background metals; scale/resize sensitivity.
Ablations:
Different lab_delta values
Median vs. mean baselines for a*/b* thresholds
Removing K-Means (should not affect the classification, only explainability)
Assumptions & Limitations
Heuristic, not material science: Color alone can’t guarantee presence of oxides/plating.
Lighting-dependent: Harsh color casts and shadows can skew ratios.
Background leakage: Non-metal regions may influence medians and ratios.
Specular highlights: Can wash out chroma; consider controlled lighting for best results.
Mitigations:
Encourage consistent, diffuse illumination and controlled background.
Optionally crop/segment to the object of interest.
Adjust lab_delta and thresholds per environment.
Reproducibility
Dependencies: pinned in requirements.txt (use opencv-python-headless).
Determinism: OpenCV k-means with KMEANS_PP_CENTERS is typically stable; for strict reproducibility fix random seeds if you wrap k-means calls accordingly.
Reports: JSON artifacts and palette images are saved for auditability.
Deployment Notes
API: uvicorn api:app --host 0.0.0.0 --port 8000; OpenAPI docs at /docs.
UI: python gradio_app.py for operator testing/threshold tuning.
Batch: Use color.py/main.py to generate reports; classify.py to re-classify with updated thresholds.
Ethical Use
Intended for screening/triage in industrial contexts, not definitive corrosion/plating certification.
Users should verify with appropriate physical/chemical tests when decisions carry risk.