Spaces:
Sleeping
Sleeping
| import os, io, base64 | |
| from typing import List, Dict, Any | |
| import gradio as gr | |
| from PIL import Image | |
| from car_core.specs_model_space import build_label_space | |
| from car_core.models_zeroshot import ModelIDZeroShot | |
| from car_core.color_detect import dominant_color | |
| from car_core.issues import detect_issues | |
| from car_core.pricing import price_issues, load_regions | |
| from car_core.exporter import export_pdf, export_json | |
| LABEL_SPACE = build_label_space() | |
| MODEL = ModelIDZeroShot(LABEL_SPACE) | |
| REGIONS = load_regions() | |
| def _to_pil(obj): | |
| if isinstance(obj, dict) and "image" in obj: | |
| # Gradio File with base64 'image' key | |
| return Image.open(io.BytesIO(base64.b64decode(obj["image"].split(",")[-1]))) | |
| if isinstance(obj, str): | |
| return Image.open(obj) | |
| if hasattr(obj, "read"): | |
| return Image.open(obj) | |
| return obj | |
| def analyze(images: list, region: str): | |
| if not images: | |
| raise gr.Error("Upload at least one car image.") | |
| imgs = [] | |
| for it in images: | |
| try: | |
| imgs.append(_to_pil(it)) | |
| except Exception: | |
| pass | |
| if not imgs: | |
| raise gr.Error("Failed to decode images. Use JPG/PNG.") | |
| # Model decision: pick the most frequent top label across images | |
| votes = {} | |
| for im in imgs: | |
| lbl = MODEL.top_label(im) | |
| votes[lbl] = votes.get(lbl, 0) + 1 | |
| model_final = sorted(votes.items(), key=lambda kv: kv[1], reverse=True)[0][0] | |
| # Color decision: take the most frequent named color across images | |
| color_votes = {} | |
| for im in imgs: | |
| c = dominant_color(im)["name"] | |
| color_votes[c] = color_votes.get(c, 0) + 1 | |
| color_name = sorted(color_votes.items(), key=lambda kv: kv[1], reverse=True)[0][0] | |
| color_any = None | |
| # Recompute once to get rgb/hex for the chosen name | |
| for im in imgs: | |
| d = dominant_color(im) | |
| if d["name"] == color_name: | |
| color_any = d; break | |
| color_final = color_any or {"name": color_name, "rgb": (0,0,0), "hex": "#000000"} | |
| # Issues (deterministic) | |
| issues = detect_issues(imgs) | |
| # Pricing | |
| pricing = price_issues(issues, region_code=region) | |
| payload = { | |
| "vehicle": {"model": model_final, "color": color_final}, | |
| "region": region, | |
| "issues": issues, | |
| "pricing": pricing | |
| } | |
| os.makedirs("exports", exist_ok=True) | |
| pdf_path = "exports/report.pdf" | |
| json_path = "exports/report.json" | |
| export_pdf(payload, pdf_path) | |
| export_json(payload, json_path) | |
| def to_dl(path): | |
| with open(path, "rb") as f: | |
| return (os.path.basename(path), f.read()) | |
| # Deterministic, actionable output only | |
| result = { | |
| "vehicle": payload["vehicle"], | |
| "region": pricing["region"], | |
| "currency": pricing["currency"], | |
| "issues_with_solutions": [ | |
| { | |
| "issue": it["issue"], | |
| "solution": it["solution"], | |
| "labor_hours": it["labor_hours"], | |
| "labor_cost": it["labor_cost"], | |
| "parts_cost": it["parts_cost"], | |
| "line_total": it["line_total"] | |
| } for it in pricing["items"] | |
| ], | |
| "totals": { | |
| "subtotal": pricing["subtotal"], | |
| "tax": pricing["tax"], | |
| "grand_total": pricing["grand_total"] | |
| } | |
| } | |
| return result, to_dl(pdf_path), to_dl(json_path) | |
| with gr.Blocks(fill_height=True) as demo: | |
| gr.Markdown("## 🛠️ Car Analysis Advisor — multi‑image model/color/issue detection with exact pricing") | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| imgs = gr.File(label="Upload car image(s)", file_count="multiple", file_types=["image"]) | |
| region = gr.Dropdown(choices=list(REGIONS["regions"].keys()), value=REGIONS.get("default_region","IN-HYD"), label="Region (pricing)") | |
| run = gr.Button("Analyze", variant="primary") | |
| with gr.Column(scale=1): | |
| out = gr.JSON(label="Actionable results") | |
| pdf = gr.File(label="Download PDF") | |
| jj = gr.File(label="Download JSON") | |
| run.click(analyze, inputs=[imgs, region], outputs=[out, pdf, jj]) | |
| if __name__ == "__main__": | |
| demo.launch() | |