Spaces:
aiqtech
/
Running on Zero

aiqtech commited on
Commit
856ab89
·
verified ·
1 Parent(s): 28192a4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +115 -63
app.py CHANGED
@@ -8,110 +8,162 @@ from PIL import Image
8
  from diffusers.utils import export_to_gif
9
  from transformers import pipeline
10
 
11
- HEIGHT = 256
12
- WIDTH = 1024
 
 
 
 
13
  MAX_SEED = np.iinfo(np.int32).max
14
 
 
 
 
 
15
  device = "cuda" if torch.cuda.is_available() else "cpu"
16
- pipe = FluxPipeline.from_pretrained(
17
- "black-forest-labs/FLUX.1-dev",
18
- torch_dtype=torch.bfloat16
19
- ).to(device)
 
 
 
20
 
 
21
  translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en")
22
 
23
- def split_image(input_image, num_splits=4):
24
- output_images = []
25
- for i in range(num_splits):
26
- left = i * 256
27
- right = (i + 1) * 256
28
- box = (left, 0, right, 256)
29
- output_images.append(input_image.crop(box))
30
- return output_images
 
 
 
 
 
 
 
31
 
32
- def translate_to_english(text):
33
- return translator(text)[0]['translation_text']
34
 
35
  @spaces.GPU()
36
- def predict(prompt, seed=42, randomize_seed=False, guidance_scale=5.0, num_inference_steps=28, progress=gr.Progress(track_tqdm=True)):
37
- if any('\u3131' <= char <= '\u318E' or '\uAC00' <= char <= '\uD7A3' for char in prompt):
 
 
 
 
 
 
 
 
 
 
38
  prompt = translate_to_english(prompt)
39
-
40
- prompt_template = f"""
41
- A side by side 4 frame image showing consecutive stills from a looped gif moving from left to right. The gif is of {prompt}.
42
- """
43
-
 
 
 
44
  if randomize_seed:
45
  seed = random.randint(0, MAX_SEED)
46
-
 
 
 
47
  image = pipe(
48
  prompt=prompt_template,
49
  guidance_scale=guidance_scale,
50
  num_inference_steps=num_inference_steps,
51
  num_images_per_prompt=1,
52
- generator=torch.Generator("cpu").manual_seed(seed),
53
- height=HEIGHT,
54
- width=WIDTH
55
  ).images[0]
56
-
57
- return export_to_gif(split_image(image, 4), "flux.gif", fps=4), image, seed
 
 
 
 
 
 
 
58
 
59
  css = """
60
- footer { visibility: hidden;}
 
61
  """
62
 
63
  examples = [
64
- "고양이가 공중에서 발을 흔드는 모습",
65
- "팬더가 엉덩이를 좌우로 흔드는 모습",
66
- "꽃이 피어나는 과정"
67
  ]
68
 
69
  with gr.Blocks(theme="soft", css=css) as demo:
 
 
70
  with gr.Column(elem_id="col-container"):
 
71
  with gr.Row():
72
- prompt = gr.Text(label="프롬프트", show_label=False, max_lines=1, placeholder="프롬프트를 입력하세요")
73
- submit = gr.Button("제출", scale=0)
74
- output = gr.Image(label="GIF", show_label=False)
75
- output_stills = gr.Image(label="스틸 이미지", show_label=False, elem_id="stills")
76
-
77
- with gr.Accordion("고급 설정", open=False):
78
- seed = gr.Slider(
79
- label="시드",
80
- minimum=0,
81
- maximum=MAX_SEED,
82
- step=1,
83
- value=0,
84
  )
85
- randomize_seed = gr.Checkbox(label="시드 무작위화", value=True)
 
 
 
 
 
 
 
 
 
86
  with gr.Row():
87
  guidance_scale = gr.Slider(
88
- label="가이던스 스케일",
89
- minimum=1,
90
- maximum=15,
91
- step=0.1,
92
- value=3.5,
93
  )
94
  num_inference_steps = gr.Slider(
95
- label="추론 단계 수",
96
- minimum=1,
97
- maximum=50,
98
- step=1,
99
- value=28,
100
  )
101
-
 
 
 
 
 
 
 
 
102
  gr.Examples(
103
  examples=examples,
104
  fn=predict,
105
  inputs=[prompt],
106
- outputs=[output, output_stills, seed],
107
- cache_examples="lazy"
108
  )
109
-
 
110
  gr.on(
111
  triggers=[submit.click, prompt.submit],
112
  fn=predict,
113
- inputs=[prompt, seed, randomize_seed, guidance_scale, num_inference_steps],
114
- outputs=[output, output_stills, seed]
 
 
 
 
 
 
 
 
115
  )
116
 
117
- demo.launch()
 
8
  from diffusers.utils import export_to_gif
9
  from transformers import pipeline
10
 
11
+ # -------------------------
12
+ # Configuration constants
13
+ # -------------------------
14
+ FRAMES = 4 # number of stills laid out horizontally
15
+ DEFAULT_HEIGHT = 256 # per‑frame size (px)
16
+ DEFAULT_FPS = 8 # smoother playback than the original 4 fps
17
  MAX_SEED = np.iinfo(np.int32).max
18
 
19
+ # -------------------------
20
+ # Model initialisation
21
+ # -------------------------
22
+
23
  device = "cuda" if torch.cuda.is_available() else "cpu"
