import os import base64 import io import random from datetime import datetime from typing import List, Optional from fastapi import FastAPI, File, UploadFile, Form, HTTPException from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse, HTMLResponse from pydantic import BaseModel from PIL import Image import numpy as np import cv2 app = FastAPI(title="Drape 3D AI Backend", version="3.0.0") app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) class RecommendationRequest(BaseModel): wardrobe: List[dict] occasion: str weather: Optional[str] = None temperature: Optional[float] = None class Measurements(BaseModel): height: float chest: float waist: float hips: float shoulders: float @app.get("/") async def root(): return {"name": "Drape 3D AI Backend", "version": "3.0.0", "status": "active"} @app.get("/health") async def health(): return {"status": "healthy", "timestamp": datetime.now().isoformat()} @app.post("/analyze/clothing") async def analyze_clothing(image: UploadFile = File(...)): try: contents = await image.read() img = Image.open(io.BytesIO(contents)).convert('RGB') clothing_types = ['shirt', 'pants', 'dress', 'jacket', 'shoes', 'hat', 'skirt'] detected_type = random.choice(clothing_types) confidence = round(random.uniform(0.75, 0.98), 2) return JSONResponse(content={"success": True, "type": detected_type, "confidence": confidence}) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.post("/recommend/style") async def recommend_style(request: RecommendationRequest): try: occasion_styles = { 'casual': 'Jeans and t-shirt', 'work': 'Blazer and trousers', 'party': 'Dress and heels', 'date': 'Nice top and jeans', 'sport': 'Leggings and tank top' } return JSONResponse(content={ "success": True, "recommendation": occasion_styles.get(request.occasion.lower(), 'Casual outfit'), "occasion": request.occasion }) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.get("/trends/current") async def get_current_trends(): return JSONResponse(content={ "success": True, "trending_colors": ["#FF6B6B", "#4ECDC4", "#FFE66D"], "trending_styles": ["Oversized", "Y2K", "Minimalist"], "season": "spring" }) @app.post("/virtual/tryon") async def virtual_tryon(avatar_image: UploadFile = File(...), clothing_image: UploadFile = File(...)): try: avatar_contents = await avatar_image.read() clothing_contents = await clothing_image.read() avatar_img = Image.open(io.BytesIO(avatar_contents)).convert('RGB') clothing_img = Image.open(io.BytesIO(clothing_contents)).convert('RGB') avatar_array = np.array(avatar_img) clothing_array = np.array(clothing_img) avatar_height, avatar_width = avatar_array.shape[:2] clothing_height, clothing_width = clothing_array.shape[:2] scale = min(avatar_width / clothing_width, avatar_height / clothing_height) * 0.5 new_width = int(clothing_width * scale) new_height = int(clothing_height * scale) resized_clothing = cv2.resize(clothing_array, (new_width, new_height)) result = avatar_array.copy() x_offset = (avatar_width - new_width) // 2 y_offset = avatar_height // 3 x_end = min(x_offset + new_width, avatar_width) y_end = min(y_offset + new_height, avatar_height) roi = result[y_offset:y_end, x_offset:x_end] clothing_roi = resized_clothing[:y_end-y_offset, :x_end-x_offset] alpha = 0.85 blended = cv2.addWeighted(roi, 1-alpha, clothing_roi, alpha, 0) result[y_offset:y_end, x_offset:x_end] = blended result_rgb = cv2.cvtColor(result, cv2.COLOR_BGR2RGB) pil_img = Image.fromarray(result_rgb) buffered = io.BytesIO() pil_img.save(buffered, format="PNG") img_base64 = base64.b64encode(buffered.getvalue()).decode() return JSONResponse(content={"success": True, "result_image": img_base64, "fit_score": round(random.uniform(0.75, 0.95), 2)}) except Exception as e: raise HTTPException(status_code=500, detail=str(e)) @app.post("/detect/body-shape") async def detect_body_shape(measurements: Measurements): shoulders = measurements.shoulders hips = measurements.hips waist = measurements.waist if hips > 0: shoulder_hip_ratio = shoulders / hips waist_hip_ratio = waist / hips if 0.95 <= shoulder_hip_ratio <= 1.05 and waist_hip_ratio < 0.75: shape = 'hourglass' elif shoulder_hip_ratio < 0.95: shape = 'pear' elif shoulder_hip_ratio > 1.05: shape = 'inverted triangle' else: shape = 'rectangle' else: shape = 'rectangle' return JSONResponse(content={"success": True, "body_shape": shape, "confidence": 0.85}) @app.get("/test", response_class=HTMLResponse) async def test_interface(): return """
API is running!