File size: 4,575 Bytes
39091be
 
 
 
 
 
 
 
6c87dd5
39091be
 
 
6c87dd5
 
 
 
 
 
 
 
 
39091be
 
 
 
6c87dd5
39091be
 
 
 
 
 
 
6c87dd5
39091be
6c87dd5
39091be
 
6c87dd5
39091be
6c87dd5
 
 
 
 
39091be
 
 
 
3e4f568
6c87dd5
39091be
6c87dd5
 
 
 
 
 
 
39091be
6c87dd5
 
 
39091be
 
6c87dd5
39091be
6c87dd5
 
 
 
 
 
 
 
 
 
 
 
39091be
 
6c87dd5
 
 
 
 
 
 
 
39091be
 
 
6c87dd5
39091be
6c87dd5
39091be
6c87dd5
 
 
 
 
 
 
39091be
6c87dd5
 
 
 
39091be
6c87dd5
39091be
 
 
 
6c87dd5
3e4f568
3fc090d
39091be
e5ff3b3
39091be
 
 
 
6c87dd5
 
39091be
6c87dd5
 
39091be
6c87dd5
39091be
 
 
 
 
 
 
b86810b
6c87dd5
39091be
 
 
 
 
 
 
 
6c87dd5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import gradio as gr
from controlnet_aux import OpenposeDetector
import os
import cv2
import numpy as np
from PIL import Image
from moviepy.editor import *

# Load the OpenPose detector
openpose = OpenposeDetector.from_pretrained('lllyasviel/ControlNet')

def get_frames(video_in):
    """Extract frames from a video and resize to height 512px.
    
    Args:
        video_in: Path to the input video file.
        
    Returns:
        frames: List of paths to extracted frame images.
        fps: Frames per second of the original video.
    """
    frames = []
    clip = VideoFileClip(video_in)
    
    if clip.fps > 30:
        print("video rate is over 30, resetting to 30")
        clip_resized = clip.resize(height=512)
        clip_resized.write_videofile("video_resized.mp4", fps=30)
    else:
        print("video rate is OK")
        clip_resized = clip.resize(height=512)
        clip_resized.write_videofile("video_resized.mp4", fps=clip.fps)
    
    cap = cv2.VideoCapture("video_resized.mp4")
    fps = cap.get(cv2.CAP_PROP_FPS)
    i = 0
    while(cap.isOpened()):
        ret, frame = cap.read()
        if not ret:
            break
        frame_path = f'frame_{i}.jpg'
        cv2.imwrite(frame_path, frame)
        frames.append(frame_path)
        i += 1

    cap.release()
    cv2.destroyAllWindows()
    return frames, fps

def get_openpose_filter(i):
    """Apply OpenPose filter to a single image frame.
    
    Args:
        i: Path to the image frame.
        
    Returns:
        output_path: Path to the OpenPose-processed image.
    """
    image = Image.open(i)
    image = openpose(image)
    output_path = f"openpose_frame_{os.path.basename(i)}.jpeg"
    image.save(output_path)
    return output_path

def create_video(frames, fps, type):
    """Create a video from a sequence of image frames.
    
    Args:
        frames: List of image frame paths.
        fps: Frames per second for the output video.
        type: A string used as the prefix for naming the result video.
        
    Returns:
        video_path: Path to the resulting video file.
    """
    clip = ImageSequenceClip(frames, fps=fps)
    video_path = f"{type}_result.mp4"
    clip.write_videofile(video_path, fps=fps)
    return video_path

def convertG2V(imported_gif):
    """Convert a GIF file to a standard MP4 video.
    
    Args:
        imported_gif: The input GIF file object.
        
    Returns:
        Path to the converted MP4 video file.
    """
    clip = VideoFileClip(imported_gif.name)
    clip.write_videofile("my_gif_video.mp4")
    return "my_gif_video.mp4"

def infer(video_in):
    """Generate an OpenPose-filtered video from an input video.
    
    This function performs the following steps:
    1. Extracts frames from the input video and retrieves the original frame rate (FPS).
    2. Applies the OpenPose model to each frame to extract pose data.
    3. Reconstructs a new video from the OpenPose-processed frames using the original FPS.

    Args:
        video_in: The uploaded input video file (MP4 or converted GIF).
    
    Returns:
        final_vid: The path to the OpenPose-filtered output video.
        files: A list containing the output video file (for download).
    """
    break_vid = get_frames(video_in)
    frames_list = break_vid[0]
    fps = break_vid[1]
    n_frame = len(frames_list)
    
    result_frames = []
    for i in frames_list[:n_frame]:
        openpose_frame = get_openpose_filter(i)
        result_frames.append(openpose_frame)

    final_vid = create_video(result_frames, fps, "openpose")
    files = [final_vid]

    return final_vid, files

# UI layout
title = """
<div style="text-align: center; max-width: 500px; margin: 0 auto;">
    <div style="display: inline-flex; align-items: center; gap: 0.8rem; font-size: 1.75rem; margin-bottom: 10px;">
        <h1 style="font-weight: 600; margin-bottom: 7px;">Video to OpenPose</h1>
    </div>
</div>
"""

with gr.Blocks() as demo:
    with gr.Column():
        gr.HTML(title)
        with gr.Row():
            with gr.Column():
                video_input = gr.Video(sources=["upload"])
                gif_input = gr.File(label="Import a GIF instead", file_types=['.gif'])
                gif_input.change(fn=convertG2V, inputs=gif_input, outputs=video_input)
                submit_btn = gr.Button("Submit")
            with gr.Column():
                video_output = gr.Video()
                file_output = gr.Files()

    submit_btn.click(fn=infer, inputs=[video_input], outputs=[video_output, file_output])

demo.launch(mcp_server=True)