24
+ pipe = (
25
+ FluxPipeline.from_pretrained(
26
+ "black-forest-labs/FLUX.1-dev",
27
+ torch_dtype=torch.float16, # slightly higher precision than bfloat16 for crisper output
28
+ )
29
+ .to(device)
30
+ )
31
 
32
+ # English is the primary UI language, but Korean prompts are still accepted & translated.
33
  translator = pipeline("translation", model="Helsinki-NLP/opus-mt-ko-en")
34
 
35
+ # -------------------------
36
+ # Helper functions
37
+ # -------------------------
38
+
39
+ def split_image(input_image: Image.Image, frame_size: int) -> list[Image.Image]:
40
+ """Cut a wide strip into equal square frames."""
41
+ return [
42
+ input_image.crop((i * frame_size, 0, (i + 1) * frame_size, frame_size))
43
+ for i in range(FRAMES)
44
+ ]
45
+
46
+
47
+ def translate_to_english(text: str) -> str:
48
+ """Translate Korean text to English if necessary."""
49
+ return translator(text)[0]["translation_text"]
50
 
 
 
51
 
52
  @spaces.GPU()
53
+ def predict(
54
+ prompt: str,
55
+ seed: int = 42,
56
+ randomize_seed: bool = False,
57
+ guidance_scale: float = 7.0,
58
+ num_inference_steps: int = 40,
59
+ height: int = DEFAULT_HEIGHT,
60
+ fps: int = DEFAULT_FPS,
61
+ progress: gr.Progress = gr.Progress(track_tqdm=True),
62
+ ):
63
+ # 1) Language handling
64
+ if any("\u3131" <= ch <= "\u318E" or "\uAC00" <= ch <= "\uD7A3" for ch in prompt):
65
  prompt = translate_to_english(prompt)
66
+
67
+ # 2) Prompt template
68
+ prompt_template = (
69
+ f"A side-by-side {FRAMES} frame image showing consecutive stills from a looped gif moving left to right. "
70
+ f"The gif is of {prompt}."
71
+ )
72
+
73
+ # 3) Seed control
74
  if randomize_seed:
75
  seed = random.randint(0, MAX_SEED)
76
+
77
+ width = FRAMES * height # maintain square frames
78
+
79
+ # 4) Generation
80
  image = pipe(
81
  prompt=prompt_template,
82
  guidance_scale=guidance_scale,
83
  num_inference_steps=num_inference_steps,
84
  num_images_per_prompt=1,
85
+ generator=torch.Generator(device).manual_seed(seed),
86
+ height=height,
87
+ width=width,
88
  ).images[0]
89
+
90
+ # 5) Assemble gif
91
+ gif_path = export_to_gif(split_image(image, height), "flux.gif", fps=fps)
92
+ return gif_path, image, seed
93
+
94
+
95
+ # -------------------------
96
+ # Interface
97
+ # -------------------------
98
 
99
  css = """
100
+ #col-container {max-width: 820px; margin: 0 auto;}
101
+ footer {visibility: hidden;}
102
  """
103
 
104
  examples = [
105
+ "cat lazily swinging its paws in mid-air",
106
+ "panda shaking its hips",
107
+ "flower blooming in timelapse",
108
  ]
109
 
110
  with gr.Blocks(theme="soft", css=css) as demo:
111
+ gr.Markdown("<h1 style='text-align:center'>FLUX GIF Generator</h1>")
112
+
113
  with gr.Column(elem_id="col-container"):
114
+ # Prompt row
115
  with gr.Row():
116
+ prompt = gr.Text(
117
+ label="", show_label=False, max_lines=1, placeholder="Enter your prompt here…"
 
 
 
 
 
 
 
 
 
 
118
  )
119
+ submit = gr.Button("Generate", scale=0)
120
+
121
+ # Outputs
122
+ output_gif = gr.Image(label="", show_label=False)
123
+ output_stills = gr.Image(label="", show_label=False, elem_id="stills")
124
+
125
+ # Advanced controls
126
+ with gr.Accordion("Advanced settings", open=False):
127
+ seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=0)
128
+ randomize_seed = gr.Checkbox(label="Randomize seed", value=True)
129
  with gr.Row():
130
  guidance_scale = gr.Slider(
131
+ label="Guidance scale", minimum=1, maximum=15, step=0.1, value=7.0
 
 
 
 
132
  )
133
  num_inference_steps = gr.Slider(
134
+ label="Inference steps", minimum=10, maximum=60, step=1, value=40
 
 
 
 
135
  )
136
+ with gr.Row():
137
+ height = gr.Slider(
138
+ label="Frame size (px)", minimum=256, maximum=512, step=64, value=DEFAULT_HEIGHT
139
+ )
140
+ fps = gr.Slider(
141
+ label="GIF FPS", minimum=4, maximum=20, step=1, value=DEFAULT_FPS
142
+ )
143
+
144
+ # Example prompts
145
  gr.Examples(
146
  examples=examples,
147
  fn=predict,
148
  inputs=[prompt],
149
+ outputs=[output_gif, output_stills, seed],
150
+ cache_examples="lazy",
151
  )
152
+
153
+ # Event wiring
154
  gr.on(
155
  triggers=[submit.click, prompt.submit],
156
  fn=predict,
157
+ inputs=[
158
+ prompt,
159
+ seed,
160
+ randomize_seed,
161
+ guidance_scale,
162
+ num_inference_steps,
163
+ height,
164
+ fps,
165
+ ],
166
+ outputs=[output_gif, output_stills, seed],
167
  )
168
 
169
+ demo.launch()