File size: 4,192 Bytes
94332c9
 
1c7bc31
b9985cf
1c7bc31
94332c9
 
 
 
 
 
1c7bc31
94332c9
 
 
1c7bc31
94332c9
 
 
 
 
 
 
 
 
1c7bc31
94332c9
 
 
 
 
 
 
 
 
 
 
1c7bc31
94332c9
 
 
 
 
 
1c7bc31
94332c9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1c7bc31
94332c9
1c7bc31
94332c9
 
1c7bc31
 
94332c9
 
1c7bc31
 
94332c9
 
 
 
1c7bc31
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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()