| """ |
| OpenPose Preprocessor for ControlNet |
| A simple Gradio application for pose detection. |
| """ |
|
|
| import gradio as gr |
| import numpy as np |
| from PIL import Image |
| import torch |
|
|
| |
| DEVICE = "cuda" if torch.cuda.is_available() else "cpu" |
| print(f"Using device: {DEVICE}") |
|
|
| |
| _openpose_detector = None |
| _dwpose_detector = None |
|
|
|
|
| def get_openpose_detector(): |
| """Get or create OpenPose detector.""" |
| global _openpose_detector |
| if _openpose_detector is None: |
| from controlnet_aux import OpenposeDetector |
| _openpose_detector = OpenposeDetector.from_pretrained("lllyasviel/Annotators") |
| return _openpose_detector |
|
|
|
|
| def get_dwpose_detector(): |
| """Get or create DWPose detector using easy-dwpose.""" |
| global _dwpose_detector |
| if _dwpose_detector is None: |
| from easy_dwpose import DWposeDetector |
| _dwpose_detector = DWposeDetector(device=DEVICE) |
| return _dwpose_detector |
|
|
|
|
| def detect_pose(image, model_type, detect_hand, detect_face, detect_resolution): |
| """Main pose detection function.""" |
| if image is None: |
| return None |
| |
| try: |
| |
| if isinstance(image, np.ndarray): |
| image = Image.fromarray(image) |
| |
| |
| if image.mode != "RGB": |
| image = image.convert("RGB") |
| |
| |
| original_size = image.size |
| ratio = detect_resolution / max(original_size) |
| new_size = (int(original_size[0] * ratio), int(original_size[1] * ratio)) |
| image_resized = image.resize(new_size, Image.Resampling.LANCZOS) |
| |
| |
| if model_type == "DWPose": |
| detector = get_dwpose_detector() |
| result = detector( |
| image_resized, |
| output_type="pil", |
| include_hands=detect_hand, |
| include_face=detect_face |
| ) |
| elif model_type == "OpenPose (Full)": |
| detector = get_openpose_detector() |
| result = detector( |
| image_resized, |
| hand_and_face=True, |
| output_type="pil" |
| ) |
| elif model_type == "OpenPose (Face Only)": |
| detector = get_openpose_detector() |
| result = detector( |
| image_resized, |
| include_body=False, |
| include_hand=False, |
| include_face=True, |
| output_type="pil" |
| ) |
| elif model_type == "OpenPose (Hand)": |
| detector = get_openpose_detector() |
| result = detector( |
| image_resized, |
| include_body=True, |
| include_hand=True, |
| include_face=False, |
| output_type="pil" |
| ) |
| else: |
| |
| detector = get_openpose_detector() |
| result = detector( |
| image_resized, |
| hand_and_face=detect_hand and detect_face, |
| output_type="pil" |
| ) |
| |
| |
| if result is not None and hasattr(result, 'size') and result.size != original_size: |
| result = result.resize(original_size, Image.Resampling.LANCZOS) |
| |
| return result |
| |
| except Exception as e: |
| print(f"Error during processing: {str(e)}") |
| import traceback |
| traceback.print_exc() |
| return None |
|
|
|
|
| |
| with gr.Blocks( |
| title="𦴠OpenPose Preprocessor", |
| theme=gr.themes.Soft() |
| ) as demo: |
| |
| gr.Markdown( |
| """ |
| # 𦴠OpenPose Preprocessor for ControlNet |
| |
| High-quality pose detection with multiple models. Upload an image and get pose skeleton for ControlNet. |
| """ |
| ) |
| |
| gr.Markdown(f"**Device**: `{DEVICE}` {'π' if DEVICE == 'cuda' else 'π’'}") |
| |
| with gr.Row(): |
| with gr.Column(scale=1): |
| input_image = gr.Image(label="π· Input Image", type="pil", height=400) |
| |
| model_type = gr.Dropdown( |
| label="π€ Model", |
| choices=["DWPose", "OpenPose", "OpenPose (Full)", "OpenPose (Face Only)", "OpenPose (Hand)"], |
| value="DWPose", |
| info="DWPose is recommended for best accuracy" |
| ) |
| |
| with gr.Row(): |
| detect_hand = gr.Checkbox(label="π Detect Hands", value=True) |
| detect_face = gr.Checkbox(label="π Detect Face", value=True) |
| |
| detect_resolution = gr.Slider( |
| label="π Detection Resolution", |
| minimum=256, |
| maximum=2048, |
| value=512, |
| step=64, |
| info="Higher = more accurate but slower" |
| ) |
| |
| process_btn = gr.Button("π Detect Pose", variant="primary", size="lg") |
| |
| with gr.Column(scale=1): |
| output_image = gr.Image(label="π¨ Output Pose", type="pil", height=400) |
| |
| gr.Markdown( |
| """ |
| ### π Tips |
| - **DWPose** is recommended for best accuracy, especially for hands and complex poses |
| - **OpenPose (Full)** detects body, face, and hands together |
| - Higher **Detection Resolution** improves accuracy but increases processing time |
| - The output image can be directly used with ControlNet OpenPose models |
| |
| ### βοΈ Options |
| - **Detect Hands/Face** checkboxes work with DWPose and basic OpenPose modes |
| - For preset modes like "OpenPose (Full)", these options are ignored |
| """ |
| ) |
| |
| process_btn.click( |
| fn=detect_pose, |
| inputs=[input_image, model_type, detect_hand, detect_face, detect_resolution], |
| outputs=[output_image] |
| ) |
|
|
|
|
| if __name__ == "__main__": |
| demo.launch( |
| server_name="0.0.0.0", |
| server_port=7860 |
| ) |
|
|