diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..e7103dac248d5b58114d883db899181f5742a4b2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,64 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text +app/static/results/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/706f091d-f713-4f34-88b1-b3eaa5082483_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/706f091d-f713-4f34-88b1-b3eaa5082483_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/86665944-f463-4be3-87be-2227b667ea4d_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/86665944-f463-4be3-87be-2227b667ea4d_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/8f2e9c10-9e39-415b-b634-e9cacff08670_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/8f2e9c10-9e39-415b-b634-e9cacff08670_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/db93084e-16d1-4448-b841-1ce1c0e1c201_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/db93084e-16d1-4448-b841-1ce1c0e1c201_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/de9bda87-c237-4c6b-8748-1ab245d4ec57_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/de9bda87-c237-4c6b-8748-1ab245d4ec57_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/f0a7c31c-d1cf-460a-abff-d32d76faa384_damage.png filter=lfs diff=lfs merge=lfs -text +app/static/results/f0a7c31c-d1cf-460a-abff-d32d76faa384_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/results/fdfef36b-2942-4bc8-bb26-ad6aad32d471_parts.png filter=lfs diff=lfs merge=lfs -text +app/static/uploads/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b.jpg filter=lfs diff=lfs merge=lfs -text +app/static/uploads/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9.jpg filter=lfs diff=lfs merge=lfs -text +app/static/uploads/4ea85461-64cd-4c8b-8ef9-3c9635df076b.jpg filter=lfs diff=lfs merge=lfs -text +app/static/uploads/706f091d-f713-4f34-88b1-b3eaa5082483.jpg filter=lfs diff=lfs merge=lfs -text +app/static/uploads/86665944-f463-4be3-87be-2227b667ea4d.jpg filter=lfs diff=lfs merge=lfs -text +app/static/uploads/8f2e9c10-9e39-415b-b634-e9cacff08670.jpg filter=lfs diff=lfs merge=lfs -text +app/static/uploads/9be81a29-214a-48af-ba99-8cab54a56d66.jpg filter=lfs diff=lfs merge=lfs -text +app/static/uploads/db93084e-16d1-4448-b841-1ce1c0e1c201.jpg filter=lfs diff=lfs merge=lfs -text diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..ec033f2c6676a3f2d96d88fcc0638a0b3a7426db --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM python:3.10-slim + +WORKDIR /code + +# Install system dependencies +RUN apt-get update && apt-get install -y \ + build-essential \ + libgl1-mesa-glx \ + && rm -rf /var/lib/apt/lists/* + +# Install Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Copy app code +COPY . . + +# Expose port +EXPOSE 7860 + +ENV PATH="/root/.local/bin:$PATH" + +# Run FastAPI app with uvicorn +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"] diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..fa4e1f0980c889e8d78c772799b3e1ea7bdce07e --- /dev/null +++ b/README.md @@ -0,0 +1,24 @@ +--- +title: Car Damage & Parts Detection +emoji: 🚗 +colorFrom: blue +colorTo: indigo +sdk: docker +app_file: app/main.py +pinned: false +--- + +# Car Damage & Parts Detection + +Upload a car image to detect damaged regions and parts using YOLOv8 models. + +## How to use +- Upload a car image. +- View annotated results and JSON output. + +## Deployment +This Space uses FastAPI and YOLOv8, running in a Docker container. + +## Model Weights +Model weights are downloaded at startup from public cloud links (not included in repo). + diff --git a/app/__pycache__/main.cpython-310.pyc b/app/__pycache__/main.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3835c8f9e42493609087384a36346e0828cf2521 Binary files /dev/null and b/app/__pycache__/main.cpython-310.pyc differ diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000000000000000000000000000000000000..07f95f02d4c984d3768aad3db63ecbe16d2b8b41 --- /dev/null +++ b/app/main.py @@ -0,0 +1,58 @@ + +# --- Model download logic (Hugging Face Hub) --- +import os +import requests + +def download_if_missing(url, dest): + if not os.path.exists(dest): + print(f"Downloading model from {url} to {dest}...") + os.makedirs(os.path.dirname(dest), exist_ok=True) + with requests.get(url, stream=True) as r: + r.raise_for_status() + with open(dest, "wb") as f: + for chunk in r.iter_content(chunk_size=8192): + f.write(chunk) + print("Download complete.") + +# Hugging Face direct download links +DAMAGE_MODEL_URL = "https://huggingface.co/AItoolstack/car_damage_detection/resolve/main/yolov8_models/damage/weights/weights/best.pt" +PARTS_MODEL_URL = "https://huggingface.co/AItoolstack/car_damage_detection/resolve/main/yolov8_models/parts/weights/weights/best.pt" + +DAMAGE_MODEL_PATH = os.path.join("models", "damage", "weights", "weights", "best.pt") +PARTS_MODEL_PATH = os.path.join("models", "parts", "weights", "weights", "best.pt") + +download_if_missing(DAMAGE_MODEL_URL, DAMAGE_MODEL_PATH) +download_if_missing(PARTS_MODEL_URL, PARTS_MODEL_PATH) + +from fastapi import FastAPI, File, UploadFile, BackgroundTasks +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates +from fastapi.responses import JSONResponse, HTMLResponse +from fastapi.middleware.cors import CORSMiddleware +import uvicorn +from datetime import datetime +import aiofiles +from pathlib import Path +import uuid +from app.routers import inference + +app = FastAPI(title="Car Damage Detection API") + +# CORS middleware +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# Mount static files +app.mount("/static", StaticFiles(directory="app/static"), name="static") +templates = Jinja2Templates(directory="app/templates") + +# Include routers +app.include_router(inference.router) + +if __name__ == "__main__": + uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) diff --git a/app/routers/__pycache__/inference.cpython-310.pyc b/app/routers/__pycache__/inference.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b551f19cb632a0ffe4afd88d23a3474108bc691e Binary files /dev/null and b/app/routers/__pycache__/inference.cpython-310.pyc differ diff --git a/app/routers/inference.py b/app/routers/inference.py new file mode 100644 index 0000000000000000000000000000000000000000..c0c6d6de379f2786309781b9b7a3fc4dd8f4ff05 --- /dev/null +++ b/app/routers/inference.py @@ -0,0 +1,218 @@ + +from fastapi import APIRouter, Request, UploadFile, File, Form +from fastapi.responses import HTMLResponse, FileResponse, JSONResponse +from fastapi.templating import Jinja2Templates +from starlette.background import BackgroundTask +import shutil +import os +import uuid +from pathlib import Path +from typing import Optional +import json +import base64 +from ultralytics import YOLO +import cv2 +import numpy as np + + +# Templates directory +TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "templates") +templates = Jinja2Templates(directory=TEMPLATES_DIR) + +router = APIRouter() + +UPLOAD_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "static", "uploads") +RESULTS_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "static", "results") + +os.makedirs(UPLOAD_DIR, exist_ok=True) +os.makedirs(RESULTS_DIR, exist_ok=True) + +ALLOWED_EXTENSIONS = {"jpg", "jpeg", "png", "tiff", "tif"} + +# Model paths +BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) +DAMAGE_MODEL_PATH = os.path.join(BASE_DIR, "models", "damage", "weights", "weights", "best.pt") +PARTS_MODEL_PATH = os.path.join(BASE_DIR, "models", "parts", "weights", "weights", "best.pt") + +# Class names for parts +PARTS_CLASS_NAMES = ['headlamp', 'front_bumper', 'hood', 'door', 'rear_bumper'] + +# Helper: Run YOLO inference and return results +def run_yolo_inference(model_path, image_path, task='segment'): + model = YOLO(model_path) + results = model.predict(source=image_path, imgsz=640, conf=0.25, save=False, task=task) + return results[0] + +# Helper: Draw masks and confidence on image +def draw_masks_and_conf(image_path, yolo_result, class_names=None): + img = cv2.imread(image_path) + overlay = img.copy() + out_img = img.copy() + colors = [(255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255), (0,255,255)] + for i, box in enumerate(yolo_result.boxes): + conf = float(box.conf[0]) + cls = int(box.cls[0]) + color = colors[cls % len(colors)] + # Draw bbox + x1, y1, x2, y2 = map(int, box.xyxy[0]) + cv2.rectangle(overlay, (x1, y1), (x2, y2), color, 2) + label = f"{class_names[cls] if class_names else 'damage'}: {conf:.2f}" + cv2.putText(overlay, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2) + # Draw mask if available + if hasattr(yolo_result, 'masks') and yolo_result.masks is not None: + mask = yolo_result.masks.data[i].cpu().numpy() + mask = (mask * 255).astype(np.uint8) + mask = cv2.resize(mask, (x2-x1, y2-y1)) + roi = overlay[y1:y2, x1:x2] + colored_mask = np.zeros_like(roi) + colored_mask[mask > 127] = color + overlay[y1:y2, x1:x2] = cv2.addWeighted(roi, 0.5, colored_mask, 0.5, 0) + out_img = cv2.addWeighted(overlay, 0.7, img, 0.3, 0) + return out_img + +# Helper: Generate JSON output +def generate_json_output(filename, damage_result, parts_result): + # Damage severity: use max confidence + severity_score = float(max([float(box.conf[0]) for box in damage_result.boxes], default=0)) + damage_regions = [] + for box in damage_result.boxes: + x1, y1, x2, y2 = map(float, box.xyxy[0]) + conf = float(box.conf[0]) + damage_regions.append({"bbox": [x1, y1, x2, y2], "confidence": conf}) + # Parts + parts = [] + for i, box in enumerate(parts_result.boxes): + x1, y1, x2, y2 = map(float, box.xyxy[0]) + conf = float(box.conf[0]) + cls = int(box.cls[0]) + # Damage %: use mask area / bbox area if available + damage_percentage = None + if hasattr(parts_result, 'masks') and parts_result.masks is not None: + mask = parts_result.masks.data[i].cpu().numpy() + mask_area = np.sum(mask > 0.5) + bbox_area = (x2-x1)*(y2-y1) + damage_percentage = float(mask_area / bbox_area) if bbox_area > 0 else None + parts.append({ + "part": PARTS_CLASS_NAMES[cls] if cls < len(PARTS_CLASS_NAMES) else str(cls), + "damaged": True, + "confidence": conf, + "damage_percentage": damage_percentage, + "bbox": [x1, y1, x2, y2] + }) + # Optionally, add base64 masks + # (not implemented here for brevity) + return { + "filename": filename, + "damage": { + "severity_score": severity_score, + "regions": damage_regions + }, + "parts": parts, + "cost_estimate": None + } + +# Dummy login credentials +def check_login(username: str, password: str) -> bool: + return username == "demo" and password == "demo123" + +@router.get("/", response_class=HTMLResponse) +def home(request: Request): + return templates.TemplateResponse("index.html", {"request": request, "result": None}) + +@router.post("/login", response_class=HTMLResponse) +def login(request: Request, username: str = Form(...), password: str = Form(...)): + if check_login(username, password): + return templates.TemplateResponse("index.html", {"request": request, "result": None, "user": username}) + return templates.TemplateResponse("login.html", {"request": request, "error": "Invalid credentials"}) + +@router.get("/login", response_class=HTMLResponse) +def login_page(request: Request): + return templates.TemplateResponse("login.html", {"request": request}) + +@router.post("/upload", response_class=HTMLResponse) +def upload_image(request: Request, file: UploadFile = File(...)): + ext = file.filename.split(".")[-1].lower() + if ext not in ALLOWED_EXTENSIONS: + return templates.TemplateResponse("index.html", {"request": request, "error": "Unsupported file type."}) + + # Save uploaded file + session_id = str(uuid.uuid4()) + upload_path = os.path.join(UPLOAD_DIR, f"{session_id}.{ext}") + with open(upload_path, "wb") as buffer: + shutil.copyfileobj(file.file, buffer) + + # Run both inferences + try: + damage_result = run_yolo_inference(DAMAGE_MODEL_PATH, upload_path) + parts_result = run_yolo_inference(PARTS_MODEL_PATH, upload_path) + + # Save annotated images + damage_img_path = os.path.join(RESULTS_DIR, f"{session_id}_damage.png") + parts_img_path = os.path.join(RESULTS_DIR, f"{session_id}_parts.png") + json_path = os.path.join(RESULTS_DIR, f"{session_id}_result.json") + damage_img_url = f"/static/results/{session_id}_damage.png" + parts_img_url = f"/static/results/{session_id}_parts.png" + json_url = f"/static/results/{session_id}_result.json" + + # Defensive: set to None by default + damage_img = None + parts_img = None + json_output = None + + # Only save and set if inference returns boxes + if hasattr(damage_result, 'boxes') and len(damage_result.boxes) > 0: + damage_img = draw_masks_and_conf(upload_path, damage_result) + cv2.imwrite(damage_img_path, damage_img) + if hasattr(parts_result, 'boxes') and len(parts_result.boxes) > 0: + parts_img = draw_masks_and_conf(upload_path, parts_result, class_names=PARTS_CLASS_NAMES) + cv2.imwrite(parts_img_path, parts_img) + if (hasattr(damage_result, 'boxes') and len(damage_result.boxes) > 0) or (hasattr(parts_result, 'boxes') and len(parts_result.boxes) > 0): + json_output = generate_json_output(file.filename, damage_result, parts_result) + with open(json_path, "w") as jf: + json.dump(json_output, jf, indent=2) + + # Prepare URLs for download (only if files exist) + result = { + "filename": file.filename, + "damage_image": damage_img_url if damage_img is not None else None, + "parts_image": parts_img_url if parts_img is not None else None, + "json": json_output, + "json_download": json_url if json_output is not None else None + } + # Debug log + print("[DEBUG] Result dict:", result) + except Exception as e: + result = { + "filename": file.filename, + "error": f"Inference failed: {str(e)}", + "damage_image": None, + "parts_image": None, + "json": None, + "json_download": None + } + print("[ERROR] Inference failed:", e) + + import threading + import time + def delayed_cleanup(): + time.sleep(300) # 5 minutes + try: + os.remove(upload_path) + except Exception: + pass + for suffix in ["_damage.png", "_parts.png", "_result.json"]: + try: + os.remove(os.path.join(RESULTS_DIR, f"{session_id}{suffix}")) + except Exception: + pass + + threading.Thread(target=delayed_cleanup, daemon=True).start() + + return templates.TemplateResponse( + "index.html", + { + "request": request, + "result": result, + "original_image": f"/static/uploads/{session_id}.{ext}" + } + ) diff --git a/app/static/css/style.css b/app/static/css/style.css new file mode 100644 index 0000000000000000000000000000000000000000..6d5e7cc7ab2b7868ad36c76754477800443e36ba --- /dev/null +++ b/app/static/css/style.css @@ -0,0 +1,140 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap'); + +body { + font-family: 'Roboto', Arial, sans-serif; + background: #f4f6fa; + margin: 0; + padding: 0; +} +.header { + background: linear-gradient(90deg, #003366 60%, #e30613 100%); + color: #fff; + padding: 24px 0 12px 0; + text-align: center; + box-shadow: 0 2px 8px #00336622; +} +.logo { + max-width: 180px; + margin-bottom: 10px; +} +@media (max-width: 600px) { + .logo { + max-width: 90px !important; + right: 10px !important; + top: 10px !important; + } + .header h2 { font-size: 1.1em; } +} +.container { + max-width: 950px; + margin: 40px auto 0 auto; + background: #fff; + padding: 32px 32px 24px 32px; + border-radius: 12px; + box-shadow: 0 4px 24px #00336622; +} +h2, h3, h4 { + color: #003366; + margin-top: 0; +} +form { + margin-bottom: 24px; + display: flex; + flex-direction: column; + align-items: center; +} +input[type="file"] { + margin-bottom: 16px; + font-size: 16px; +} +button { + background: #e30613; + color: #fff; + border: none; + padding: 12px 32px; + border-radius: 6px; + font-size: 16px; + font-weight: 700; + cursor: pointer; + transition: background 0.2s; + margin-bottom: 10px; +} +button:hover { + background: #003366; +} +.error { + color: #e30613; + margin-bottom: 16px; + font-weight: 700; +} +.images-row { + display: flex; + gap: 32px; + margin-bottom: 24px; + justify-content: center; + flex-wrap: wrap; +} +.result-img { + max-width: 260px; + border: 2px solid #e30613; + border-radius: 8px; + box-shadow: 0 2px 8px #00336622; + margin-bottom: 8px; +} +.result-label { + text-align: center; + font-weight: 700; + color: #003366; + margin-bottom: 8px; +} +.download-btn { + display: inline-block; + background: #003366; + color: #fff; + padding: 8px 18px; + border-radius: 5px; + text-decoration: none; + font-weight: 700; + margin-right: 10px; + margin-bottom: 10px; + transition: background 0.2s; +} +.download-btn:hover { + background: #e30613; +} +pre.json-output { + background: #f0f0f0; + padding: 16px; + border-radius: 6px; + font-size: 15px; + overflow-x: auto; + color: #222; + margin-bottom: 12px; + box-shadow: 0 1px 4px #00336611; +} +.copy-btn { + background: #e30613; + color: #fff; + border: none; + border-radius: 4px; + padding: 6px 14px; + font-size: 14px; + font-weight: 700; + cursor: pointer; + margin-bottom: 10px; + float: right; +} +.copy-btn:hover { + background: #003366; +} +.footer { + text-align: center; + color: #888; + font-size: 15px; + margin: 40px 0 10px 0; +} +@media (max-width: 900px) { + .container { padding: 16px; } + .images-row { gap: 12px; } + .result-img { max-width: 98vw; } +} diff --git a/app/static/img/logo.png b/app/static/img/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4405f1706410bd8243ece5e39dfbd9f0a953cc5e Binary files /dev/null and b/app/static/img/logo.png differ diff --git a/app/static/results/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b_damage.png b/app/static/results/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..e0099add0438da4480c5a1e2515b0914bbb3a2ac --- /dev/null +++ b/app/static/results/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:843234317ec8027fee1329fb191590a6523e6645fafa0717f71b267e6d97edf1 +size 1366857 diff --git a/app/static/results/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b_parts.png b/app/static/results/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..f765436de876551024ea307d36f6749862336d80 --- /dev/null +++ b/app/static/results/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7736748ab74a20eb2049e04494b66dc453b0b49d4cd41b3a7990447e6aee37d4 +size 1286254 diff --git a/app/static/results/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9_damage.png b/app/static/results/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..e0099add0438da4480c5a1e2515b0914bbb3a2ac --- /dev/null +++ b/app/static/results/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:843234317ec8027fee1329fb191590a6523e6645fafa0717f71b267e6d97edf1 +size 1366857 diff --git a/app/static/results/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9_parts.png b/app/static/results/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..f765436de876551024ea307d36f6749862336d80 --- /dev/null +++ b/app/static/results/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7736748ab74a20eb2049e04494b66dc453b0b49d4cd41b3a7990447e6aee37d4 +size 1286254 diff --git a/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_damage.png b/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..7c0f03b3957d6858277f0ed4ac4fc8b82ec38863 --- /dev/null +++ b/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2a3fa666110fa57240a3e356a4bbe258b03cde0d2027db12158ef65775504e57 +size 1436867 diff --git a/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_parts.png b/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..f60bdf189f2dc82e338c3b817f51fb8926085108 --- /dev/null +++ b/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bdcf896c24e952df34be4247e25dd2ab2f306cfb78f2d5d3bcd1a22c52cb3b6 +size 1414241 diff --git a/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_result.json b/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_result.json new file mode 100644 index 0000000000000000000000000000000000000000..704c3f838842a502ef1aae3a50dcb4d834afe1a8 --- /dev/null +++ b/app/static/results/4ea85461-64cd-4c8b-8ef9-3c9635df076b_result.json @@ -0,0 +1,86 @@ +{ + "filename": "28.jpg", + "damage": { + "severity_score": 0.7707259058952332, + "regions": [ + { + "bbox": [ + 522.2720947265625, + 530.5602416992188, + 728.9972534179688, + 892.2079467773438 + ], + "confidence": 0.7707259058952332 + }, + { + "bbox": [ + 660.1974487304688, + 512.72119140625, + 927.4169921875, + 883.8523559570312 + ], + "confidence": 0.6494596600532532 + }, + { + "bbox": [ + 196.1370086669922, + 277.27374267578125, + 366.7127990722656, + 712.44775390625 + ], + "confidence": 0.32863757014274597 + } + ] + }, + "parts": [ + { + "part": "hood", + "damaged": true, + "confidence": 0.9392628073692322, + "damage_percentage": 0.20169149219339333, + "bbox": [ + 411.4404296875, + 342.9278869628906, + 952.9636840820312, + 578.835693359375 + ] + }, + { + "part": "headlamp", + "damaged": true, + "confidence": 0.9351847171783447, + "damage_percentage": 1.7647002993974346, + "bbox": [ + 531.9706420898438, + 553.8896484375, + 706.9000854492188, + 656.3943481445312 + ] + }, + { + "part": "door", + "damaged": true, + "confidence": 0.9011728763580322, + "damage_percentage": 0.29901854346557094, + "bbox": [ + 143.66470336914062, + 224.3675537109375, + 391.3798522949219, + 737.7504272460938 + ] + }, + { + "part": "front_bumper", + "damaged": true, + "confidence": 0.8590587377548218, + "damage_percentage": 0.03409931158993679, + "bbox": [ + 461.2880859375, + 534.1759033203125, + 978.0007934570312, + 874.1959838867188 + ] + } + ], + "cost_estimate": null +} \ No newline at end of file diff --git a/app/static/results/706f091d-f713-4f34-88b1-b3eaa5082483_damage.png b/app/static/results/706f091d-f713-4f34-88b1-b3eaa5082483_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..7f72dc88d9ec70466457b100df4059d5a9a9bbbb --- /dev/null +++ b/app/static/results/706f091d-f713-4f34-88b1-b3eaa5082483_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:864160d73f14a642d0c79c1d5583bc7bbd5783b7fd1a7651cb10b6b404bbc656 +size 1369802 diff --git a/app/static/results/706f091d-f713-4f34-88b1-b3eaa5082483_parts.png b/app/static/results/706f091d-f713-4f34-88b1-b3eaa5082483_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..1ec8f6235bbe77aed73a68b5f433d300dd9017e3 --- /dev/null +++ b/app/static/results/706f091d-f713-4f34-88b1-b3eaa5082483_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:434038d40e7c0ea3b9ad891c20f4909537d66bd728dc831dce8fe805390c4669 +size 1326584 diff --git a/app/static/results/86665944-f463-4be3-87be-2227b667ea4d_damage.png b/app/static/results/86665944-f463-4be3-87be-2227b667ea4d_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..e0099add0438da4480c5a1e2515b0914bbb3a2ac --- /dev/null +++ b/app/static/results/86665944-f463-4be3-87be-2227b667ea4d_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:843234317ec8027fee1329fb191590a6523e6645fafa0717f71b267e6d97edf1 +size 1366857 diff --git a/app/static/results/86665944-f463-4be3-87be-2227b667ea4d_parts.png b/app/static/results/86665944-f463-4be3-87be-2227b667ea4d_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..f765436de876551024ea307d36f6749862336d80 --- /dev/null +++ b/app/static/results/86665944-f463-4be3-87be-2227b667ea4d_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7736748ab74a20eb2049e04494b66dc453b0b49d4cd41b3a7990447e6aee37d4 +size 1286254 diff --git a/app/static/results/8f2e9c10-9e39-415b-b634-e9cacff08670_damage.png b/app/static/results/8f2e9c10-9e39-415b-b634-e9cacff08670_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..7f72dc88d9ec70466457b100df4059d5a9a9bbbb --- /dev/null +++ b/app/static/results/8f2e9c10-9e39-415b-b634-e9cacff08670_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:864160d73f14a642d0c79c1d5583bc7bbd5783b7fd1a7651cb10b6b404bbc656 +size 1369802 diff --git a/app/static/results/8f2e9c10-9e39-415b-b634-e9cacff08670_parts.png b/app/static/results/8f2e9c10-9e39-415b-b634-e9cacff08670_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..1ec8f6235bbe77aed73a68b5f433d300dd9017e3 --- /dev/null +++ b/app/static/results/8f2e9c10-9e39-415b-b634-e9cacff08670_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:434038d40e7c0ea3b9ad891c20f4909537d66bd728dc831dce8fe805390c4669 +size 1326584 diff --git a/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_damage.png b/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..e883b086cb081f2fdae0802efe551e201d3e26e6 --- /dev/null +++ b/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11364615cb173dfae5739657f8ecca4f1b550e82a8565a8347b52c20fed3c134 +size 1425181 diff --git a/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_parts.png b/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..5d232cba017c3b67a6c0d9d73d546c92abec9dd2 --- /dev/null +++ b/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9076be5837c8bc5b361a12ada76a5f5088ddab7b5bbed8812e7cf8f6108199b1 +size 1407342 diff --git a/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_result.json b/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_result.json new file mode 100644 index 0000000000000000000000000000000000000000..b8a2e07664a9dc64e69f16ccac800d4b9a2c3834 --- /dev/null +++ b/app/static/results/9be81a29-214a-48af-ba99-8cab54a56d66_result.json @@ -0,0 +1,83 @@ +{ + "filename": "72.jpg", + "damage": { + "severity_score": 0.6467820405960083, + "regions": [ + { + "bbox": [ + 20.340744018554688, + 93.4926986694336, + 112.2962646484375, + 271.3760986328125 + ], + "confidence": 0.6467820405960083 + }, + { + "bbox": [ + 129.6874237060547, + 107.35161590576172, + 238.290771484375, + 377.91192626953125 + ], + "confidence": 0.43937909603118896 + }, + { + "bbox": [ + 127.2110595703125, + 23.03559684753418, + 353.25946044921875, + 420.0022888183594 + ], + "confidence": 0.3795366883277893 + }, + { + "bbox": [ + 126.8061752319336, + 38.61054611206055, + 242.341064453125, + 433.29034423828125 + ], + "confidence": 0.3542208969593048 + } + ] + }, + "parts": [ + { + "part": "hood", + "damaged": true, + "confidence": 0.746218204498291, + "damage_percentage": 0.2284878057871993, + "bbox": [ + 1.409912109375, + 666.6517944335938, + 200.2979278564453, + 1020.8939819335938 + ] + }, + { + "part": "hood", + "damaged": true, + "confidence": 0.5614964962005615, + "damage_percentage": 0.04930226900457474, + "bbox": [ + 265.2085876464844, + 582.6806030273438, + 1017.8049926757812, + 1016.5338745117188 + ] + }, + { + "part": "hood", + "damaged": true, + "confidence": 0.5332340598106384, + "damage_percentage": 0.25070920790460405, + "bbox": [ + 0.0, + 501.2841796875, + 358.5841369628906, + 680.34912109375 + ] + } + ], + "cost_estimate": null +} \ No newline at end of file diff --git a/app/static/results/db93084e-16d1-4448-b841-1ce1c0e1c201_damage.png b/app/static/results/db93084e-16d1-4448-b841-1ce1c0e1c201_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..e0099add0438da4480c5a1e2515b0914bbb3a2ac --- /dev/null +++ b/app/static/results/db93084e-16d1-4448-b841-1ce1c0e1c201_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:843234317ec8027fee1329fb191590a6523e6645fafa0717f71b267e6d97edf1 +size 1366857 diff --git a/app/static/results/db93084e-16d1-4448-b841-1ce1c0e1c201_parts.png b/app/static/results/db93084e-16d1-4448-b841-1ce1c0e1c201_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..f765436de876551024ea307d36f6749862336d80 --- /dev/null +++ b/app/static/results/db93084e-16d1-4448-b841-1ce1c0e1c201_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7736748ab74a20eb2049e04494b66dc453b0b49d4cd41b3a7990447e6aee37d4 +size 1286254 diff --git a/app/static/results/de9bda87-c237-4c6b-8748-1ab245d4ec57_damage.png b/app/static/results/de9bda87-c237-4c6b-8748-1ab245d4ec57_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..20c4ec21db3dbe4fd18e310ae881470052ff106b --- /dev/null +++ b/app/static/results/de9bda87-c237-4c6b-8748-1ab245d4ec57_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3ce4e1711a1354f0bc289fa81c2fca85f95ba8ab3c97b85dda4977405d7aaadc +size 1317902 diff --git a/app/static/results/de9bda87-c237-4c6b-8748-1ab245d4ec57_parts.png b/app/static/results/de9bda87-c237-4c6b-8748-1ab245d4ec57_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..7046762650a9c10ff7cd8f4a27d0b708424581bc --- /dev/null +++ b/app/static/results/de9bda87-c237-4c6b-8748-1ab245d4ec57_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5e430bf68e1de01b04208fd84d049e8bebf1199d5f2caa3ae0bebdb2be2938e8 +size 1175140 diff --git a/app/static/results/f0a7c31c-d1cf-460a-abff-d32d76faa384_damage.png b/app/static/results/f0a7c31c-d1cf-460a-abff-d32d76faa384_damage.png new file mode 100644 index 0000000000000000000000000000000000000000..f24c5bd94b0fa0b6be8fba731c8aab03009878c8 --- /dev/null +++ b/app/static/results/f0a7c31c-d1cf-460a-abff-d32d76faa384_damage.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a2257fb2db1401111cc2c0d08d0a16ed7d5796983155660c33ea8c895174fbc0 +size 624913 diff --git a/app/static/results/f0a7c31c-d1cf-460a-abff-d32d76faa384_parts.png b/app/static/results/f0a7c31c-d1cf-460a-abff-d32d76faa384_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..e881e58190de8b68c28c691dec5fd5376d4b5b33 --- /dev/null +++ b/app/static/results/f0a7c31c-d1cf-460a-abff-d32d76faa384_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2193c3f71bc942286682aebacc32ac19458f2431f5347a5d947472fa55b9e0a6 +size 628654 diff --git a/app/static/results/fdfef36b-2942-4bc8-bb26-ad6aad32d471_parts.png b/app/static/results/fdfef36b-2942-4bc8-bb26-ad6aad32d471_parts.png new file mode 100644 index 0000000000000000000000000000000000000000..6155784c90add9a7405898864274feb98dc1ffc0 --- /dev/null +++ b/app/static/results/fdfef36b-2942-4bc8-bb26-ad6aad32d471_parts.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b4e32a45e5c02e186b8a977686ac356e58460425e5ab9abb84973d1f82010d39 +size 920202 diff --git a/app/static/uploads/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b.jpg b/app/static/uploads/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4885d03fce37826d9e36f0b8766183bd2c71b473 --- /dev/null +++ b/app/static/uploads/1d91cb91-46f0-4123-9b3d-dd963a4a1b8b.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:092aba449d902c7e88a7cd2b4b588f584dbb71ec46d3f1ae6610caced7da72a6 +size 111180 diff --git a/app/static/uploads/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9.jpg b/app/static/uploads/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4885d03fce37826d9e36f0b8766183bd2c71b473 --- /dev/null +++ b/app/static/uploads/2b9a2716-12dc-4fec-8b1b-8a26375e4fd9.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:092aba449d902c7e88a7cd2b4b588f584dbb71ec46d3f1ae6610caced7da72a6 +size 111180 diff --git a/app/static/uploads/4ea85461-64cd-4c8b-8ef9-3c9635df076b.jpg b/app/static/uploads/4ea85461-64cd-4c8b-8ef9-3c9635df076b.jpg new file mode 100644 index 0000000000000000000000000000000000000000..319c333be5e8e895f9c28363154141a3a17b02c5 --- /dev/null +++ b/app/static/uploads/4ea85461-64cd-4c8b-8ef9-3c9635df076b.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9727abba3fdd97eeb17e763d77479943b88f9c6d72185d919ae852b5f80e8837 +size 104751 diff --git a/app/static/uploads/706f091d-f713-4f34-88b1-b3eaa5082483.jpg b/app/static/uploads/706f091d-f713-4f34-88b1-b3eaa5082483.jpg new file mode 100644 index 0000000000000000000000000000000000000000..34cdc6eb2e01407c0262fbc1d5afe93d9bbca0e1 --- /dev/null +++ b/app/static/uploads/706f091d-f713-4f34-88b1-b3eaa5082483.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd09285677be22be4bc70a81ab947db3745875c585b6a9339ad82e07dd733c74 +size 107319 diff --git a/app/static/uploads/86665944-f463-4be3-87be-2227b667ea4d.jpg b/app/static/uploads/86665944-f463-4be3-87be-2227b667ea4d.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4885d03fce37826d9e36f0b8766183bd2c71b473 --- /dev/null +++ b/app/static/uploads/86665944-f463-4be3-87be-2227b667ea4d.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:092aba449d902c7e88a7cd2b4b588f584dbb71ec46d3f1ae6610caced7da72a6 +size 111180 diff --git a/app/static/uploads/8f2e9c10-9e39-415b-b634-e9cacff08670.jpg b/app/static/uploads/8f2e9c10-9e39-415b-b634-e9cacff08670.jpg new file mode 100644 index 0000000000000000000000000000000000000000..34cdc6eb2e01407c0262fbc1d5afe93d9bbca0e1 --- /dev/null +++ b/app/static/uploads/8f2e9c10-9e39-415b-b634-e9cacff08670.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd09285677be22be4bc70a81ab947db3745875c585b6a9339ad82e07dd733c74 +size 107319 diff --git a/app/static/uploads/9be81a29-214a-48af-ba99-8cab54a56d66.jpg b/app/static/uploads/9be81a29-214a-48af-ba99-8cab54a56d66.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d9d45034fcec0dbb9c3bc4fbdf0f5ac5dbdedc51 --- /dev/null +++ b/app/static/uploads/9be81a29-214a-48af-ba99-8cab54a56d66.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30936869771053b22752ec10a1c339e40e43061291d8dce60586093dbb87a692 +size 116112 diff --git a/app/static/uploads/db93084e-16d1-4448-b841-1ce1c0e1c201.jpg b/app/static/uploads/db93084e-16d1-4448-b841-1ce1c0e1c201.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4885d03fce37826d9e36f0b8766183bd2c71b473 --- /dev/null +++ b/app/static/uploads/db93084e-16d1-4448-b841-1ce1c0e1c201.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:092aba449d902c7e88a7cd2b4b588f584dbb71ec46d3f1ae6610caced7da72a6 +size 111180 diff --git a/app/static/uploads/de9bda87-c237-4c6b-8748-1ab245d4ec57.jpg b/app/static/uploads/de9bda87-c237-4c6b-8748-1ab245d4ec57.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aeac59a2d006afbf62b78b7fd4e3fbbbebdd4a51 Binary files /dev/null and b/app/static/uploads/de9bda87-c237-4c6b-8748-1ab245d4ec57.jpg differ diff --git a/app/static/uploads/f0a7c31c-d1cf-460a-abff-d32d76faa384.jpg b/app/static/uploads/f0a7c31c-d1cf-460a-abff-d32d76faa384.jpg new file mode 100644 index 0000000000000000000000000000000000000000..732da4aeaa5c496444193a3ed4f817dcee716337 Binary files /dev/null and b/app/static/uploads/f0a7c31c-d1cf-460a-abff-d32d76faa384.jpg differ diff --git a/app/static/uploads/fdfef36b-2942-4bc8-bb26-ad6aad32d471.jpg b/app/static/uploads/fdfef36b-2942-4bc8-bb26-ad6aad32d471.jpg new file mode 100644 index 0000000000000000000000000000000000000000..792589945d9465f8056de27ac8bfc328fb73a269 Binary files /dev/null and b/app/static/uploads/fdfef36b-2942-4bc8-bb26-ad6aad32d471.jpg differ diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000000000000000000000000000000000000..db27280cba691fe37e2b453a9983ebe1faf15aea --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,82 @@ + + +
+ +