Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,42 +1,203 @@
|
|
1 |
import os
|
2 |
-
|
3 |
-
import
|
4 |
-
os.system("pip install 'git+https://github.com/facebookresearch/detectron2.git'")
|
5 |
-
os.system("git clone https://github.com/ShuhongChen/bizarre-pose-estimator.git")
|
6 |
-
os.chdir("bizarre-pose-estimator")
|
7 |
|
8 |
-
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
-
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
|
13 |
-
|
14 |
-
|
|
|
|
|
|
|
|
|
|
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
-
def inference(img):
|
20 |
-
os.system("python3 -m _scripts.pose_estimator "+img+" ./_train/character_pose_estim/runs/feat_concat+data.ckpt")
|
21 |
|
22 |
-
return "./_samples/character_pose_estim.png"
|
23 |
-
|
24 |
-
|
25 |
title = "bizarre-pose-estimator"
|
26 |
description = "Gradio demo for Transfer Learning for Pose Estimation of Illustrated Characters. To use it, simply upload your image, or click one of the examples to load them. Read more at the links below."
|
27 |
-
|
28 |
article = "<p style='text-align: center'><a href='https://arxiv.org/abs/2108.01819' target='_blank'>Transfer Learning for Pose Estimation of Illustrated Characters</a> | <a href='https://github.com/ShuhongChen/bizarre-pose-estimator' target='_blank'>Github Repo</a></p>"
|
29 |
|
30 |
-
|
|
|
|
|
31 |
gr.Interface(
|
32 |
-
inference,
|
33 |
-
|
34 |
-
gr.
|
|
|
35 |
title=title,
|
36 |
description=description,
|
37 |
article=article,
|
38 |
-
allow_flagging="never",
|
39 |
-
examples=
|
40 |
-
enable_queue=True
|
41 |
-
|
42 |
-
|
|
|
1 |
import os
|
2 |
+
import subprocess # Using subprocess for better command execution
|
3 |
+
import time # For potential retries or delays if needed
|
|
|
|
|
|
|
4 |
|
5 |
+
# --- Dependency Installation ---
|
6 |
+
# Note: Ideally, manage dependencies via requirements.txt for HF Spaces build process.
|
7 |
+
# Running pip here might be slow on startup or cause unexpected version conflicts.
|
8 |
+
print("Ensuring dependencies are installed...")
|
9 |
+
# os.system("pip install gradio==2.4.6") # Prefer version from requirements.txt
|
10 |
+
# os.system("pip install 'git+https://github.com/facebookresearch/detectron2.git'") # Prefer from requirements.txt
|
11 |
|
12 |
+
import gradio as gr # Import after potential install
|
13 |
|
14 |
+
# --- Repository Setup ---
|
15 |
+
repo_dir = "bizarre-pose-estimator"
|
16 |
+
if not os.path.exists(repo_dir):
|
17 |
+
print(f"Cloning repository '{repo_dir}'...")
|
18 |
+
clone_command = "git clone https://github.com/ShuhongChen/bizarre-pose-estimator.git"
|
19 |
+
try:
|
20 |
+
subprocess.run(clone_command, shell=True, check=True, capture_output=True, text=True)
|
21 |
+
print("Repository cloned successfully.")
|
22 |
+
except subprocess.CalledProcessError as e:
|
23 |
+
print(f"ERROR: Failed to clone repository: {e.stderr}")
|
24 |
+
# Consider exiting if clone fails
|
25 |
+
exit()
|
26 |
+
else:
|
27 |
+
print(f"Repository '{repo_dir}' already exists.")
|
28 |
|
29 |
+
# --- Change Directory ---
|
30 |
+
try:
|
31 |
+
os.chdir(repo_dir)
|
32 |
+
print(f"Changed directory to: {os.getcwd()}")
|
33 |
+
except FileNotFoundError:
|
34 |
+
print(f"ERROR: Failed to change directory to '{repo_dir}'.")
|
35 |
+
exit() # Cannot continue without the repo code
|
36 |
|
37 |
+
# --- Download Example Image ---
|
38 |
+
example_img_url = "https://i.imgur.com/IkJzlaE.jpeg"
|
39 |
+
example_img_file = "IkJzlaE.jpeg"
|
40 |
+
if not os.path.exists(example_img_file):
|
41 |
+
print(f"Downloading example image: {example_img_file}")
|
42 |
+
try:
|
43 |
+
subprocess.run(["curl", "-fL", example_img_url, "-o", example_img_file], check=True)
|
44 |
+
print("Example image downloaded.")
|
45 |
+
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
46 |
+
print(f"Warning: Failed to download example image {example_img_url}. Error: {e}")
|
47 |
|
48 |
+
# --- Model Download ---
|
49 |
+
model_zip_file = "bizarre_pose_models.zip"
|
50 |
+
model_extract_dir = "bizarre_pose_models" # Expected folder name inside zip
|
51 |
+
model_id = "17N5PutpYJTlKuNB6bdDaiQsPSIkYtiPm" # The correct FILE ID
|
52 |
+
download_successful = False
|
53 |
+
|
54 |
+
# Check if model files already exist (e.g., from previous run/unzip)
|
55 |
+
# Check for a key file/folder that should exist after copy
|
56 |
+
# Using the checkpoint file as an indicator
|
57 |
+
model_checkpoint_rel_path = "_train/character_pose_estim/runs/feat_concat+data.ckpt"
|
58 |
+
if os.path.exists(model_checkpoint_rel_path):
|
59 |
+
print("Model checkpoint already exists. Skipping download and unzip.")
|
60 |
+
download_successful = True # Treat as success for logic flow
|
61 |
+
models_ready = True
|
62 |
+
else:
|
63 |
+
print(f"Model checkpoint not found at '{model_checkpoint_rel_path}'. Attempting download...")
|
64 |
+
models_ready = False
|
65 |
+
if os.path.exists(model_zip_file):
|
66 |
+
print(f"Zip file '{model_zip_file}' already exists. Skipping download.")
|
67 |
+
download_successful = True
|
68 |
+
else:
|
69 |
+
print(f"Attempting to download model weights using gdown (ID: {model_id})...")
|
70 |
+
gdown_command = f"gdown --id {model_id} -O {model_zip_file}"
|
71 |
+
print(f"Executing: {gdown_command}")
|
72 |
+
try:
|
73 |
+
result = subprocess.run(gdown_command, shell=True, check=True, capture_output=True, text=True)
|
74 |
+
print("Gdown download successful.")
|
75 |
+
# print("stdout:", result.stdout) # Often too verbose
|
76 |
+
# print("stderr:", result.stderr)
|
77 |
+
download_successful = True
|
78 |
+
except FileNotFoundError:
|
79 |
+
print("ERROR: 'gdown' command not found. Install via requirements.txt.")
|
80 |
+
except subprocess.CalledProcessError as e:
|
81 |
+
print(f"ERROR: gdown download failed with exit code {e.returncode}")
|
82 |
+
print("Stderr:", e.stderr)
|
83 |
+
print("Stdout:", e.stdout) # May contain useful info from gdown
|
84 |
+
print("Download might fail due to quotas or permissions on Google Drive.")
|
85 |
+
print("Consider manually uploading 'bizarre_pose_models.zip' to the Space root if errors persist.")
|
86 |
+
|
87 |
+
# --- Unzip and Copy ---
|
88 |
+
if download_successful and os.path.exists(model_zip_file):
|
89 |
+
print(f"Unzipping '{model_zip_file}'...")
|
90 |
+
try:
|
91 |
+
if os.path.exists(model_extract_dir): print(f"Note: '{model_extract_dir}' already exists. Overwriting.")
|
92 |
+
subprocess.run(["unzip", "-oq", model_zip_file], check=True) # -o overwrite, -q quiet
|
93 |
+
print("Unzip successful.")
|
94 |
+
|
95 |
+
print("Copying model files...")
|
96 |
+
source_dir_unzip = f"./{model_extract_dir}/"
|
97 |
+
dest_dir = "."
|
98 |
+
if os.path.exists(source_dir_unzip):
|
99 |
+
os.system(f"cp -a {source_dir_unzip}. {dest_dir}") # Use os.system like original
|
100 |
+
print("Model files copied.")
|
101 |
+
models_ready = True # Models should now be ready
|
102 |
+
|
103 |
+
# --- Delete Zip File ---
|
104 |
+
print(f"Attempting to remove zip file to save space: {model_zip_file}")
|
105 |
+
try:
|
106 |
+
os.remove(model_zip_file)
|
107 |
+
print(f"Removed zip file: {model_zip_file}")
|
108 |
+
except OSError as e:
|
109 |
+
print(f"Warning: Error removing zip file {model_zip_file}: {e}")
|
110 |
+
# --- End Zip Deletion ---
|
111 |
+
|
112 |
+
else:
|
113 |
+
print(f"ERROR: Directory '{source_dir_unzip}' not found after unzip.")
|
114 |
+
|
115 |
+
except FileNotFoundError: print(f"ERROR: 'unzip' command not available.")
|
116 |
+
except subprocess.CalledProcessError as e: print(f"ERROR: Unzip failed: {e}")
|
117 |
+
else:
|
118 |
+
if not download_successful: print("Download failed previously, cannot unzip.")
|
119 |
+
elif not os.path.exists(model_zip_file): print(f"Zip file '{model_zip_file}' not found, cannot unzip.")
|
120 |
+
|
121 |
+
# --- Final Check and LS ---
|
122 |
+
print("\nCurrent directory contents:")
|
123 |
+
os.system("ls -la")
|
124 |
+
if not models_ready:
|
125 |
+
print("\n\nERROR: MODEL FILES ARE NOT SET UP CORRECTLY. APP MAY NOT WORK.\n\n")
|
126 |
+
|
127 |
+
# --- Gradio Interface ---
|
128 |
+
def inference(img_input):
|
129 |
+
# Gradio passes a PIL Image or Numpy array depending on config, need filepath
|
130 |
+
# Save the uploaded image temporarily if it's not already a path
|
131 |
+
if isinstance(img_input, str):
|
132 |
+
img_path = img_input # Already a path (e.g., from examples)
|
133 |
+
else:
|
134 |
+
# Save PIL/Numpy input to a temporary file
|
135 |
+
from PIL import Image
|
136 |
+
import numpy as np
|
137 |
+
if isinstance(img_input, np.ndarray):
|
138 |
+
img_pil = Image.fromarray(img_input)
|
139 |
+
else: # Assume PIL Image
|
140 |
+
img_pil = img_input
|
141 |
+
temp_img_name = "temp_gradio_input.png"
|
142 |
+
img_pil.save(temp_img_name)
|
143 |
+
img_path = temp_img_name
|
144 |
+
print(f"Saved Gradio input to temporary file: {img_path}")
|
145 |
+
|
146 |
+
print(f"Running inference on: {img_path}")
|
147 |
+
output_sample_path = "./_samples/character_pose_estim.png"
|
148 |
+
model_checkpoint = "./_train/character_pose_estim/runs/feat_concat+data.ckpt"
|
149 |
+
|
150 |
+
# Check paths relative to current directory ('bizarre-pose-estimator')
|
151 |
+
if not os.path.exists(img_path):
|
152 |
+
print(f"ERROR: Input image path does not exist: {img_path}"); return None
|
153 |
+
if not os.path.exists(model_checkpoint):
|
154 |
+
print(f"ERROR: Model checkpoint not found at: {model_checkpoint}"); return None
|
155 |
+
|
156 |
+
command = f"python3 -m _scripts.pose_estimator '{img_path}' '{model_checkpoint}'" # Add quotes for paths
|
157 |
+
print(f"Executing command: {command}")
|
158 |
+
try:
|
159 |
+
result = subprocess.run(command, shell=True, check=True, capture_output=True, text=True, timeout=120) # Add timeout
|
160 |
+
print("Inference stdout:", result.stdout)
|
161 |
+
print("Inference stderr:", result.stderr)
|
162 |
+
print("Inference completed.")
|
163 |
+
if os.path.exists(output_sample_path):
|
164 |
+
return output_sample_path # Return path to the output image
|
165 |
+
else:
|
166 |
+
print(f"ERROR: Inference ran but output file not found: {output_sample_path}")
|
167 |
+
return None
|
168 |
+
except subprocess.TimeoutExpired:
|
169 |
+
print("ERROR: Inference script timed out.")
|
170 |
+
return None
|
171 |
+
except subprocess.CalledProcessError as e:
|
172 |
+
print(f"ERROR: Inference script failed: {e.returncode}\nStderr:{e.stderr}\nStdout:{e.stdout}")
|
173 |
+
return None
|
174 |
+
finally:
|
175 |
+
# Clean up temporary input file if created
|
176 |
+
if not isinstance(img_input, str) and os.path.exists(temp_img_name):
|
177 |
+
try:
|
178 |
+
os.remove(temp_img_name)
|
179 |
+
print(f"Removed temporary file: {temp_img_name}")
|
180 |
+
except OSError as e:
|
181 |
+
print(f"Warning: Failed to remove temp file {temp_img_name}: {e}")
|
182 |
|
|
|
|
|
183 |
|
|
|
|
|
|
|
184 |
title = "bizarre-pose-estimator"
|
185 |
description = "Gradio demo for Transfer Learning for Pose Estimation of Illustrated Characters. To use it, simply upload your image, or click one of the examples to load them. Read more at the links below."
|
|
|
186 |
article = "<p style='text-align: center'><a href='https://arxiv.org/abs/2108.01819' target='_blank'>Transfer Learning for Pose Estimation of Illustrated Characters</a> | <a href='https://github.com/ShuhongChen/bizarre-pose-estimator' target='_blank'>Github Repo</a></p>"
|
187 |
|
188 |
+
# Ensure example file exists before adding it
|
189 |
+
examples_list = [[example_img_file]] if os.path.exists(example_img_file) else []
|
190 |
+
|
191 |
gr.Interface(
|
192 |
+
fn=inference, # Use fn= alias
|
193 |
+
# Input needs to accept various types, filepath ensures it works with examples
|
194 |
+
inputs=gr.Image(type="pil", label="Input"), # Use PIL input type, save internally
|
195 |
+
outputs=gr.Image(type="filepath", label="Output"), # Output is path to generated file
|
196 |
title=title,
|
197 |
description=description,
|
198 |
article=article,
|
199 |
+
allow_flagging="never", # Original setting
|
200 |
+
examples=examples_list,
|
201 |
+
enable_queue=True # Original setting
|
202 |
+
# Consider adding cache_examples=True if examples are static
|
203 |
+
).launch() # share=True is needed only if not running on HF platform
|