detrpose / app.py
multimodalart's picture
multimodalart HF Staff
Upload app.py with huggingface_hub
a2bc821 verified
Raw
History Blame Contribute Delete
3.58 kB
import spaces # MUST come before torch / any CUDA-touching import
import torch
import torchvision.transforms as T
import gradio as gr
import numpy as np
import cv2
from PIL import Image
from copy import deepcopy
from detrpose import DETR
# Load the model at module scope, .to("cuda") eagerly.
model = DETR(model="detrpose_hgnetv2_l", device="cuda")
transforms = T.Compose(
[
T.Resize((640, 640)),
T.ToTensor(),
]
)
@spaces.GPU(duration=30)
def predict(image: "Image.Image", threshold: float = 0.5) -> "Image.Image":
"""Detect multi-person poses in an image using DETRPose-L.
Args:
image: Input PIL image.
threshold: Confidence threshold for keeping detected poses.
"""
if image is None:
return None
im_pil = image.convert("RGB")
w, h = im_pil.size
orig_size = torch.tensor([[w, h]]).to("cuda")
im_data = transforms(im_pil).unsqueeze(0).to("cuda")
with torch.no_grad():
outputs = model.model.model(im_data)
results = model.model.postprocessor(outputs, orig_size)
scores, labels, keypoints = results
scores = scores[0].detach().cpu().numpy()
keypoints = keypoints[0].detach().cpu().numpy()
idx = scores > threshold
valid_keypoints = keypoints[idx]
im_cv2 = cv2.cvtColor(np.array(im_pil), cv2.COLOR_RGB2BGR)
model.annotator.draw_on(im_cv2, valid_keypoints)
result_rgb = cv2.cvtColor(im_cv2, cv2.COLOR_BGR2RGB)
return Image.fromarray(result_rgb)
CSS = """
#col-container { max-width: 1100px; margin: 0 auto; }
.dark .gradio-container { color: var(--body-text-color); }
"""
with gr.Blocks() as demo:
with gr.Column(elem_id="col-container"):
gr.Markdown(
"# DETRPose: Real-Time Multi-Person Pose Estimation\n"
"Upload an image to detect human poses with skeleton keypoints overlaid. "
"Powered by [DETRPose-L](https://huggingface.co/SebasJanampa/DETRPose_L_COCO) — "
"the first real-time end-to-end transformer for multi-person pose estimation."
)
with gr.Row():
with gr.Column(scale=1):
input_image = gr.Image(
type="pil", label="Input Image", sources=["upload", "clipboard"]
)
threshold_slider = gr.Slider(
minimum=0.1,
maximum=0.9,
value=0.5,
step=0.05,
label="Confidence Threshold",
)
run_btn = gr.Button("Run", variant="primary")
with gr.Column(scale=1):
output_image = gr.Image(
type="pil", label="Pose Estimation Result"
)
with gr.Accordion("Advanced settings", open=False):
gr.Markdown(
"**Confidence Threshold**: Lower this to detect more poses (may include "
"false positives). Raise it for stricter, more confident detections."
)
gr.Examples(
examples=[
["example1.jpg", 0.5],
["example2.jpg", 0.5],
],
inputs=[input_image, threshold_slider],
outputs=output_image,
fn=predict,
cache_examples=True,
cache_mode="lazy",
)
run_btn.click(
fn=predict,
inputs=[input_image, threshold_slider],
outputs=output_image,
api_name="predict",
)
if __name__ == "__main__":
demo.launch(mcp_server=True, theme=gr.themes.Citrus(), css=CSS)