DRAPEa / app.py
andevs's picture
Update app.py
0ba129e verified
Raw
History Blame Contribute Delete
6.25 kB
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 """
<!DOCTYPE html>
<html>
<head><title>Drape 3D API</title><style>
body { font-family: Arial; max-width: 800px; margin: 50px auto; padding: 20px; }
h1 { color: #667eea; }
.endpoint { background: #f0f0f0; margin: 10px 0; padding: 10px; border-radius: 5px; }
</style></head>
<body>
<h1>๐Ÿ‘— Drape 3D AI Backend</h1>
<p>API is running!</p>
<div class="endpoint"><strong>POST /analyze/clothing</strong> - Analyze clothing</div>
<div class="endpoint"><strong>POST /recommend/style</strong> - Style recommendations</div>
<div class="endpoint"><strong>POST /virtual/tryon</strong> - Virtual try-on</div>
<div class="endpoint"><strong>GET /trends/current</strong> - Current trends</div>
<p><a href="/docs">๐Ÿ“– API Documentation</a></p>
</body>
</html>
"""
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=7860)