Spaces:
Running
Running
update
Browse files
app.py
CHANGED
@@ -1,13 +1,21 @@
|
|
1 |
import os
|
2 |
import sys
|
3 |
import subprocess
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
|
5 |
# Đảm bảo cài đặt các thư viện cần thiết trước khi import
|
6 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "scikit-learn"])
|
7 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "scikit-image==0.19.3"])
|
8 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "face-alignment==1.3.5"])
|
9 |
-
subprocess.check_call([sys.executable, "-m", "pip", "install", "ffmpeg-python"])
|
10 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "PyYAML==5.3.1"])
|
|
|
11 |
|
12 |
# Cài đặt ffmpeg trong môi trường Ubuntu
|
13 |
os.system("apt-get update && apt-get install -y ffmpeg")
|
@@ -15,24 +23,13 @@ os.system("apt-get update && apt-get install -y ffmpeg")
|
|
15 |
# Clone repo nếu chưa có
|
16 |
if not os.path.exists('first_order_model'):
|
17 |
subprocess.call(['git', 'clone', 'https://github.com/AliaksandrSiarohin/first-order-model.git'])
|
18 |
-
os.
|
|
|
19 |
|
20 |
# Thêm đường dẫn vào PYTHONPATH
|
21 |
sys.path.append('.')
|
22 |
sys.path.append('first_order_model')
|
23 |
|
24 |
-
# Sửa code để truy cập trực tiếp vào các hàm cần thiết
|
25 |
-
# Tạo một bản sao của demo.py mà không phụ thuộc vào ffmpeg thư viện Python
|
26 |
-
with open('first_order_model/demo.py', 'r') as f:
|
27 |
-
demo_code = f.read()
|
28 |
-
|
29 |
-
# Thay thế dòng import ffmpeg
|
30 |
-
demo_code = demo_code.replace('import ffmpeg', '# import ffmpeg')
|
31 |
-
|
32 |
-
# Viết lại demo.py đã sửa
|
33 |
-
with open('first_order_model/demo_fixed.py', 'w') as f:
|
34 |
-
f.write(demo_code)
|
35 |
-
|
36 |
# Tạo file helper với hàm load_checkpoints
|
37 |
with open('load_helper.py', 'w') as f:
|
38 |
f.write("""
|
@@ -43,7 +40,7 @@ from first_order_model.modules.keypoint_detector import KPDetector
|
|
43 |
|
44 |
def load_checkpoints(config_path, checkpoint_path, device='cpu'):
|
45 |
with open(config_path) as f:
|
46 |
-
config = yaml.
|
47 |
|
48 |
generator = OcclusionAwareGenerator(**config['model_params']['generator_params'],
|
49 |
**config['model_params']['common_params'])
|
@@ -93,15 +90,6 @@ def normalize_kp(kp_source, kp_driving, kp_driving_initial,
|
|
93 |
return kp_new
|
94 |
""")
|
95 |
|
96 |
-
# Bây giờ import các module cần thiết
|
97 |
-
import gradio as gr
|
98 |
-
import numpy as np
|
99 |
-
import torch
|
100 |
-
import imageio
|
101 |
-
from skimage.transform import resize
|
102 |
-
from skimage import img_as_ubyte
|
103 |
-
from PIL import Image
|
104 |
-
|
105 |
# Import hàm load_checkpoints từ file helper
|
106 |
from load_helper import load_checkpoints, normalize_kp
|
107 |
|
@@ -112,14 +100,14 @@ def download_model():
|
|
112 |
os.makedirs('checkpoints', exist_ok=True)
|
113 |
|
114 |
if not os.path.exists(model_path):
|
115 |
-
os.system('wget -
|
116 |
|
117 |
config_path = 'first_order_model/config/vox-256.yaml'
|
118 |
if not os.path.exists('first_order_model/config'):
|
119 |
os.makedirs('first_order_model/config', exist_ok=True)
|
120 |
|
121 |
if not os.path.exists(config_path):
|
122 |
-
os.system('wget -
|
123 |
|
124 |
return config_path, model_path
|
125 |
|
@@ -180,7 +168,8 @@ def make_animation(source_image, driving_video, relative=True, adapt_movement_sc
|
|
180 |
|
181 |
# Lưu video kết quả
|
182 |
output_path = 'result.mp4'
|
183 |
-
os.
|
|
|
184 |
|
185 |
# Lưu frames thành video sử dụng imageio
|
186 |
frames = [img_as_ubyte(frame) for frame in predictions]
|
@@ -189,21 +178,34 @@ def make_animation(source_image, driving_video, relative=True, adapt_movement_sc
|
|
189 |
return output_path
|
190 |
|
191 |
# Định nghĩa giao diện Gradio
|
192 |
-
def animate_fomm(source_image,
|
193 |
-
if source_image is None or
|
194 |
return None, "Vui lòng tải lên cả ảnh nguồn và video tham chiếu."
|
195 |
|
196 |
try:
|
197 |
-
# Lưu tạm ảnh
|
198 |
source_path = "source_image.jpg"
|
199 |
-
driving_path = "driving_video.mp4"
|
200 |
-
|
201 |
-
# Lưu ảnh nguồn
|
202 |
source_image.save(source_path)
|
203 |
|
204 |
-
#
|
205 |
-
|
206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
207 |
|
208 |
# Tạo animation
|
209 |
result_path = make_animation(
|
@@ -215,7 +217,8 @@ def animate_fomm(source_image, driving_video, relative=True, adapt_scale=True):
|
|
215 |
|
216 |
return result_path, "Video được tạo thành công!"
|
217 |
except Exception as e:
|
218 |
-
|
|
|
219 |
|
220 |
# Tạo giao diện Gradio
|
221 |
with gr.Blocks(title="First Order Motion Model - Tạo video người chuyển động") as demo:
|
@@ -225,28 +228,51 @@ with gr.Blocks(title="First Order Motion Model - Tạo video người chuyển
|
|
225 |
with gr.Row():
|
226 |
with gr.Column():
|
227 |
source_image = gr.Image(type="pil", label="Tải lên ảnh nguồn")
|
228 |
-
|
|
|
|
|
229 |
|
230 |
with gr.Row():
|
231 |
relative = gr.Checkbox(value=True, label="Chuyển động tương đối")
|
232 |
adapt_scale = gr.Checkbox(value=True, label="Điều chỉnh tỷ lệ chuyển động")
|
233 |
|
|
|
|
|
|
|
234 |
submit_btn = gr.Button("Tạo video")
|
235 |
|
236 |
with gr.Column():
|
237 |
output_video = gr.Video(label="Video kết quả")
|
238 |
-
output_message = gr.Textbox(label="Thông báo")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
239 |
|
240 |
submit_btn.click(
|
241 |
-
fn=
|
242 |
-
inputs=[source_image,
|
243 |
outputs=[output_video, output_message]
|
244 |
)
|
245 |
|
246 |
gr.Markdown("### Cách sử dụng")
|
247 |
gr.Markdown("1. Tải lên **ảnh nguồn** - ảnh chứa người/đối tượng bạn muốn làm chuyển động")
|
248 |
gr.Markdown("2. Tải lên **video tham chiếu** - video có chuyển động bạn muốn áp dụng")
|
249 |
-
gr.Markdown("3.
|
|
|
250 |
|
251 |
gr.Markdown("### Lưu ý")
|
252 |
gr.Markdown("- Ảnh nguồn và video tham chiếu nên có đối tượng tương tự (người với người, mặt với mặt)")
|
|
|
1 |
import os
|
2 |
import sys
|
3 |
import subprocess
|
4 |
+
import numpy as np
|
5 |
+
import torch
|
6 |
+
import imageio
|
7 |
+
from skimage.transform import resize
|
8 |
+
from skimage import img_as_ubyte
|
9 |
+
import gradio as gr
|
10 |
+
from PIL import Image
|
11 |
+
import tempfile
|
12 |
|
13 |
# Đảm bảo cài đặt các thư viện cần thiết trước khi import
|
14 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "scikit-learn"])
|
15 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "scikit-image==0.19.3"])
|
16 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "face-alignment==1.3.5"])
|
|
|
17 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "PyYAML==5.3.1"])
|
18 |
+
subprocess.check_call([sys.executable, "-m", "pip", "install", "imageio-ffmpeg==0.4.5"])
|
19 |
|
20 |
# Cài đặt ffmpeg trong môi trường Ubuntu
|
21 |
os.system("apt-get update && apt-get install -y ffmpeg")
|
|
|
23 |
# Clone repo nếu chưa có
|
24 |
if not os.path.exists('first_order_model'):
|
25 |
subprocess.call(['git', 'clone', 'https://github.com/AliaksandrSiarohin/first-order-model.git'])
|
26 |
+
if os.path.exists('first-order-model'):
|
27 |
+
os.rename('first-order-model', 'first_order_model')
|
28 |
|
29 |
# Thêm đường dẫn vào PYTHONPATH
|
30 |
sys.path.append('.')
|
31 |
sys.path.append('first_order_model')
|
32 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
33 |
# Tạo file helper với hàm load_checkpoints
|
34 |
with open('load_helper.py', 'w') as f:
|
35 |
f.write("""
|
|
|
40 |
|
41 |
def load_checkpoints(config_path, checkpoint_path, device='cpu'):
|
42 |
with open(config_path) as f:
|
43 |
+
config = yaml.safe_load(f)
|
44 |
|
45 |
generator = OcclusionAwareGenerator(**config['model_params']['generator_params'],
|
46 |
**config['model_params']['common_params'])
|
|
|
90 |
return kp_new
|
91 |
""")
|
92 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
# Import hàm load_checkpoints từ file helper
|
94 |
from load_helper import load_checkpoints, normalize_kp
|
95 |
|
|
|
100 |
os.makedirs('checkpoints', exist_ok=True)
|
101 |
|
102 |
if not os.path.exists(model_path):
|
103 |
+
os.system('wget -O checkpoints/vox-cpk.pth.tar https://drive.google.com/uc?export=download&id=1PyQJmkdCsAkOYwUyaj_l-l0as-iLDgeH')
|
104 |
|
105 |
config_path = 'first_order_model/config/vox-256.yaml'
|
106 |
if not os.path.exists('first_order_model/config'):
|
107 |
os.makedirs('first_order_model/config', exist_ok=True)
|
108 |
|
109 |
if not os.path.exists(config_path):
|
110 |
+
os.system('wget -O first_order_model/config/vox-256.yaml https://drive.google.com/uc?export=download&id=1pZUMNRjkBiuBEM68oj9nskuWgJR-5QMn')
|
111 |
|
112 |
return config_path, model_path
|
113 |
|
|
|
168 |
|
169 |
# Lưu video kết quả
|
170 |
output_path = 'result.mp4'
|
171 |
+
if os.path.exists(output_path):
|
172 |
+
os.remove(output_path) # Xóa video nếu tồn tại
|
173 |
|
174 |
# Lưu frames thành video sử dụng imageio
|
175 |
frames = [img_as_ubyte(frame) for frame in predictions]
|
|
|
178 |
return output_path
|
179 |
|
180 |
# Định nghĩa giao diện Gradio
|
181 |
+
def animate_fomm(source_image, driving_video_file, relative=True, adapt_scale=True):
|
182 |
+
if source_image is None or driving_video_file is None:
|
183 |
return None, "Vui lòng tải lên cả ảnh nguồn và video tham chiếu."
|
184 |
|
185 |
try:
|
186 |
+
# Lưu tạm ảnh nguồn
|
187 |
source_path = "source_image.jpg"
|
|
|
|
|
|
|
188 |
source_image.save(source_path)
|
189 |
|
190 |
+
# Xử lý video tham chiếu - Sửa lỗi "a bytes-like object is required, not 'str'"
|
191 |
+
print(f"Type of driving_video: {type(driving_video_file)}")
|
192 |
+
|
193 |
+
# Tạo file tạm cho video
|
194 |
+
driving_path = "driving_video.mp4"
|
195 |
+
|
196 |
+
# Kiểm tra loại dữ liệu của driving_video_file
|
197 |
+
if isinstance(driving_video_file, str):
|
198 |
+
# Nếu là đường dẫn, sử dụng video mẫu hoặc copy file
|
199 |
+
if os.path.exists(driving_video_file):
|
200 |
+
import shutil
|
201 |
+
shutil.copyfile(driving_video_file, driving_path)
|
202 |
+
else:
|
203 |
+
# Tải video mẫu
|
204 |
+
os.system("wget -O driving_video.mp4 https://github.com/AliaksandrSiarohin/first-order-model/raw/master/driving.mp4")
|
205 |
+
else:
|
206 |
+
# Ghi dữ liệu nhị phân vào file
|
207 |
+
with open(driving_path, 'wb') as f:
|
208 |
+
f.write(driving_video_file)
|
209 |
|
210 |
# Tạo animation
|
211 |
result_path = make_animation(
|
|
|
217 |
|
218 |
return result_path, "Video được tạo thành công!"
|
219 |
except Exception as e:
|
220 |
+
import traceback
|
221 |
+
return None, f"Lỗi: {str(e)}\n{traceback.format_exc()}"
|
222 |
|
223 |
# Tạo giao diện Gradio
|
224 |
with gr.Blocks(title="First Order Motion Model - Tạo video người chuyển động") as demo:
|
|
|
228 |
with gr.Row():
|
229 |
with gr.Column():
|
230 |
source_image = gr.Image(type="pil", label="Tải lên ảnh nguồn")
|
231 |
+
|
232 |
+
# Thay đổi từ gr.Video sang gr.File để xử lý lỗi binary
|
233 |
+
driving_video_file = gr.File(label="Tải lên video tham chiếu (.mp4)")
|
234 |
|
235 |
with gr.Row():
|
236 |
relative = gr.Checkbox(value=True, label="Chuyển động tương đối")
|
237 |
adapt_scale = gr.Checkbox(value=True, label="Điều chỉnh tỷ lệ chuyển động")
|
238 |
|
239 |
+
# Thêm tùy chọn sử dụng video mẫu
|
240 |
+
use_sample = gr.Checkbox(label="Sử dụng video mẫu (nếu bạn không muốn tải lên video)")
|
241 |
+
|
242 |
submit_btn = gr.Button("Tạo video")
|
243 |
|
244 |
with gr.Column():
|
245 |
output_video = gr.Video(label="Video kết quả")
|
246 |
+
output_message = gr.Textbox(label="Thông báo", lines=5)
|
247 |
+
|
248 |
+
# Xử lý sự kiện khi checkbox được chọn
|
249 |
+
def toggle_video_upload(use_sample_video):
|
250 |
+
return gr.update(interactive=not use_sample_video)
|
251 |
+
|
252 |
+
use_sample.change(fn=toggle_video_upload, inputs=[use_sample], outputs=[driving_video_file])
|
253 |
+
|
254 |
+
# Cập nhật hàm xử lý khi nhấn nút
|
255 |
+
def process_inputs(source_img, driving_vid, use_sample_vid, rel, adapt):
|
256 |
+
if use_sample_vid:
|
257 |
+
# Tải video mẫu nếu cần
|
258 |
+
sample_path = "sample_driving.mp4"
|
259 |
+
if not os.path.exists(sample_path):
|
260 |
+
os.system("wget -O sample_driving.mp4 https://github.com/AliaksandrSiarohin/first-order-model/raw/master/driving.mp4")
|
261 |
+
return animate_fomm(source_img, sample_path, rel, adapt)
|
262 |
+
else:
|
263 |
+
return animate_fomm(source_img, driving_vid, rel, adapt)
|
264 |
|
265 |
submit_btn.click(
|
266 |
+
fn=process_inputs,
|
267 |
+
inputs=[source_image, driving_video_file, use_sample, relative, adapt_scale],
|
268 |
outputs=[output_video, output_message]
|
269 |
)
|
270 |
|
271 |
gr.Markdown("### Cách sử dụng")
|
272 |
gr.Markdown("1. Tải lên **ảnh nguồn** - ảnh chứa người/đối tượng bạn muốn làm chuyển động")
|
273 |
gr.Markdown("2. Tải lên **video tham chiếu** - video có chuyển động bạn muốn áp dụng")
|
274 |
+
gr.Markdown("3. Hoặc chọn sử dụng video mẫu có sẵn")
|
275 |
+
gr.Markdown("4. Nhấn **Tạo video** và chờ kết quả")
|
276 |
|
277 |
gr.Markdown("### Lưu ý")
|
278 |
gr.Markdown("- Ảnh nguồn và video tham chiếu nên có đối tượng tương tự (người với người, mặt với mặt)")
|