Spaces:
Sleeping
Sleeping
| from typing import Dict, List | |
| import numpy as np | |
| from PIL import Image, ImageFilter | |
| ISSUE_LIST = [ | |
| "scratch_dent","paint_damage","cracked_windshield","flat_tire","engine_leak", | |
| "brake_wear","headlight_fault","battery_corrosion","rust","bumper_damage" | |
| ] | |
| def _edge_contrast(im: Image.Image) -> float: | |
| g = im.convert("L").resize((256,256)) | |
| arr = np.array(g, dtype=np.float32)/255.0 | |
| return float(arr.std()) | |
| def _redness(im: Image.Image) -> float: | |
| rgb = im.convert("RGB").resize((256,256)) | |
| arr = np.array(rgb, dtype=np.float32)/255.0 | |
| return float(arr[:,:,0].mean()) | |
| def _darkness(im: Image.Image) -> float: | |
| g = im.convert("L").resize((256,256)) | |
| arr = np.array(g, dtype=np.float32)/255.0 | |
| return float(1.0 - arr.mean()) | |
| def detect_issues(images: List[Image.Image]) -> List[str]: | |
| """Deterministic heuristics over multiple images; choose final set without probabilities.""" | |
| if not images: return ["diagnostic_inspection"] | |
| # aggregate signals | |
| contrast = np.mean([_edge_contrast(i) for i in images]) | |
| red = np.mean([_redness(i) for i in images]) | |
| dark = np.mean([_darkness(i) for i in images]) | |
| # thresholds chosen empirically; tune with dataset | |
| issues = set() | |
| if contrast > 0.22: | |
| issues.update(["scratch_dent","paint_damage","bumper_damage"]) | |
| if red > 0.55: | |
| issues.add("engine_leak") | |
| if dark > 0.55: | |
| issues.add("headlight_fault") | |
| # Always narrow to a final deterministic list of max 4 using rule priority | |
| priority = ["engine_leak","cracked_windshield","brake_wear","flat_tire","scratch_dent","paint_damage","bumper_damage","headlight_fault","battery_corrosion","rust"] | |
| final = [] | |
| for p in priority: | |
| if p in issues: | |
| final.append(p) | |
| if len(final) >= 4: | |
| break | |
| if not final: | |
| final = ["diagnostic_inspection"] | |
| return final | |