Spaces:
Running
Running
udpate lib
Browse files- app.py +79 -41
- requirements.txt +1 -6
app.py
CHANGED
@@ -1,19 +1,17 @@
|
|
1 |
import gradio as gr
|
2 |
import torch
|
3 |
-
from transformers import pipeline
|
4 |
-
from huggingface_hub import hf_hub_download
|
5 |
import os
|
6 |
from PIL import Image
|
7 |
import numpy as np
|
8 |
-
|
9 |
import time
|
10 |
|
11 |
-
# Kiểm tra
|
12 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
13 |
print(f"Using device: {device}")
|
14 |
|
15 |
-
#
|
16 |
-
def generate_video(image,
|
17 |
if image is None:
|
18 |
return None, "Vui lòng tải lên một hình ảnh"
|
19 |
|
@@ -25,36 +23,72 @@ def generate_video(image, prompt, num_frames=16, guidance_scale=7.5):
|
|
25 |
image = image.resize((512, 512))
|
26 |
|
27 |
try:
|
28 |
-
#
|
29 |
-
image_path = "input_image.jpg"
|
30 |
-
image.save(image_path)
|
31 |
-
|
32 |
-
# Tạo chuỗi khung hình đơn giản (hiệu ứng zoom-in)
|
33 |
frames = []
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
# Tạo video từ các khung hình
|
55 |
-
clip = ImageSequenceClip(frames, fps=8)
|
56 |
output_path = f"output_video_{int(time.time())}.mp4"
|
57 |
-
|
58 |
|
59 |
return output_path, "Video đã được tạo thành công!"
|
60 |
except Exception as e:
|
@@ -63,16 +97,18 @@ def generate_video(image, prompt, num_frames=16, guidance_scale=7.5):
|
|
63 |
# Tạo giao diện Gradio
|
64 |
with gr.Blocks(title="Ứng dụng tạo video từ hình ảnh") as demo:
|
65 |
gr.Markdown("# Tạo video từ hình ảnh")
|
66 |
-
gr.Markdown("Tải lên một hình ảnh và
|
67 |
|
68 |
with gr.Row():
|
69 |
with gr.Column():
|
70 |
image_input = gr.Image(type="pil", label="Tải lên hình ảnh")
|
71 |
-
|
72 |
-
|
73 |
-
|
|
|
|
|
74 |
num_frames = gr.Slider(minimum=10, maximum=30, value=16, step=2, label="Số khung hình")
|
75 |
-
|
76 |
submit_btn = gr.Button("Tạo video")
|
77 |
|
78 |
with gr.Column():
|
@@ -81,12 +117,14 @@ with gr.Blocks(title="Ứng dụng tạo video từ hình ảnh") as demo:
|
|
81 |
|
82 |
submit_btn.click(
|
83 |
fn=generate_video,
|
84 |
-
inputs=[image_input,
|
85 |
outputs=[output_video, output_message]
|
86 |
)
|
87 |
|
88 |
-
gr.Markdown("###
|
89 |
-
gr.Markdown("-
|
90 |
-
gr.Markdown("-
|
|
|
|
|
91 |
|
92 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
import torch
|
|
|
|
|
3 |
import os
|
4 |
from PIL import Image
|
5 |
import numpy as np
|
6 |
+
import imageio
|
7 |
import time
|
8 |
|
9 |
+
# Kiểm tra device
|
10 |
device = "cuda" if torch.cuda.is_available() else "cpu"
|
11 |
print(f"Using device: {device}")
|
12 |
|
13 |
+
# Hàm tạo video đơn giản
|
14 |
+
def generate_video(image, effect_type, num_frames=16, effect_strength=5.0):
|
15 |
if image is None:
|
16 |
return None, "Vui lòng tải lên một hình ảnh"
|
17 |
|
|
|
23 |
image = image.resize((512, 512))
|
24 |
|
25 |
try:
|
26 |
+
# Tạo chuỗi khung hình với hiệu ứng khác nhau
|
|
|
|
|
|
|
|
|
27 |
frames = []
|
28 |
+
|
29 |
+
if effect_type == "zoom-in":
|
30 |
+
# Hiệu ứng zoom-in
|
31 |
+
for i in range(num_frames):
|
32 |
+
zoom_factor = 1.0 + (i / num_frames) * (effect_strength / 10)
|
33 |
+
img_copy = image.copy()
|
34 |
+
|
35 |
+
size = int(img_copy.width / zoom_factor)
|
36 |
+
left = (img_copy.width - size) // 2
|
37 |
+
top = (img_copy.height - size) // 2
|
38 |
+
right = left + size
|
39 |
+
bottom = top + size
|
40 |
+
|
41 |
+
cropped = img_copy.crop((left, top, right, bottom))
|
42 |
+
frame = cropped.resize((512, 512))
|
43 |
+
frames.append(np.array(frame))
|
44 |
+
|
45 |
+
elif effect_type == "pan-right":
|
46 |
+
# Hiệu ứng pan từ trái sang phải
|
47 |
+
width, height = image.size
|
48 |
+
for i in range(num_frames):
|
49 |
+
offset = int((i / num_frames) * width * (effect_strength / 10))
|
50 |
+
img_copy = image.copy()
|
51 |
+
|
52 |
+
# Tạo hiệu ứng pan
|
53 |
+
if offset > 0:
|
54 |
+
# Lấy phần hình ảnh từ offset đến cuối
|
55 |
+
right_part = img_copy.crop((offset, 0, width, height))
|
56 |
+
# Lấy phần còn lại từ đầu
|
57 |
+
left_part = img_copy.crop((0, 0, offset, height))
|
58 |
+
# Tạo hình ảnh mới
|
59 |
+
new_img = Image.new('RGB', (width, height))
|
60 |
+
new_img.paste(right_part, (0, 0))
|
61 |
+
new_img.paste(left_part, (width - offset, 0))
|
62 |
+
frames.append(np.array(new_img))
|
63 |
+
else:
|
64 |
+
frames.append(np.array(img_copy))
|
65 |
+
|
66 |
+
elif effect_type == "fade":
|
67 |
+
# Hiệu ứng fade in/out
|
68 |
+
base_frame = np.array(image)
|
69 |
+
for i in range(num_frames):
|
70 |
+
# Tính toán độ mờ
|
71 |
+
if i < num_frames / 2:
|
72 |
+
# Fade in
|
73 |
+
alpha = i / (num_frames / 2)
|
74 |
+
else:
|
75 |
+
# Fade out
|
76 |
+
alpha = 2.0 - (i / (num_frames / 2))
|
77 |
+
|
78 |
+
# Áp dụng độ mờ
|
79 |
+
frame = (base_frame * alpha * (effect_strength / 5)).astype(np.uint8)
|
80 |
+
frames.append(frame)
|
81 |
+
|
82 |
+
else:
|
83 |
+
# Mặc định, chỉ thêm hiệu ứng đơn giản
|
84 |
+
for i in range(num_frames):
|
85 |
+
brightness = 1.0 + (effect_strength / 10) * np.sin(2 * np.pi * i / num_frames)
|
86 |
+
frame = (np.array(image) * brightness).clip(0, 255).astype(np.uint8)
|
87 |
+
frames.append(frame)
|
88 |
|
89 |
# Tạo video từ các khung hình
|
|
|
90 |
output_path = f"output_video_{int(time.time())}.mp4"
|
91 |
+
imageio.mimsave(output_path, frames, fps=8)
|
92 |
|
93 |
return output_path, "Video đã được tạo thành công!"
|
94 |
except Exception as e:
|
|
|
97 |
# Tạo giao diện Gradio
|
98 |
with gr.Blocks(title="Ứng dụng tạo video từ hình ảnh") as demo:
|
99 |
gr.Markdown("# Tạo video từ hình ảnh")
|
100 |
+
gr.Markdown("Tải lên một hình ảnh và chọn hiệu ứng để tạo video.")
|
101 |
|
102 |
with gr.Row():
|
103 |
with gr.Column():
|
104 |
image_input = gr.Image(type="pil", label="Tải lên hình ảnh")
|
105 |
+
effect_input = gr.Radio(
|
106 |
+
["zoom-in", "pan-right", "fade", "pulse"],
|
107 |
+
label="Chọn hiệu ứng",
|
108 |
+
value="zoom-in"
|
109 |
+
)
|
110 |
num_frames = gr.Slider(minimum=10, maximum=30, value=16, step=2, label="Số khung hình")
|
111 |
+
effect_strength = gr.Slider(minimum=1.0, maximum=10.0, value=5.0, step=0.5, label="Độ mạnh của hiệu ứng")
|
112 |
submit_btn = gr.Button("Tạo video")
|
113 |
|
114 |
with gr.Column():
|
|
|
117 |
|
118 |
submit_btn.click(
|
119 |
fn=generate_video,
|
120 |
+
inputs=[image_input, effect_input, num_frames, effect_strength],
|
121 |
outputs=[output_video, output_message]
|
122 |
)
|
123 |
|
124 |
+
gr.Markdown("### Hướng dẫn")
|
125 |
+
gr.Markdown("- **Zoom-in**: Hiệu ứng phóng to hình ảnh")
|
126 |
+
gr.Markdown("- **Pan-right**: Hiệu ứng di chuyển từ trái sang phải")
|
127 |
+
gr.Markdown("- **Fade**: Hiệu ứng mờ dần rồi hiện dần")
|
128 |
+
gr.Markdown("- **Pulse**: Hiệu ứng thay đổi độ sáng theo nhịp")
|
129 |
|
130 |
demo.launch()
|
requirements.txt
CHANGED
@@ -4,9 +4,4 @@ torchvision
|
|
4 |
pillow
|
5 |
numpy
|
6 |
imageio==2.31.1
|
7 |
-
imageio-ffmpeg
|
8 |
-
decorator>=4.0.2
|
9 |
-
tqdm>=4.11.2
|
10 |
-
proglog<=1.0.0
|
11 |
-
requests
|
12 |
-
moviepy==1.0.3
|
|
|
4 |
pillow
|
5 |
numpy
|
6 |
imageio==2.31.1
|
7 |
+
imageio-ffmpeg
|
|
|
|
|
|
|
|
|
|