Spaces:
Sleeping
Sleeping
| """ | |
| Alpeccaai Pose β Hugging Face Space (ZeroGPU) | |
| Runs DWPose / RTMPose whole-body 2D pose via rtmlib and returns keypoint JSON | |
| in the exact format RIGFORGE's "AI keypoints -> Import pose keypoints" reads. | |
| Endpoint: /detect (the RIGFORGE "Detect via HF Space" button calls this). | |
| """ | |
| import os, json, tempfile | |
| import numpy as np | |
| import cv2 | |
| import gradio as gr | |
| # ZeroGPU: CUDA is only visible INSIDE a @spaces.GPU function, so the model is | |
| # built lazily on first call (see get_model). Off ZeroGPU this is a no-op. | |
| try: | |
| import spaces | |
| gpu = spaces.GPU(duration=60) | |
| except Exception: | |
| def gpu(fn): | |
| return fn | |
| # COCO-17 body order == first 17 COCO-WholeBody points == RIGFORGE's order: | |
| # 0 nose 1 L_eye 2 R_eye 3 L_ear 4 R_ear 5 L_sho 6 R_sho 7 L_elb 8 R_elb | |
| # 9 L_wri 10 R_wri 11 L_hip 12 R_hip 13 L_knee 14 R_knee 15 L_ank 16 R_ank | |
| SKELETON = [(5,7),(7,9),(6,8),(8,10),(5,6),(11,12),(5,11),(6,12), | |
| (11,13),(13,15),(12,14),(14,16),(0,5),(0,6)] | |
| _model = None | |
| def get_model(): | |
| global _model | |
| if _model is None: | |
| import onnxruntime as ort | |
| from rtmlib import Wholebody | |
| dev = "cuda" if "CUDAExecutionProvider" in ort.get_available_providers() else "cpu" | |
| _model = Wholebody(mode="balanced", backend="onnxruntime", device=dev) | |
| return _model | |
| def _openpose18(b): | |
| """COCO-17 -> OpenPose-COCO18 flat list (neck = shoulder midpoint).""" | |
| neck = [(b[5][0]+b[6][0])/2, (b[5][1]+b[6][1])/2, min(b[5][2], b[6][2])] | |
| order = [b[0], neck, b[6], b[8], b[10], b[5], b[7], b[9], | |
| b[12], b[14], b[16], b[11], b[13], b[15], b[2], b[1], b[4], b[3]] | |
| flat = [] | |
| for x, y, s in order: | |
| flat += [float(x), float(y), float(s)] | |
| return flat | |
| def detect(image, conf=0.3): | |
| if image is None: | |
| raise gr.Error("Upload a single, isolated character figure (not a sheet).") | |
| rgb = np.array(image.convert("RGB")) | |
| bgr = rgb[:, :, ::-1].copy() | |
| h, w = bgr.shape[:2] | |
| kpts, scores = get_model()(bgr) | |
| if kpts is None or len(kpts) == 0: | |
| raise gr.Error("No person detected. Use a clean front T/A-pose crop.") | |
| p = int(np.argmax(scores.mean(axis=1))) | |
| kp, sc = kpts[p], scores[p] | |
| body = [[float(kp[i][0]), float(kp[i][1]), float(sc[i])] for i in range(17)] | |
| out = { | |
| "format": "coco17", | |
| "canvas_width": int(w), "canvas_height": int(h), | |
| "keypoints": body, | |
| "people": [{"pose_keypoints_2d": _openpose18(body)}], | |
| "model": "rtmlib.Wholebody(balanced)", | |
| } | |
| prev = rgb.copy() | |
| r = max(3, w // 200); lw = max(2, w // 300) | |
| for x, y, s in body: | |
| if s >= conf: | |
| cv2.circle(prev, (int(x), int(y)), r, (61, 240, 224), -1) | |
| for a, b in SKELETON: | |
| if body[a][2] >= conf and body[b][2] >= conf: | |
| cv2.line(prev, (int(body[a][0]), int(body[a][1])), | |
| (int(body[b][0]), int(body[b][1])), (255, 61, 127), lw) | |
| path = os.path.join(tempfile.gettempdir(), "rigpose.json") | |
| with open(path, "w") as f: | |
| json.dump(out, f, indent=2) | |
| return prev, path | |
| with gr.Blocks(title="Alpeccaai Pose") as demo: | |
| gr.Markdown( | |
| "# Alpeccaai Pose β DWPose keypoints\n" | |
| "Upload **one isolated character figure** (front T/A-pose is best β *not* a " | |
| "multi-pose reference sheet). Returns whole-body 2D keypoints as JSON for " | |
| "RIGFORGE β **AI keypoints β Import pose keypoints**, or call `/detect` from " | |
| "the in-tool **Detect via HF Space** button." | |
| ) | |
| with gr.Row(): | |
| inp = gr.Image(type="pil", label="Single character figure") | |
| with gr.Column(): | |
| conf = gr.Slider(0.0, 1.0, value=0.3, label="Keypoint confidence threshold") | |
| btn = gr.Button("Detect", variant="primary") | |
| with gr.Row(): | |
| out_img = gr.Image(label="Detected skeleton") | |
| out_file = gr.File(label="rigpose.json") | |
| btn.click(detect, inputs=[inp, conf], outputs=[out_img, out_file], api_name="detect") | |
| if __name__ == "__main__": | |
| demo.launch() | |