Spaces:
Runtime error
Runtime error
hamzaanwar12 commited on
Commit ·
e4cf3ad
1
Parent(s): f555976
checking the server
Browse files
app.py
CHANGED
|
@@ -12,6 +12,7 @@ os.environ["https_proxy"] = ""
|
|
| 12 |
import threading
|
| 13 |
import requests
|
| 14 |
from huggingface_hub import snapshot_download
|
|
|
|
| 15 |
import base64
|
| 16 |
import io
|
| 17 |
import json
|
|
@@ -261,6 +262,8 @@ def initialize_models():
|
|
| 261 |
annotation_file = pd.read_csv(annotation_file_path, sep=':')
|
| 262 |
annotation_file = annotation_file.set_index('name')
|
| 263 |
|
|
|
|
|
|
|
| 264 |
log("✅ Models initialized successfully")
|
| 265 |
|
| 266 |
except Exception as e:
|
|
@@ -273,6 +276,7 @@ def build_pose_img(annotation_file, img_path):
|
|
| 273 |
log(f"📄 Index Sample: {annotation_file.index[:5]}")
|
| 274 |
log(f"📄 Does key exist?: {os.path.basename(img_path) in annotation_file.index}")
|
| 275 |
|
|
|
|
| 276 |
string = annotation_file.loc[os.path.basename(img_path)]
|
| 277 |
array = load_pose_cords_from_strings(string['keypoints_y'], string['keypoints_x'])
|
| 278 |
pose_map = torch.tensor(cords_to_map(array, (256, 256), (256, 176)).transpose(2, 0, 1), dtype=torch.float32)
|
|
@@ -316,7 +320,7 @@ def pose_transfer(source_image, test_pair_index):
|
|
| 316 |
c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[bsz:]])
|
| 317 |
down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample, sample]).to(dtype=weight_dtype)
|
| 318 |
for sample in down_block_additional_residuals]
|
| 319 |
-
up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), torch.
|
| 320 |
for k, v in up_block_additional_residuals.items()}
|
| 321 |
|
| 322 |
noise_scheduler.set_timesteps(cfg.TEST.NUM_INFERENCE_STEPS)
|
|
@@ -337,6 +341,8 @@ def pose_transfer(source_image, test_pair_index):
|
|
| 337 |
sampling_imgs = sampling_imgs.clamp(0, 1)
|
| 338 |
|
| 339 |
# Convert to PIL image
|
|
|
|
|
|
|
| 340 |
output_img = Image.fromarray(
|
| 341 |
(sampling_imgs[0] * 255.)
|
| 342 |
.permute((1, 2, 0))
|
|
@@ -346,14 +352,169 @@ def pose_transfer(source_image, test_pair_index):
|
|
| 346 |
.astype(np.uint8)
|
| 347 |
)
|
| 348 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 349 |
log("✅ Pose transfer completed successfully")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 350 |
return output_img
|
| 351 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 352 |
# ==============================
|
| 353 |
-
#
|
| 354 |
# ==============================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
|
| 356 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 357 |
from fastapi.responses import JSONResponse
|
| 358 |
from fastapi.middleware.cors import CORSMiddleware
|
| 359 |
from PIL import Image
|
|
@@ -372,15 +533,6 @@ app.add_middleware(
|
|
| 372 |
allow_headers=["*"],
|
| 373 |
)
|
| 374 |
|
| 375 |
-
@app.get("/health")
|
| 376 |
-
async def health_check():
|
| 377 |
-
"""Health check endpoint to verify server status"""
|
| 378 |
-
return {
|
| 379 |
-
"status": "healthy",
|
| 380 |
-
"model_ready": model_ready,
|
| 381 |
-
"message": "Server is running" if model_ready else "Server running but models not ready"
|
| 382 |
-
}
|
| 383 |
-
|
| 384 |
@app.post("/pose-transfer")
|
| 385 |
async def pose_transfer_api(
|
| 386 |
test_pair_index: int = Form(...),
|
|
@@ -388,9 +540,6 @@ async def pose_transfer_api(
|
|
| 388 |
image_base64: str = Form(None)
|
| 389 |
):
|
| 390 |
try:
|
| 391 |
-
if not model_ready:
|
| 392 |
-
raise HTTPException(status_code=503, detail="Models not ready. Please wait for models to be downloaded and initialized.")
|
| 393 |
-
|
| 394 |
# Get input image
|
| 395 |
if source_image:
|
| 396 |
image_bytes = await source_image.read()
|
|
@@ -401,13 +550,12 @@ async def pose_transfer_api(
|
|
| 401 |
image_bytes = base64.b64decode(image_base64)
|
| 402 |
image = Image.open(BytesIO(image_bytes)).convert("RGB")
|
| 403 |
else:
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
|
| 408 |
-
raise HTTPException(status_code=400, detail=f"Test pair index must be between 0 and {len(test_pairs)-1}")
|
| 409 |
|
| 410 |
-
#
|
| 411 |
output_image = pose_transfer(image, test_pair_index)
|
| 412 |
|
| 413 |
# Convert result to base64
|
|
@@ -422,35 +570,28 @@ async def pose_transfer_api(
|
|
| 422 |
"output_image_base64": f"data:image/png;base64,{img_base64}"
|
| 423 |
}
|
| 424 |
)
|
| 425 |
-
except HTTPException:
|
| 426 |
-
raise
|
| 427 |
except Exception as e:
|
| 428 |
import traceback
|
| 429 |
tb = traceback.format_exc()
|
| 430 |
-
|
| 431 |
-
|
|
|
|
|
|
|
| 432 |
|
| 433 |
-
|
| 434 |
-
"""Initialize models before starting the server"""
|
| 435 |
-
global model_ready
|
| 436 |
-
|
| 437 |
-
print("Checking if models are available...")
|
| 438 |
if is_model_ready():
|
| 439 |
-
print("✅ Models found. Initializing...")
|
| 440 |
model_ready = True
|
| 441 |
initialize_models()
|
| 442 |
-
print("✅ Models initialized successfully")
|
| 443 |
-
else:
|
| 444 |
-
print("⚠️ Models not found. Starting download process...")
|
| 445 |
-
# Download models synchronously (blocking)
|
| 446 |
-
download_models()
|
| 447 |
|
| 448 |
-
|
| 449 |
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 453 |
|
| 454 |
-
|
| 455 |
-
print("Starting server on http://0.0.0.0:8000")
|
| 456 |
-
uvicorn.run(app, host="0.0.0.0", port=8000)
|
|
|
|
| 12 |
import threading
|
| 13 |
import requests
|
| 14 |
from huggingface_hub import snapshot_download
|
| 15 |
+
import gradio as gr
|
| 16 |
import base64
|
| 17 |
import io
|
| 18 |
import json
|
|
|
|
| 262 |
annotation_file = pd.read_csv(annotation_file_path, sep=':')
|
| 263 |
annotation_file = annotation_file.set_index('name')
|
| 264 |
|
| 265 |
+
|
| 266 |
+
|
| 267 |
log("✅ Models initialized successfully")
|
| 268 |
|
| 269 |
except Exception as e:
|
|
|
|
| 276 |
log(f"📄 Index Sample: {annotation_file.index[:5]}")
|
| 277 |
log(f"📄 Does key exist?: {os.path.basename(img_path) in annotation_file.index}")
|
| 278 |
|
| 279 |
+
|
| 280 |
string = annotation_file.loc[os.path.basename(img_path)]
|
| 281 |
array = load_pose_cords_from_strings(string['keypoints_y'], string['keypoints_x'])
|
| 282 |
pose_map = torch.tensor(cords_to_map(array, (256, 256), (256, 176)).transpose(2, 0, 1), dtype=torch.float32)
|
|
|
|
| 320 |
c_new = torch.cat([c_new[:bsz], c_new[:bsz], c_new[bsz:]])
|
| 321 |
down_block_additional_residuals = [torch.cat([torch.zeros_like(sample), sample, sample]).to(dtype=weight_dtype)
|
| 322 |
for sample in down_block_additional_residuals]
|
| 323 |
+
up_block_additional_residuals = {k: torch.cat([torch.zeros_like(v), torch.zeros_like(v), v]).to(dtype=weight_dtype)
|
| 324 |
for k, v in up_block_additional_residuals.items()}
|
| 325 |
|
| 326 |
noise_scheduler.set_timesteps(cfg.TEST.NUM_INFERENCE_STEPS)
|
|
|
|
| 341 |
sampling_imgs = sampling_imgs.clamp(0, 1)
|
| 342 |
|
| 343 |
# Convert to PIL image
|
| 344 |
+
# output_img = Image.fromarray((sampling_imgs[0] * 255.).permute((1, 2, 0)).long().cpu().numpy().astype(np.uint8)).resize((256, 256))
|
| 345 |
+
# Convert tensor to PIL image without resizing
|
| 346 |
output_img = Image.fromarray(
|
| 347 |
(sampling_imgs[0] * 255.)
|
| 348 |
.permute((1, 2, 0))
|
|
|
|
| 352 |
.astype(np.uint8)
|
| 353 |
)
|
| 354 |
|
| 355 |
+
# ✅ Save image in-memory as PNG, preserving original size
|
| 356 |
+
img_bytes = io.BytesIO()
|
| 357 |
+
output_img.save(img_bytes, format="PNG")
|
| 358 |
+
img_bytes.seek(0)
|
| 359 |
+
|
| 360 |
log("✅ Pose transfer completed successfully")
|
| 361 |
+
log(f"🔄 output_img size: {output_img.size}")
|
| 362 |
+
log(f"🔄 output_img butes: {img_bytes}")
|
| 363 |
+
|
| 364 |
+
|
| 365 |
+
|
| 366 |
+
|
| 367 |
return output_img
|
| 368 |
|
| 369 |
+
def start_download():
|
| 370 |
+
"""Start model download in a separate thread."""
|
| 371 |
+
global download_thread, download_log, cancel_download
|
| 372 |
+
if download_thread and download_thread.is_alive():
|
| 373 |
+
return "⚠️ Download already running..."
|
| 374 |
+
|
| 375 |
+
download_log = []
|
| 376 |
+
cancel_download = False
|
| 377 |
+
download_thread = threading.Thread(target=download_models)
|
| 378 |
+
download_thread.start()
|
| 379 |
+
return "📥 Download started..."
|
| 380 |
+
|
| 381 |
+
def get_download_status():
|
| 382 |
+
"""Get the latest log status."""
|
| 383 |
+
global download_thread
|
| 384 |
+
status = "\n".join(download_log) if download_log else "Preparing download..."
|
| 385 |
+
if download_thread and download_thread.is_alive():
|
| 386 |
+
return status + "\n\n⏳ Download in progress..."
|
| 387 |
+
elif is_model_ready():
|
| 388 |
+
# tree = get_directory_tree(PERSISTENT_DIR)
|
| 389 |
+
# log(f"\n{tree}")
|
| 390 |
+
return status + "\n\n✅ Models are ready."
|
| 391 |
+
return status
|
| 392 |
+
|
| 393 |
+
def cancel_download_fn():
|
| 394 |
+
"""Cancel request handler."""
|
| 395 |
+
global cancel_download
|
| 396 |
+
cancel_download = True
|
| 397 |
+
log("⛔ Download cancelled by user.")
|
| 398 |
+
return "Download cancelled."
|
| 399 |
+
|
| 400 |
# ==============================
|
| 401 |
+
# GRADIO UI ONLY (NO API ENDPOINTS)
|
| 402 |
# ==============================
|
| 403 |
+
def gradio_pose_transfer(source_image, test_pair_index):
|
| 404 |
+
test_pair_index = int(test_pair_index)
|
| 405 |
+
"""Gradio interface for pose transfer."""
|
| 406 |
+
try:
|
| 407 |
+
if not model_ready:
|
| 408 |
+
return None, "Models not ready. Please download models first."
|
| 409 |
+
|
| 410 |
+
if test_pair_index < 0 or test_pair_index >= len(test_pairs):
|
| 411 |
+
return None, f"Test pair index must be between 0 and {len(test_pairs)-1}"
|
| 412 |
+
|
| 413 |
+
# Perform pose transfer
|
| 414 |
+
output_image = pose_transfer(source_image, test_pair_index)
|
| 415 |
+
|
| 416 |
+
# Save image to in-memory bytes (PNG)
|
| 417 |
+
img_bytes = io.BytesIO()
|
| 418 |
+
output_image.save(img_bytes, format="PNG")
|
| 419 |
+
img_bytes.seek(0)
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
return output_image, img_bytes, "Pose transfer successful"
|
| 423 |
+
|
| 424 |
+
|
| 425 |
+
except Exception as e:
|
| 426 |
+
import traceback
|
| 427 |
+
tb = traceback.format_exc()
|
| 428 |
+
log(f"❌ Error during pose transfer:\n{tb}")
|
| 429 |
+
log(f"❌ the value recieved is as follow: \n{test_pair_index}")
|
| 430 |
+
return None, f"Error during pose transfer: {str(e)}"
|
| 431 |
+
|
| 432 |
+
with gr.Blocks() as demo:
|
| 433 |
+
gr.Markdown("## 🧩 Model Downloader & Pose Transfer")
|
| 434 |
+
gr.Markdown(f"**Model Source:** [{MODEL_REPO}](https://huggingface.co/{MODEL_REPO})")
|
| 435 |
+
gr.Markdown("**Required folders:** checkpoints/, pretrained_models/, fashion/")
|
| 436 |
+
|
| 437 |
+
with gr.Tab("Model Download"):
|
| 438 |
+
with gr.Row():
|
| 439 |
+
start_btn = gr.Button("📥 Download Models")
|
| 440 |
+
cancel_btn = gr.Button("❌ Cancel Download")
|
| 441 |
+
|
| 442 |
+
status_box = gr.Textbox(
|
| 443 |
+
label="Download Logs",
|
| 444 |
+
lines=25,
|
| 445 |
+
interactive=False,
|
| 446 |
+
placeholder="Click 'Download Models' to start downloading..."
|
| 447 |
+
)
|
| 448 |
+
|
| 449 |
+
# Button bindings
|
| 450 |
+
start_btn.click(fn=start_download, inputs=None, outputs=status_box)
|
| 451 |
+
cancel_btn.click(fn=cancel_download_fn, inputs=None, outputs=status_box)
|
| 452 |
|
| 453 |
+
# Periodic refresh of logs
|
| 454 |
+
demo.load(fn=get_download_status, inputs=None, outputs=status_box, every=2)
|
| 455 |
+
|
| 456 |
+
with gr.Tab("Pose Transfer"):
|
| 457 |
+
gr.Markdown("## Pose Transfer")
|
| 458 |
+
|
| 459 |
+
with gr.Row():
|
| 460 |
+
with gr.Column():
|
| 461 |
+
source_image = gr.Image(label="Source Image", type="pil")
|
| 462 |
+
test_pair_index = gr.Number(
|
| 463 |
+
label="Test Pair Index",
|
| 464 |
+
value=0,
|
| 465 |
+
minimum=0,
|
| 466 |
+
maximum=4039
|
| 467 |
+
)
|
| 468 |
+
generate_btn = gr.Button("🚀 Generate Pose Transfer")
|
| 469 |
+
|
| 470 |
+
with gr.Column():
|
| 471 |
+
output_image = gr.Image(label="Output Image", type="pil")
|
| 472 |
+
download_btn = gr.File(label="Download Output", file_types=[".png"])
|
| 473 |
+
status_message = gr.Textbox(label="Status", interactive=False)
|
| 474 |
+
|
| 475 |
+
generate_btn.click(
|
| 476 |
+
fn=gradio_pose_transfer,
|
| 477 |
+
inputs=[source_image, test_pair_index],
|
| 478 |
+
outputs=[output_image, status_message]
|
| 479 |
+
)
|
| 480 |
+
|
| 481 |
+
# ==============================
|
| 482 |
+
# START APP
|
| 483 |
+
# ==============================
|
| 484 |
+
|
| 485 |
+
|
| 486 |
+
from fastapi import FastAPI, Request
|
| 487 |
+
from fastapi.responses import JSONResponse
|
| 488 |
+
import traceback
|
| 489 |
+
|
| 490 |
+
|
| 491 |
+
def read_image_from_input(image_input: str):
|
| 492 |
+
"""
|
| 493 |
+
Accepts either:
|
| 494 |
+
- Base64 image string ("data:image/png;base64,...")
|
| 495 |
+
- Image URL ("https://...")
|
| 496 |
+
Returns: PIL.Image
|
| 497 |
+
"""
|
| 498 |
+
try:
|
| 499 |
+
if image_input.startswith("http://") or image_input.startswith("https://"):
|
| 500 |
+
response = requests.get(image_input)
|
| 501 |
+
response.raise_for_status()
|
| 502 |
+
return Image.open(io.BytesIO(response.content)).convert("RGB")
|
| 503 |
+
else:
|
| 504 |
+
# Base64 input
|
| 505 |
+
if "," in image_input:
|
| 506 |
+
image_input = image_input.split(",", 1)[1]
|
| 507 |
+
image_bytes = base64.b64decode(image_input)
|
| 508 |
+
return Image.open(io.BytesIO(image_bytes)).convert("RGB")
|
| 509 |
+
except Exception as e:
|
| 510 |
+
raise ValueError(f"Invalid image input: {str(e)}")
|
| 511 |
+
|
| 512 |
+
|
| 513 |
+
|
| 514 |
+
|
| 515 |
+
|
| 516 |
+
|
| 517 |
+
from fastapi import FastAPI, Form, UploadFile
|
| 518 |
from fastapi.responses import JSONResponse
|
| 519 |
from fastapi.middleware.cors import CORSMiddleware
|
| 520 |
from PIL import Image
|
|
|
|
| 533 |
allow_headers=["*"],
|
| 534 |
)
|
| 535 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 536 |
@app.post("/pose-transfer")
|
| 537 |
async def pose_transfer_api(
|
| 538 |
test_pair_index: int = Form(...),
|
|
|
|
| 540 |
image_base64: str = Form(None)
|
| 541 |
):
|
| 542 |
try:
|
|
|
|
|
|
|
|
|
|
| 543 |
# Get input image
|
| 544 |
if source_image:
|
| 545 |
image_bytes = await source_image.read()
|
|
|
|
| 550 |
image_bytes = base64.b64decode(image_base64)
|
| 551 |
image = Image.open(BytesIO(image_bytes)).convert("RGB")
|
| 552 |
else:
|
| 553 |
+
return JSONResponse(
|
| 554 |
+
content={"status": "error", "message": "No image provided"},
|
| 555 |
+
status_code=400
|
| 556 |
+
)
|
|
|
|
| 557 |
|
| 558 |
+
# 🔹 Call your pose transfer model
|
| 559 |
output_image = pose_transfer(image, test_pair_index)
|
| 560 |
|
| 561 |
# Convert result to base64
|
|
|
|
| 570 |
"output_image_base64": f"data:image/png;base64,{img_base64}"
|
| 571 |
}
|
| 572 |
)
|
|
|
|
|
|
|
| 573 |
except Exception as e:
|
| 574 |
import traceback
|
| 575 |
tb = traceback.format_exc()
|
| 576 |
+
return JSONResponse(
|
| 577 |
+
content={"status": "error", "message": str(e), "traceback": tb},
|
| 578 |
+
status_code=500
|
| 579 |
+
)
|
| 580 |
|
| 581 |
+
if __name__ == "__main__":
|
|
|
|
|
|
|
|
|
|
|
|
|
| 582 |
if is_model_ready():
|
|
|
|
| 583 |
model_ready = True
|
| 584 |
initialize_models()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 585 |
|
| 586 |
+
uvicorn.run(app, host="0.0.0.0", port=7860)
|
| 587 |
|
| 588 |
+
|
| 589 |
+
|
| 590 |
+
|
| 591 |
+
# if __name__ == "__main__":
|
| 592 |
+
# # Initialize models if they exist
|
| 593 |
+
# if is_model_ready():
|
| 594 |
+
# model_ready = True
|
| 595 |
+
# initialize_models()
|
| 596 |
|
| 597 |
+
# demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
|
|