File size: 4,182 Bytes
f43c9b7
aff3e71
 
 
f43c9b7
 
 
aff3e71
f43c9b7
 
 
 
 
 
 
 
 
 
 
aff3e71
 
b601d4d
9bb97f4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b601d4d
0acdc60
9bb97f4
 
 
b601d4d
 
 
 
 
 
 
 
 
 
 
 
 
9bb97f4
b601d4d
9bb97f4
0acdc60
b601d4d
9bb97f4
0acdc60
9bb97f4
 
aff3e71
 
9bb97f4
 
 
ac3c226
 
 
e4cfea2
 
ac3c226
aff3e71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f43c9b7
 
 
aff3e71
 
f43c9b7
 
 
c01aad0
 
 
f43c9b7
 
c01aad0
f43c9b7
c01aad0
f43c9b7
c01aad0
f43c9b7
c01aad0
f43c9b7
 
 
be3490d
f43c9b7
 
 
 
483d460
f43c9b7
 
c6678f9
f43c9b7
c6678f9
2e55dd7
f43c9b7
 
 
c01aad0
 
 
c6678f9
c01aad0
f43c9b7
c01aad0
1847121
aff3e71
 
f43c9b7
 
 
 
 
 
 
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
150
151
152
153
154
155
156
157
158
import os
import shutil
import subprocess
import textwrap
from pathlib import Path

import gradio as gr
import torch
from huggingface_hub import hf_hub_download

REPO_ID = "kbrodt/sketch2pose"
API_TOKEN = os.environ["sketch2pose"]
ASSET_DIR = Path("./assets")
SAVE_DIR = "output"
CMD = textwrap.dedent("""
    python src/pose.py
        --save-path {}
        --img-path {}
""")
TITLE = "Sketch2Pose: Estimating a 3D Character Pose from a Bitmap Sketch"
DESCRIPTION = '''
<style>
figure {
    margin: 0;
    font-size: smaller;
    text-align: justify;
}
img {
    width: auto;
    max-width: 100%;
    height: auto;
}
video {
    width: 720;
    max-width: 100%;
    height: 405;
}
ul.horizontal {
    padding: 0;
}
ul.horizontal li {
    padding: 0 1em 0 0;
    display: inline-block;
}
table td {
    vertical-align: top;
}
</style>

<table>
<tr>
<td>
<figure>
<img src="http://www-labs.iro.umontreal.ca/~bmpix/sketch2pose/teaser.png" alt="sketch2pose">
<figcaption>
Given a single natural <b>bitmap</b> sketch of a character (a), our
learning-based approach allows to automatically, with no additional input,
recover the 3D pose consistent with the viewer expectation (b). This pose can
be then automatically copied a custom rigged and skinned 3D character (c) using
standard retargeting tools (d). Input image &copy;&nbsp;Olga Posukh.
</figcaption>
</figure>

<p>
<ul class="horizontal">
<li><a href="http://www-labs.iro.umontreal.ca/~bmpix/sketch2pose/">[project page]</a></li>
<li><a href="https://dl.acm.org/doi/10.1145/3528223.3530106">[paper acm siggraph 2022]</a></li>
<li><a href="https://github.com/kbrodt/sketch2pose">[code.git]</a></li>
</ul>
</p>
</td>

<td>
<video width="720" height="405" controls autoplay muted loop>
<source src="http://www-labs.iro.umontreal.ca/~bmpix/sketch2pose/sketch2pose.webm" type="video/mp4">
</video>
</td>
</tr>
<table>

<p>
Note: it takes about 30 seconds to infer 3D pose on Hugginface Spaces without
self-contacts and 2.5 minutes with self-contacts (uncheck it if the input character
sketch does not have self-contacts).
</p>
'''


def prepare():
    filename = "models_smplx_v1_1.zip"
    smpl_path = hf_hub_download(
        repo_id=REPO_ID,
        repo_type="model",
        filename=filename,
        use_auth_token=API_TOKEN,
        cache_dir=ASSET_DIR,
    )
    if not (ASSET_DIR / filename).is_file():
        shutil.copy(smpl_path, ASSET_DIR)
    
    subprocess.run("bash ./scripts/download.sh".split())
    subprocess.run("bash ./scripts/prepare.sh".split())


def main():
    prepare()

    save_dir = Path(SAVE_DIR)
    save_dir.mkdir(parents=True, exist_ok=True)

    def pose(img_path, use_cos=True, use_angle_transf=True, use_contacts=False, use_natural=True):
        if use_cos == False:
            use_angle_transf = False

        cmd = CMD.format(save_dir, img_path)
        if use_cos:
            cmd = cmd + " --use-cos"
        if use_angle_transf:
            cmd = cmd + " --use-angle-transf"
        if use_contacts:
            cmd = cmd + " --use-contacts"
        if use_natural:
            cmd = cmd + " --use-natural"

        out_dir = (save_dir / Path(img_path).name).with_suffix("")
        mesh_path = out_dir / "us.glb"

        if not mesh_path.is_file():
            subprocess.call(cmd.split())

        return str(mesh_path)

    examples = []
    use_contacts = torch.cuda.is_available()
    for img_path in Path("./data/images").glob("*"):
        examples.append([str(img_path), True, True, use_contacts, True])

    demo = gr.Interface(
        fn=pose,
        inputs=[
            gr.Image(type="filepath", label="Image"),
            gr.Checkbox(value=True, label="Bone lenghts"),
            gr.Checkbox(value=True, label="Foreshortening"),
            gr.Checkbox(value=use_contacts, label="Self-contacts", interactive=use_contacts),
            gr.Checkbox(value=True, label="Pose naturalness"),
        ],
        outputs=gr.Model3D(clear_color=[0.0, 0.0, 0.0, 0.0], label="SMPL 3D pose"),
        examples=examples[:1],  # 5] + examples[6:6 + 4],        
        title=TITLE,
        description=DESCRIPTION,
    )

    demo.launch()


if __name__ == "__main__":
    main()