darwinlevead commited on
Commit
bea6963
·
1 Parent(s): 15d1fb7

Upload stable_diffusion_2_0.ipynb

Browse files
Files changed (1) hide show
  1. stable_diffusion_2_0.ipynb +602 -0
stable_diffusion_2_0.ipynb ADDED
@@ -0,0 +1,602 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "markdown",
5
+ "metadata": {
6
+ "id": "620o1BxdNbgq"
7
+ },
8
+ "source": [
9
+ "# **Stable Diffusion 2.1**\n",
10
+ "Gradio app for [Stable Diffusion 2](https://huggingface.co/stabilityai/stable-diffusion-2) by [Stability AI](https://stability.ai/) (v2-1_768-ema-pruned.ckpt).\n",
11
+ "It uses [Hugging Face](https://huggingface.co/) Diffusers🧨 implementation.\n",
12
+ "\n",
13
+ "Currently supported pipelines are `text-to-image`, `image-to-image`, `inpainting`, `4x upscaling` and `depth-to-image`.\n",
14
+ "\n",
15
+ "<br>\n",
16
+ "\n",
17
+ "Colab by [anzorq](https://twitter.com/hahahahohohe). If you like it, please consider supporting me:\n",
18
+ "\n",
19
+ "[<a href=\"https://www.buymeacoffee.com/anzorq\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" height=\"32px\" width=\"108px\" alt=\"Buy Me A Coffee\"></a>](https://www.buymeacoffee.com/anzorq)\n",
20
+ "<br>\n",
21
+ "[![GitHub Repo stars](https://img.shields.io/github/stars/qunash/stable-diffusion-2-gui?style=social)](https://github.com/qunash/stable-diffusion-2-gui)\n",
22
+ "\n",
23
+ "![visitors](https://visitor-badge.glitch.me/badge?page_id=anzorq.sd-2-colab-header)"
24
+ ]
25
+ },
26
+ {
27
+ "cell_type": "markdown",
28
+ "metadata": {
29
+ "id": "KQI4RX20DW_8"
30
+ },
31
+ "source": [
32
+ "# Install dependencies (~1.5 mins)"
33
+ ]
34
+ },
35
+ {
36
+ "cell_type": "code",
37
+ "execution_count": null,
38
+ "metadata": {
39
+ "cellView": "form",
40
+ "id": "78HoqRAB-cES"
41
+ },
42
+ "outputs": [],
43
+ "source": [
44
+ "!pip install --upgrade git+https://github.com/huggingface/diffusers.git\n",
45
+ "# !pip install diffusers\n",
46
+ "!pip install --upgrade git+https://github.com/huggingface/transformers/\n",
47
+ "# !pip install transformers\n",
48
+ "!pip install accelerate==0.12.0\n",
49
+ "!pip install scipy\n",
50
+ "!pip install ftfy\n",
51
+ "!pip install gradio==3.16.0\n",
52
+ "!git clone https://github.com/qunash/stable-diffusion-2-gui\n",
53
+ "%cd stable-diffusion-2-gui\n",
54
+ "\n",
55
+ "#@markdown ### ⬅️ Run this cell\n",
56
+ "#@markdown ---\n",
57
+ "#@markdown ### Install **xformers**?\n",
58
+ "#@markdown This will take an additional ~3.5 mins.<br>But images will generate 25-40% faster.\n",
59
+ "install_xformers = False #@param {type:\"boolean\"}\n",
60
+ "\n",
61
+ "if install_xformers:\n",
62
+ " import os\n",
63
+ " from subprocess import getoutput\n",
64
+ "\n",
65
+ " os.system(\"pip install --extra-index-url https://download.pytorch.org/whl/cu113 torch torchvision==0.13.1+cu113\")\n",
66
+ " os.system(\"pip install triton==2.0.0.dev20220701\")\n",
67
+ " gpu_info = getoutput('nvidia-smi')\n",
68
+ " if(\"A10G\" in gpu_info):\n",
69
+ " os.system(f\"pip install -q https://github.com/camenduru/stable-diffusion-webui-colab/releases/download/0.0.15/xformers-0.0.15.dev0+4c06c79.d20221205-cp38-cp38-linux_x86_64.whl\")\n",
70
+ " elif(\"T4\" in gpu_info):\n",
71
+ " os.system(f\"pip install -q https://github.com/camenduru/stable-diffusion-webui-colab/releases/download/0.0.15/xformers-0.0.15.dev0+1515f77.d20221130-cp38-cp38-linux_x86_64.whl\")\n",
72
+ "\n",
73
+ "\n",
74
+ "# ### install xformers\n",
75
+ "# from IPython.utils import capture\n",
76
+ "# from subprocess import getoutput\n",
77
+ "# from re import search\n",
78
+ "\n",
79
+ "# with capture.capture_output() as cap:\n",
80
+ " \n",
81
+ "# smi_out = getoutput('nvidia-smi')\n",
82
+ "# supported = search('(T4|P100|V100|A100|K80)', smi_out)\n",
83
+ "\n",
84
+ "# if not supported:\n",
85
+ "# while True:\n",
86
+ "# print(\"\\x1b[1;31mThe current GPU is not supported, try starting a new session.\\x1b[0m\")\n",
87
+ "# else:\n",
88
+ "# supported = supported.group(0)\n",
89
+ "\n",
90
+ "# !pip install -q https://github.com/TheLastBen/fast-stable-diffusion/raw/main/precompiled/{supported}/xformers-0.0.13.dev0-py3-none-any.whl\n",
91
+ "# !pip install -q https://github.com/ShivamShrirao/xformers-wheels/releases/download/4c06c79/xformers-0.0.15.dev0+4c06c79.d20221201-cp38-cp38-linux_x86_64.whl"
92
+ ]
93
+ },
94
+ {
95
+ "cell_type": "markdown",
96
+ "metadata": {
97
+ "id": "OOPHNsFYDbc0"
98
+ },
99
+ "source": [
100
+ "# Run the app"
101
+ ]
102
+ },
103
+ {
104
+ "cell_type": "code",
105
+ "execution_count": null,
106
+ "metadata": {
107
+ "id": "gId0-asCBVwL"
108
+ },
109
+ "outputs": [],
110
+ "source": [
111
+ "#@title ⬇️🖼️\n",
112
+ "from diffusers import StableDiffusionPipeline, StableDiffusionImg2ImgPipeline, StableDiffusionUpscalePipeline, DiffusionPipeline, StableDiffusionDepth2ImgPipeline, DPMSolverMultistepScheduler\n",
113
+ "import gradio as gr\n",
114
+ "import torch\n",
115
+ "from PIL import Image\n",
116
+ "import random\n",
117
+ "\n",
118
+ "state = None\n",
119
+ "current_steps = 25\n",
120
+ "attn_slicing_enabled = True\n",
121
+ "mem_eff_attn_enabled = install_xformers\n",
122
+ "\n",
123
+ "# model_id = 'stabilityai/stable-diffusion-2'\n",
124
+ "model_id = 'stabilityai/stable-diffusion-2-1'\n",
125
+ "\n",
126
+ "scheduler = DPMSolverMultistepScheduler.from_pretrained(model_id, subfolder=\"scheduler\")\n",
127
+ "\n",
128
+ "pipe = StableDiffusionPipeline.from_pretrained(\n",
129
+ " model_id,\n",
130
+ " revision=\"fp16\" if torch.cuda.is_available() else \"fp32\",\n",
131
+ " torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,\n",
132
+ " scheduler=scheduler\n",
133
+ " ).to(\"cuda\")\n",
134
+ "pipe.enable_attention_slicing()\n",
135
+ "if mem_eff_attn_enabled:\n",
136
+ " pipe.enable_xformers_memory_efficient_attention()\n",
137
+ "\n",
138
+ "pipe_i2i = None\n",
139
+ "pipe_upscale = None\n",
140
+ "pipe_inpaint = None\n",
141
+ "pipe_depth2img = None\n",
142
+ "\n",
143
+ "\n",
144
+ "modes = {\n",
145
+ " 'txt2img': 'Text to Image',\n",
146
+ " 'img2img': 'Image to Image',\n",
147
+ " 'inpaint': 'Inpainting',\n",
148
+ " 'upscale4x': 'Upscale 4x',\n",
149
+ " 'depth2img': 'Depth to Image'\n",
150
+ "}\n",
151
+ "current_mode = modes['txt2img']\n",
152
+ "\n",
153
+ "def error_str(error, title=\"Error\"):\n",
154
+ " return f\"\"\"#### {title}\n",
155
+ " {error}\"\"\" if error else \"\"\n",
156
+ "\n",
157
+ "def update_state(new_state):\n",
158
+ " global state\n",
159
+ " state = new_state\n",
160
+ "\n",
161
+ "def update_state_info(old_state):\n",
162
+ " if state and state != old_state:\n",
163
+ " return gr.update(value=state)\n",
164
+ "\n",
165
+ "def set_mem_optimizations(pipe):\n",
166
+ " if attn_slicing_enabled:\n",
167
+ " pipe.enable_attention_slicing()\n",
168
+ " else:\n",
169
+ " pipe.disable_attention_slicing()\n",
170
+ " \n",
171
+ " if mem_eff_attn_enabled:\n",
172
+ " pipe.enable_xformers_memory_efficient_attention()\n",
173
+ " # else:\n",
174
+ " # pipe.disable_xformers_memory_efficient_attention()\n",
175
+ "\n",
176
+ "def get_i2i_pipe(scheduler):\n",
177
+ " \n",
178
+ " update_state(\"Loading image to image model...\")\n",
179
+ "\n",
180
+ " pipe = StableDiffusionImg2ImgPipeline.from_pretrained(\n",
181
+ " model_id,\n",
182
+ " revision=\"fp16\" if torch.cuda.is_available() else \"fp32\",\n",
183
+ " torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,\n",
184
+ " scheduler=scheduler,\n",
185
+ " safety_checker=None,\n",
186
+ " feature_extractor=None\n",
187
+ " )\n",
188
+ " set_mem_optimizations(pipe)\n",
189
+ " pipe.to(\"cuda\")\n",
190
+ " return pipe\n",
191
+ "\n",
192
+ "def get_inpaint_pipe():\n",
193
+ " \n",
194
+ " update_state(\"Loading inpainting model...\")\n",
195
+ "\n",
196
+ " pipe = DiffusionPipeline.from_pretrained(\n",
197
+ " \"stabilityai/stable-diffusion-2-inpainting\",\n",
198
+ " revision=\"fp16\" if torch.cuda.is_available() else \"fp32\",\n",
199
+ " torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,\n",
200
+ " # scheduler=scheduler # TODO currently setting scheduler here messes up the end result. A bug in Diffusers🧨\n",
201
+ " ).to(\"cuda\")\n",
202
+ " pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)\n",
203
+ " # pipe.enable_attention_slicing()\n",
204
+ " # pipe.enable_xformers_memory_efficient_attention()\n",
205
+ " set_mem_optimizations(pipe)\n",
206
+ " return pipe\n",
207
+ "\n",
208
+ "def get_upscale_pipe(scheduler):\n",
209
+ " \n",
210
+ " update_state(\"Loading upscale model...\")\n",
211
+ "\n",
212
+ " pipe = StableDiffusionUpscalePipeline.from_pretrained(\n",
213
+ " \"stabilityai/stable-diffusion-x4-upscaler\",\n",
214
+ " revision=\"fp16\" if torch.cuda.is_available() else \"fp32\",\n",
215
+ " torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,\n",
216
+ " # scheduler=scheduler\n",
217
+ " )\n",
218
+ " # pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)\n",
219
+ " set_mem_optimizations(pipe)\n",
220
+ " pipe.to(\"cuda\")\n",
221
+ " return pipe\n",
222
+ " \n",
223
+ "def get_depth2img_pipe():\n",
224
+ " \n",
225
+ " update_state(\"Loading depth to image model...\")\n",
226
+ "\n",
227
+ " pipe = StableDiffusionDepth2ImgPipeline.from_pretrained(\n",
228
+ " \"stabilityai/stable-diffusion-2-depth\",\n",
229
+ " revision=\"fp16\" if torch.cuda.is_available() else \"fp32\",\n",
230
+ " torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,\n",
231
+ " # scheduler=scheduler\n",
232
+ " )\n",
233
+ " pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)\n",
234
+ " set_mem_optimizations(pipe)\n",
235
+ " pipe.to(\"cuda\")\n",
236
+ " return pipe\n",
237
+ "\n",
238
+ "def switch_attention_slicing(attn_slicing):\n",
239
+ " global attn_slicing_enabled\n",
240
+ " attn_slicing_enabled = attn_slicing\n",
241
+ "\n",
242
+ "def switch_mem_eff_attn(mem_eff_attn):\n",
243
+ " global mem_eff_attn_enabled\n",
244
+ " mem_eff_attn_enabled = mem_eff_attn\n",
245
+ "\n",
246
+ "def pipe_callback(step: int, timestep: int, latents: torch.FloatTensor):\n",
247
+ " update_state(f\"{step}/{current_steps} steps\")#\\nTime left, sec: {timestep/100:.0f}\")\n",
248
+ "\n",
249
+ "def inference(inf_mode, prompt, n_images, guidance, steps, width=768, height=768, seed=0, img=None, strength=0.5, neg_prompt=\"\"):\n",
250
+ "\n",
251
+ " update_state(\" \")\n",
252
+ "\n",
253
+ " global current_mode\n",
254
+ " if inf_mode != current_mode:\n",
255
+ " pipe.to(\"cuda\" if inf_mode == modes['txt2img'] else \"cpu\")\n",
256
+ "\n",
257
+ " if pipe_i2i is not None:\n",
258
+ " pipe_i2i.to(\"cuda\" if inf_mode == modes['img2img'] else \"cpu\")\n",
259
+ "\n",
260
+ " if pipe_inpaint is not None:\n",
261
+ " pipe_inpaint.to(\"cuda\" if inf_mode == modes['inpaint'] else \"cpu\")\n",
262
+ "\n",
263
+ " if pipe_upscale is not None:\n",
264
+ " pipe_upscale.to(\"cuda\" if inf_mode == modes['upscale4x'] else \"cpu\")\n",
265
+ " \n",
266
+ " if pipe_depth2img is not None:\n",
267
+ " pipe_depth2img.to(\"cuda\" if inf_mode == modes['depth2img'] else \"cpu\")\n",
268
+ "\n",
269
+ " current_mode = inf_mode\n",
270
+ " \n",
271
+ " if seed == 0:\n",
272
+ " seed = random.randint(0, 2147483647)\n",
273
+ "\n",
274
+ " generator = torch.Generator('cuda').manual_seed(seed)\n",
275
+ " prompt = prompt\n",
276
+ "\n",
277
+ " try:\n",
278
+ " \n",
279
+ " if inf_mode == modes['txt2img']:\n",
280
+ " return txt_to_img(prompt, n_images, neg_prompt, guidance, steps, width, height, generator, seed), gr.update(visible=False, value=None)\n",
281
+ " \n",
282
+ " elif inf_mode == modes['img2img']:\n",
283
+ " if img is None:\n",
284
+ " return None, gr.update(visible=True, value=error_str(\"Image is required for Image to Image mode\"))\n",
285
+ "\n",
286
+ " return img_to_img(prompt, n_images, neg_prompt, img, strength, guidance, steps, width, height, generator, seed), gr.update(visible=False, value=None)\n",
287
+ " \n",
288
+ " elif inf_mode == modes['inpaint']:\n",
289
+ " if img is None:\n",
290
+ " return None, gr.update(visible=True, value=error_str(\"Image is required for Inpainting mode\"))\n",
291
+ "\n",
292
+ " return inpaint(prompt, n_images, neg_prompt, img, guidance, steps, width, height, generator, seed), gr.update(visible=False, value=None)\n",
293
+ "\n",
294
+ " elif inf_mode == modes['upscale4x']:\n",
295
+ " if img is None:\n",
296
+ " return None, gr.update(visible=True, value=error_str(\"Image is required for Upscale mode\"))\n",
297
+ "\n",
298
+ " return upscale(prompt, n_images, neg_prompt, img, guidance, steps, generator), gr.update(visible=False, value=None)\n",
299
+ "\n",
300
+ " elif inf_mode == modes['depth2img']:\n",
301
+ " if img is None:\n",
302
+ " return None, gr.update(visible=True, value=error_str(\"Image is required for Depth to Image mode\"))\n",
303
+ "\n",
304
+ " return depth2img(prompt, n_images, neg_prompt, img, guidance, steps, generator, seed), gr.update(visible=False, value=None)\n",
305
+ "\n",
306
+ " except Exception as e:\n",
307
+ " return None, gr.update(visible=True, value=error_str(e))\n",
308
+ "\n",
309
+ "def txt_to_img(prompt, n_images, neg_prompt, guidance, steps, width, height, generator, seed):\n",
310
+ "\n",
311
+ " result = pipe(\n",
312
+ " prompt,\n",
313
+ " num_images_per_prompt = n_images,\n",
314
+ " negative_prompt = neg_prompt,\n",
315
+ " num_inference_steps = int(steps),\n",
316
+ " guidance_scale = guidance,\n",
317
+ " width = width,\n",
318
+ " height = height,\n",
319
+ " generator = generator,\n",
320
+ " callback=pipe_callback).images\n",
321
+ "\n",
322
+ " update_state(f\"Done. Seed: {seed}\")\n",
323
+ "\n",
324
+ " return result\n",
325
+ "\n",
326
+ "def img_to_img(prompt, n_images, neg_prompt, img, strength, guidance, steps, width, height, generator, seed):\n",
327
+ "\n",
328
+ " global pipe_i2i\n",
329
+ " if pipe_i2i is None:\n",
330
+ " pipe_i2i = get_i2i_pipe(scheduler)\n",
331
+ "\n",
332
+ " img = img['image']\n",
333
+ " ratio = min(height / img.height, width / img.width)\n",
334
+ " img = img.resize((int(img.width * ratio), int(img.height * ratio)), Image.LANCZOS)\n",
335
+ " result = pipe_i2i(\n",
336
+ " prompt,\n",
337
+ " num_images_per_prompt = n_images,\n",
338
+ " negative_prompt = neg_prompt,\n",
339
+ " image = img,\n",
340
+ " num_inference_steps = int(steps),\n",
341
+ " strength = strength,\n",
342
+ " guidance_scale = guidance,\n",
343
+ " # width = width,\n",
344
+ " # height = height,\n",
345
+ " generator = generator,\n",
346
+ " callback=pipe_callback).images\n",
347
+ "\n",
348
+ " update_state(f\"Done. Seed: {seed}\")\n",
349
+ " \n",
350
+ " return result\n",
351
+ "\n",
352
+ "# TODO Currently supports only 512x512 images\n",
353
+ "def inpaint(prompt, n_images, neg_prompt, img, guidance, steps, width, height, generator, seed):\n",
354
+ "\n",
355
+ " global pipe_inpaint\n",
356
+ " if pipe_inpaint is None:\n",
357
+ " pipe_inpaint = get_inpaint_pipe()\n",
358
+ "\n",
359
+ " inp_img = img['image']\n",
360
+ " mask = img['mask']\n",
361
+ " inp_img = square_padding(inp_img)\n",
362
+ " mask = square_padding(mask)\n",
363
+ "\n",
364
+ " # # ratio = min(height / inp_img.height, width / inp_img.width)\n",
365
+ " # ratio = min(512 / inp_img.height, 512 / inp_img.width)\n",
366
+ " # inp_img = inp_img.resize((int(inp_img.width * ratio), int(inp_img.height * ratio)), Image.LANCZOS)\n",
367
+ " # mask = mask.resize((int(mask.width * ratio), int(mask.height * ratio)), Image.LANCZOS)\n",
368
+ "\n",
369
+ " inp_img = inp_img.resize((512, 512))\n",
370
+ " mask = mask.resize((512, 512))\n",
371
+ "\n",
372
+ " result = pipe_inpaint(\n",
373
+ " prompt,\n",
374
+ " image = inp_img,\n",
375
+ " mask_image = mask,\n",
376
+ " num_images_per_prompt = n_images,\n",
377
+ " negative_prompt = neg_prompt,\n",
378
+ " num_inference_steps = int(steps),\n",
379
+ " guidance_scale = guidance,\n",
380
+ " # width = width,\n",
381
+ " # height = height,\n",
382
+ " generator = generator,\n",
383
+ " callback=pipe_callback).images\n",
384
+ " \n",
385
+ " update_state(f\"Done. Seed: {seed}\")\n",
386
+ "\n",
387
+ " return result\n",
388
+ "\n",
389
+ "def depth2img(prompt, n_images, neg_prompt, img, guidance, steps, generator, seed):\n",
390
+ "\n",
391
+ " global pipe_depth2img\n",
392
+ " if pipe_depth2img is None:\n",
393
+ " pipe_depth2img = get_depth2img_pipe()\n",
394
+ "\n",
395
+ " img = img['image']\n",
396
+ " result = pipe_depth2img(\n",
397
+ " prompt,\n",
398
+ " num_images_per_prompt = n_images,\n",
399
+ " negative_prompt = neg_prompt,\n",
400
+ " image = img,\n",
401
+ " num_inference_steps = int(steps),\n",
402
+ " guidance_scale = guidance,\n",
403
+ " # width = width,\n",
404
+ " # height = height,\n",
405
+ " generator = generator,\n",
406
+ " callback=pipe_callback).images\n",
407
+ "\n",
408
+ " update_state(f\"Done. Seed: {seed}\")\n",
409
+ " \n",
410
+ " return result\n",
411
+ "\n",
412
+ "def square_padding(img):\n",
413
+ " width, height = img.size\n",
414
+ " if width == height:\n",
415
+ " return img\n",
416
+ " new_size = max(width, height)\n",
417
+ " new_img = Image.new('RGB', (new_size, new_size), (0, 0, 0, 255))\n",
418
+ " new_img.paste(img, ((new_size - width) // 2, (new_size - height) // 2))\n",
419
+ " return new_img\n",
420
+ "\n",
421
+ "def upscale(prompt, n_images, neg_prompt, img, guidance, steps, generator):\n",
422
+ "\n",
423
+ " global pipe_upscale\n",
424
+ " if pipe_upscale is None:\n",
425
+ " pipe_upscale = get_upscale_pipe(scheduler)\n",
426
+ "\n",
427
+ " img = img['image']\n",
428
+ " return upscale_tiling(prompt, neg_prompt, img, guidance, steps, generator)\n",
429
+ "\n",
430
+ " # result = pipe_upscale(\n",
431
+ " # prompt,\n",
432
+ " # image = img,\n",
433
+ " # num_inference_steps = int(steps),\n",
434
+ " # guidance_scale = guidance,\n",
435
+ " # negative_prompt = neg_prompt,\n",
436
+ " # num_images_per_prompt = n_images,\n",
437
+ " # generator = generator).images[0]\n",
438
+ "\n",
439
+ " # return result\n",
440
+ "\n",
441
+ "def upscale_tiling(prompt, neg_prompt, img, guidance, steps, generator):\n",
442
+ "\n",
443
+ " width, height = img.size\n",
444
+ "\n",
445
+ " # calculate the padding needed to make the image dimensions a multiple of 128\n",
446
+ " padding_x = 128 - (width % 128) if width % 128 != 0 else 0\n",
447
+ " padding_y = 128 - (height % 128) if height % 128 != 0 else 0\n",
448
+ "\n",
449
+ " # create a white image of the right size to be used as padding\n",
450
+ " padding_img = Image.new('RGB', (padding_x, padding_y), color=(255, 255, 255, 0))\n",
451
+ "\n",
452
+ " # paste the padding image onto the original image to add the padding\n",
453
+ " img.paste(padding_img, (width, height))\n",
454
+ "\n",
455
+ " # update the image dimensions to include the padding\n",
456
+ " width += padding_x\n",
457
+ " height += padding_y\n",
458
+ "\n",
459
+ " if width > 128 or height > 128:\n",
460
+ "\n",
461
+ " num_tiles_x = int(width / 128)\n",
462
+ " num_tiles_y = int(height / 128)\n",
463
+ "\n",
464
+ " upscaled_img = Image.new('RGB', (img.size[0] * 4, img.size[1] * 4))\n",
465
+ " for x in range(num_tiles_x):\n",
466
+ " for y in range(num_tiles_y):\n",
467
+ " update_state(f\"Upscaling tile {x * num_tiles_y + y + 1}/{num_tiles_x * num_tiles_y}\")\n",
468
+ " tile = img.crop((x * 128, y * 128, (x + 1) * 128, (y + 1) * 128))\n",
469
+ "\n",
470
+ " upscaled_tile = pipe_upscale(\n",
471
+ " prompt=\"\",\n",
472
+ " image=tile,\n",
473
+ " num_inference_steps=steps,\n",
474
+ " guidance_scale=guidance,\n",
475
+ " # negative_prompt = neg_prompt,\n",
476
+ " generator=generator,\n",
477
+ " ).images[0]\n",
478
+ "\n",
479
+ " upscaled_img.paste(upscaled_tile, (x * upscaled_tile.size[0], y * upscaled_tile.size[1]))\n",
480
+ "\n",
481
+ " return [upscaled_img]\n",
482
+ " else:\n",
483
+ " return pipe_upscale(\n",
484
+ " prompt=prompt,\n",
485
+ " image=img,\n",
486
+ " num_inference_steps=steps,\n",
487
+ " guidance_scale=guidance,\n",
488
+ " negative_prompt = neg_prompt,\n",
489
+ " generator=generator,\n",
490
+ " ).images\n",
491
+ "\n",
492
+ "\n",
493
+ "\n",
494
+ "def on_mode_change(mode):\n",
495
+ " return gr.update(visible = mode in (modes['img2img'], modes['inpaint'], modes['upscale4x'], modes['depth2img'])), \\\n",
496
+ " gr.update(visible = mode == modes['inpaint']), \\\n",
497
+ " gr.update(visible = mode == modes['upscale4x']), \\\n",
498
+ " gr.update(visible = mode == modes['img2img'])\n",
499
+ "\n",
500
+ "def on_steps_change(steps):\n",
501
+ " global current_steps\n",
502
+ " current_steps = steps\n",
503
+ "\n",
504
+ "with gr.Blocks(css=\"style.css\") as demo:\n",
505
+ " gr.HTML(\n",
506
+ " f\"\"\"\n",
507
+ " <div class=\"main-div\">\n",
508
+ " <div>\n",
509
+ " <h1>Stable Diffusion 2.1</h1>\n",
510
+ " </div><br>\n",
511
+ " <p> Model used: <a href=\"https://huggingface.co/stabilityai/stable-diffusion-2-1/blob/main/v2-1_768-ema-pruned.ckpt\" target=\"_blank\">v2-1_768-ema-pruned.ckpt</a></p>\n",
512
+ " Running on <b>{\"GPU 🔥\" if torch.cuda.is_available() else \"CPU 🥶\"}</b>\n",
513
+ " </div>\n",
514
+ " \"\"\"\n",
515
+ " )\n",
516
+ " with gr.Row():\n",
517
+ " \n",
518
+ " with gr.Column(scale=70):\n",
519
+ " with gr.Group():\n",
520
+ " with gr.Row():\n",
521
+ " prompt = gr.Textbox(label=\"Prompt\", show_label=False, max_lines=2,placeholder=f\"Enter prompt\").style(container=False)\n",
522
+ " generate = gr.Button(value=\"Generate\").style(rounded=(False, True, True, False))\n",
523
+ "\n",
524
+ " gallery = gr.Gallery(label=\"Generated images\", show_label=False).style(grid=[2], height=\"auto\")\n",
525
+ " state_info = gr.Textbox(label=\"State\", show_label=False, max_lines=2).style(container=False)\n",
526
+ " error_output = gr.Markdown(visible=False)\n",
527
+ "\n",
528
+ " with gr.Column(scale=30):\n",
529
+ " inf_mode = gr.Radio(label=\"Inference Mode\", choices=list(modes.values()), value=modes['txt2img'])\n",
530
+ " \n",
531
+ " with gr.Group(visible=False) as i2i_options:\n",
532
+ " image = gr.Image(label=\"Image\", height=128, type=\"pil\", tool='sketch')\n",
533
+ " inpaint_info = gr.Markdown(\"Inpainting resizes and pads images to 512x512\", visible=False)\n",
534
+ " upscale_info = gr.Markdown(\"\"\"Best for small images (128x128 or smaller).<br>\n",
535
+ " Bigger images will be sliced into 128x128 tiles which will be upscaled individually.<br>\n",
536
+ " This is done to avoid running out of GPU memory.\"\"\", visible=False)\n",
537
+ " strength = gr.Slider(label=\"Transformation strength\", minimum=0, maximum=1, step=0.01, value=0.5)\n",
538
+ "\n",
539
+ " with gr.Group():\n",
540
+ " neg_prompt = gr.Textbox(label=\"Negative prompt\", placeholder=\"What to exclude from the image\")\n",
541
+ "\n",
542
+ " n_images = gr.Slider(label=\"Number of images\", value=1, minimum=1, maximum=4, step=1)\n",
543
+ " with gr.Row():\n",
544
+ " guidance = gr.Slider(label=\"Guidance scale\", value=7.5, maximum=15)\n",
545
+ " steps = gr.Slider(label=\"Steps\", value=current_steps, minimum=2, maximum=100, step=1)\n",
546
+ "\n",
547
+ " with gr.Row():\n",
548
+ " width = gr.Slider(label=\"Width\", value=768, minimum=64, maximum=1024, step=8)\n",
549
+ " height = gr.Slider(label=\"Height\", value=768, minimum=64, maximum=1024, step=8)\n",
550
+ "\n",
551
+ " seed = gr.Slider(0, 2147483647, label='Seed (0 = random)', value=0, step=1)\n",
552
+ " with gr.Accordion(\"Memory optimization\"):\n",
553
+ " attn_slicing = gr.Checkbox(label=\"Attention slicing (a bit slower, but uses less memory)\", value=attn_slicing_enabled)\n",
554
+ " # mem_eff_attn = gr.Checkbox(label=\"Memory efficient attention (xformers)\", value=mem_eff_attn_enabled)\n",
555
+ "\n",
556
+ " inf_mode.change(on_mode_change, inputs=[inf_mode], outputs=[i2i_options, inpaint_info, upscale_info, strength], queue=False)\n",
557
+ " steps.change(on_steps_change, inputs=[steps], outputs=[], queue=False)\n",
558
+ " attn_slicing.change(lambda x: switch_attention_slicing(x), inputs=[attn_slicing], queue=False)\n",
559
+ " # mem_eff_attn.change(lambda x: switch_mem_eff_attn(x), inputs=[mem_eff_attn], queue=False)\n",
560
+ "\n",
561
+ " inputs = [inf_mode, prompt, n_images, guidance, steps, width, height, seed, image, strength, neg_prompt]\n",
562
+ " outputs = [gallery, error_output]\n",
563
+ " prompt.submit(inference, inputs=inputs, outputs=outputs)\n",
564
+ " generate.click(inference, inputs=inputs, outputs=outputs)\n",
565
+ "\n",
566
+ " demo.load(update_state_info, inputs=state_info, outputs=state_info, every=0.5, show_progress=False)\n",
567
+ "\n",
568
+ " gr.HTML(\"\"\"\n",
569
+ " <div style=\"border-top: 1px solid #303030;\">\n",
570
+ " <br>\n",
571
+ " <p>Space by: <a href=\"https://twitter.com/hahahahohohe\"><img src=\"https://img.shields.io/twitter/follow/hahahahohohe?label=%40anzorq&style=social\" alt=\"Twitter Follow\"></a></p><br>\n",
572
+ " <p>Enjoying this app? Please consider <a href=\"https://www.buymeacoffee.com/anzorq\">supporting me</a></p>\n",
573
+ " <a href=\"https://www.buymeacoffee.com/anzorq\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png\" alt=\"Buy Me A Coffee\" style=\"height: 45px !important;width: 162px !important;\" ></a><br><br>\n",
574
+ " <a href=\"https://github.com/qunash/stable-diffusion-2-gui\" target=\"_blank\"><img alt=\"GitHub Repo stars\" src=\"https://img.shields.io/github/stars/qunash/stable-diffusion-2-gui?style=social\"></a>\n",
575
+ " <p><img src=\"https://visitor-badge.glitch.me/badge?page_id=anzorq.sd-2-colab\" alt=\"visitors\"></p>\n",
576
+ " </div>\n",
577
+ " \"\"\")\n",
578
+ "\n",
579
+ "demo.queue()\n",
580
+ "demo.launch(debug=True, share=True, height=768)\n"
581
+ ]
582
+ }
583
+ ],
584
+ "metadata": {
585
+ "accelerator": "GPU",
586
+ "colab": {
587
+ "private_outputs": true,
588
+ "provenance": [],
589
+ "toc_visible": true
590
+ },
591
+ "gpuClass": "standard",
592
+ "kernelspec": {
593
+ "display_name": "Python 3",
594
+ "name": "python3"
595
+ },
596
+ "language_info": {
597
+ "name": "python"
598
+ }
599
+ },
600
+ "nbformat": 4,
601
+ "nbformat_minor": 0
602
+ }