# 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.