Spaces:
Running
Running
Update app.py
#2
by Mhmodijla - opened
app.py
CHANGED
|
@@ -60,7 +60,7 @@ def is_valid_prompt(prompt):
|
|
| 60 |
|
| 61 |
return True
|
| 62 |
|
| 63 |
-
# ββ Generation function ββββββββββββββββββββββββββββββββββββββ
|
| 64 |
def generate_image(prompt, num_inference_steps=500, guidance_scale=7.5):
|
| 65 |
if not is_valid_prompt(prompt):
|
| 66 |
raise gr.Error("Please enter a valid prompt (not empty or special characters only).")
|
|
@@ -144,38 +144,135 @@ def generate_image(prompt, num_inference_steps=500, guidance_scale=7.5):
|
|
| 144 |
|
| 145 |
return image
|
| 146 |
|
| 147 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
with gr.Blocks() as demo:
|
| 149 |
-
gr.Markdown("# πΌοΈ Latent Diffusion Model β Text to Image")
|
| 150 |
-
|
| 151 |
-
with gr.
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
if __name__ == "__main__":
|
| 181 |
demo.launch()
|
|
|
|
| 60 |
|
| 61 |
return True
|
| 62 |
|
| 63 |
+
# ββ Generation function (Text-to-Image) ββββββββββββββββββββββββββββββββββββββ
|
| 64 |
def generate_image(prompt, num_inference_steps=500, guidance_scale=7.5):
|
| 65 |
if not is_valid_prompt(prompt):
|
| 66 |
raise gr.Error("Please enter a valid prompt (not empty or special characters only).")
|
|
|
|
| 144 |
|
| 145 |
return image
|
| 146 |
|
| 147 |
+
|
| 148 |
+
# ββ NEW: Image-to-Image (Img2Img) Function βββββββββββββββββββββββββββββββββββ
|
| 149 |
+
def generate_img2img(prompt, init_image, strength=0.75, num_inference_steps=500, guidance_scale=7.5):
|
| 150 |
+
if init_image is None:
|
| 151 |
+
raise gr.Error("Please upload an image first.")
|
| 152 |
+
if not is_valid_prompt(prompt):
|
| 153 |
+
raise gr.Error("Please enter a valid prompt (not empty or special characters only).")
|
| 154 |
+
|
| 155 |
+
# 1. Preprocess the input image
|
| 156 |
+
init_image = init_image.convert("RGB").resize((128, 128))
|
| 157 |
+
init_tensor = torch.from_numpy(np.array(init_image)).permute(2, 0, 1).unsqueeze(0).float() / 255.0
|
| 158 |
+
init_tensor = (init_tensor * 2 - 1).to(device)
|
| 159 |
+
if torch_dtype == torch.float16:
|
| 160 |
+
init_tensor = init_tensor.half()
|
| 161 |
+
|
| 162 |
+
# 2. Encode image to latent space
|
| 163 |
+
with torch.no_grad():
|
| 164 |
+
latents = vae.encode(init_tensor).latent_dist.sample()
|
| 165 |
+
latents = 0.18215 * latents
|
| 166 |
+
|
| 167 |
+
# 3. Add noise according to strength
|
| 168 |
+
noise = torch.randn_like(latents)
|
| 169 |
+
start_step = int(strength * num_inference_steps)
|
| 170 |
+
scheduler.set_timesteps(num_inference_steps)
|
| 171 |
+
timesteps = scheduler.timesteps
|
| 172 |
+
|
| 173 |
+
if start_step < len(timesteps):
|
| 174 |
+
t_start = timesteps[start_step]
|
| 175 |
+
latents = scheduler.add_noise(latents, noise, t_start)
|
| 176 |
+
else:
|
| 177 |
+
latents = scheduler.add_noise(latents, noise, timesteps[-1])
|
| 178 |
+
|
| 179 |
+
# 4. Prepare text embeddings (same as txt2img)
|
| 180 |
+
text_input = tokenizer(
|
| 181 |
+
prompt, padding="max_length", max_length=77,
|
| 182 |
+
truncation=True, return_tensors="pt"
|
| 183 |
+
).to(device)
|
| 184 |
+
|
| 185 |
+
uncond_input = tokenizer(
|
| 186 |
+
[""], padding="max_length", max_length=77,
|
| 187 |
+
truncation=True, return_tensors="pt"
|
| 188 |
+
).to(device)
|
| 189 |
+
|
| 190 |
+
with torch.no_grad():
|
| 191 |
+
text_embeddings = text_encoder(text_input.input_ids)[0]
|
| 192 |
+
uncond_embeddings = text_encoder(uncond_input.input_ids)[0]
|
| 193 |
+
text_embeddings = torch.cat([uncond_embeddings, text_embeddings])
|
| 194 |
+
|
| 195 |
+
# 5. Denoising loop (starting from noisy latent)
|
| 196 |
+
for i, t in enumerate(timesteps):
|
| 197 |
+
if i < start_step:
|
| 198 |
+
continue # skip steps we already noised
|
| 199 |
+
|
| 200 |
+
latent_model_input = torch.cat([latents] * 2)
|
| 201 |
+
latent_model_input = scheduler.scale_model_input(latent_model_input, t)
|
| 202 |
+
|
| 203 |
+
with torch.no_grad():
|
| 204 |
+
noise_pred = unet(
|
| 205 |
+
latent_model_input, t,
|
| 206 |
+
encoder_hidden_states=text_embeddings
|
| 207 |
+
).sample
|
| 208 |
+
|
| 209 |
+
noise_pred_uncond, noise_pred_text = noise_pred.chunk(2)
|
| 210 |
+
noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)
|
| 211 |
+
latents = scheduler.step(noise_pred, t, latents).prev_sample
|
| 212 |
+
|
| 213 |
+
# 6. Decode
|
| 214 |
+
latents = 1 / 0.18215 * latents
|
| 215 |
+
with torch.no_grad():
|
| 216 |
+
image = vae.decode(latents).sample
|
| 217 |
+
|
| 218 |
+
image = (image / 2 + 0.5).clamp(0, 1)
|
| 219 |
+
image = image.detach().cpu().float()
|
| 220 |
+
image = image.permute(0, 2, 3, 1).squeeze(0).numpy()
|
| 221 |
+
image = (image * 255).round().astype("uint8")
|
| 222 |
+
return Image.fromarray(image)
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
# ββ Gradio UI (Ω
ΨΉ Ψ§ΩΨͺΨ¨ΩΩΨ¨Ψ§Ψͺ) ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 226 |
with gr.Blocks() as demo:
|
| 227 |
+
gr.Markdown("# πΌοΈ Latent Diffusion Model β Text to Image + Img2Img")
|
| 228 |
+
|
| 229 |
+
with gr.Tabs():
|
| 230 |
+
# ΨͺΨ¨ΩΩΨ¨ Text-to-Image (Ψ§ΩΩΩΨ― Ψ§ΩΨ£Ψ΅ΩΩ Ψ¨Ψ―ΩΩ Ψ£Ω ΨͺΨΊΩΩΨ±)
|
| 231 |
+
with gr.TabItem("Text to Image"):
|
| 232 |
+
with gr.Row():
|
| 233 |
+
with gr.Column():
|
| 234 |
+
prompt = gr.Text(label="Prompt", placeholder="e.g. people walking on street")
|
| 235 |
+
steps = gr.Slider(label="Inference Steps", minimum=100, maximum=1000, step=50, value=500)
|
| 236 |
+
guidance = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=15.0, step=0.5, value=7.5)
|
| 237 |
+
generate_button = gr.Button("Generate", variant="primary")
|
| 238 |
+
|
| 239 |
+
with gr.Column():
|
| 240 |
+
output_image = gr.Image(label="Generated Image")
|
| 241 |
+
|
| 242 |
+
generate_button.click(
|
| 243 |
+
fn=generate_image,
|
| 244 |
+
inputs=[prompt, steps, guidance],
|
| 245 |
+
outputs=[output_image]
|
| 246 |
+
)
|
| 247 |
+
|
| 248 |
+
gr.Examples(
|
| 249 |
+
examples=[
|
| 250 |
+
["people walking on street", 500, 7.5],
|
| 251 |
+
["a dog playing in the park", 500, 7.5],
|
| 252 |
+
["sunset over mountains", 500, 7.5],
|
| 253 |
+
],
|
| 254 |
+
inputs=[prompt, steps, guidance]
|
| 255 |
+
)
|
| 256 |
+
|
| 257 |
+
# ΨͺΨ¨ΩΩΨ¨ Image-to-Image (Ψ§ΩΨ¬Ψ―ΩΨ―)
|
| 258 |
+
with gr.TabItem("Image to Image (Img2Img)"):
|
| 259 |
+
with gr.Row():
|
| 260 |
+
with gr.Column():
|
| 261 |
+
init_image = gr.Image(label="Ψ§Ψ±ΩΨΉ Ψ§ΩΨ΅ΩΨ±Ψ©", type="pil")
|
| 262 |
+
prompt_img = gr.Text(label="Prompt", placeholder="Ψ§ΩΨͺΨ¨ ΩΨ΅Ω Ψ§ΩΨͺΨΉΨ―ΩΩ Ψ§ΩΩ
Ψ·ΩΩΨ¨")
|
| 263 |
+
strength = gr.Slider(label="Strength (ΩΩΨ© Ψ§ΩΨͺΨΉΨ―ΩΩ)", minimum=0.1, maximum=1.0, step=0.05, value=0.75)
|
| 264 |
+
steps_img = gr.Slider(label="Inference Steps", minimum=100, maximum=1000, step=50, value=500)
|
| 265 |
+
guidance_img = gr.Slider(label="Guidance Scale", minimum=1.0, maximum=15.0, step=0.5, value=7.5)
|
| 266 |
+
generate_img_btn = gr.Button("Generate from Image", variant="primary")
|
| 267 |
+
|
| 268 |
+
with gr.Column():
|
| 269 |
+
output_img2img = gr.Image(label="Ψ§ΩΨ΅ΩΨ±Ψ© Ψ§ΩΩ
ΨΉΨ―ΩΨ©")
|
| 270 |
+
|
| 271 |
+
generate_img_btn.click(
|
| 272 |
+
fn=generate_img2img,
|
| 273 |
+
inputs=[prompt_img, init_image, strength, steps_img, guidance_img],
|
| 274 |
+
outputs=[output_img2img]
|
| 275 |
+
)
|
| 276 |
|
| 277 |
if __name__ == "__main__":
|
| 278 |
demo.launch()
|