├── README.md ├── Stable_Diffusion_English.ipynb └── Stable_Diffusion.ipynb /README.md: -------------------------------------------------------------------------------- 1 |

Всем привет, меня зовут Вадим! 2 |

3 |

А это мой Python скрипт для того чтобы работать с нейросетью Stable Diffusion через сервис Google Colaboratory без платной подписки.

4 | 5 | Открыть в Колабе Русская версия 6 |

7 | Open In Colab English version 8 | 9 |

Typing SVG

10 | 11 | The English version of the manual is located below the Russian version. 12 | 13 |

Инструкция по началу использования скрипта:

14 |
Видео-инструкция:
15 | IMAGE ALT TEXT HERE 16 |
17 |
18 | 19 | Зайдите на сайт Google Colab и импортируйте файл Stable_Diffusion.ipynb нажав Файл --> Открыть блокнот --> Загрузить 20 |

21 | ...либо воспользуйтесь кнопкой "Open in Colab", которая находиться чуть выше на этой странице и тайное волшебство откроет Колаб сразу с нужным блокнотом. ✨ 22 | 23 |

Убедитесь что ваш сеанс будет обрабатываться при помощи видеокарты, нажав Среда выполнения --> Сменить среду выполнения --> T4 GPU. 24 |

25 |
26 | Далее всё что вам остаётся так это просто последовательно запускать блоки кода и в конце концов вы всё таки сгененрируете своих котиков (или что там обычно генерируют люди при помощи нейросетей). Желательно иметь какой-нибудь опыт работы с веб-интерфейсом Stable Diffusion. Если вы новичок, то попробуйте сначала погенерировать изображения на бесплатных сервисах по типу playgroundai.com. А когда вы разберётесь с тем какие вообще модели SD бывают, как устроен Stable Diffusion и его токены, какие есть настройки и как они влияют на генерацию изображений, вам станет легче пользоваться данным скриптом и вы будете чувствовать себя как рыба в воде. 🐟💦 27 |

28 | 29 |

Если у вас есть предложения по правке данного README файла, если вы хотите сообщить о багах в скрипте или у вас есть ещё какие-нибудь вопросы, то пишите мне на E-Mail r4darksoulii@gmail.com.

30 | 31 |

Если хотите меня поддержать, то купите мне чашечку кофе, ☕ https://www.buymeacoffee.com/ran4erep
буду очень вам благодарен. :)

32 | 33 |
34 |
35 |
36 |
1.0.0 - Первая версия скрипта.
37 |
1.1.0 - Добавлен пользовательский интерфейс. Теперь даже не нужно знать что такое переменные в Python. 🙌
38 |
42 |
1.2.0 - Добавлена генерация нескольких изображений за один раз.
43 |
48 |
1.3.0 - Выбор планировщика переехал в блок "Настройка пайплайна", потому что при его смене на работающей моделе колоссально увеличивается потребление оперативной памяти за счёт перезагрузки в неё остальных компонентов пайплайна. Был добавлен выбор стиля. Стили - это заранее заготовленные промпты, которые и создают тот или иной стиль.
49 |
54 |
1.4.0 - Добавлена поддержка image2image.
55 |
59 |
1.5.0 - Добавлена возможность использования моделей с сайта CivitAI. Оперативной памяти Google Colab хватает только на конвертацию 1.5/2.0 моделей, так что XL модели с CivitAI вы использовать не сможете, даже и не пытайтесь. Также добавлена очистка видеопамяти перед каждой генерацией изображения, следовательно ошибок "cuda out of memory" станет меньше.
60 |
67 |
68 | 69 |

English version:

70 | 71 | Go to the Google Colab website and import the Stable_Diffusion_English.ipynb file by clicking File --> Open Notepad --> Upload 72 |

73 | ...or use the "Open in Colab" button just above on this page and the secret magic will open Colab right away with the desired notepad. ✨ 74 | 75 |

Make sure that your session will be handled by the video card by clicking Runtime Environment --> Change Runtime Environment --> T4 GPU. 76 |

77 |
78 | Then all you have to do is just run blocks of code sequentially and eventually you'll end up generating your kitties (or whatever it is that people usually generate with neural networks). It is desirable to have some experience with a Stable Diffusion web interface. If you are a beginner, try generating images on free services like playgroundai.com. And when you understand what SD models there are, how Stable Diffusion and its tokens are organized, what are the settings and how they affect the generation of images, it will be easier to use this script and you will feel yourself like a fish in water. 🐟💦 79 |

80 | 81 |

If you have any suggestions on how to edit this README file, if you want to report bugs in the script or if you have any other questions, then write to me on E-Mail r4darksoulii@gmail.com.

82 | 83 |

If you want to support me, buy me a cup of coffee, ☕ https://www.buymeacoffee.com/ran4erep
would be much appreciated. :)

84 | 85 |
86 |
87 |
88 |
1.0.0 - First version of the script.
89 |
1.1.0 - Added user interface. Now you don't even need to know what variables are in Python. 🙌
90 |
94 |
1.2.0 - Added generation of multiple images at one time.
95 |
100 |
1.3.0 - Scheduler selection moved to the "Pipeline Customization" block, because when changing it on a running model, RAM consumption increases enormously due to reloading of other components of the Pipeline into it. Style selection has been added. Styles are pre-prepared prompts that create a particular style.
101 |
106 |
1.4.0 - Added support for image2image.
107 |
111 |
1.5.0 - Added ability to use models from CivitAI website. Google Colab's RAM is only enough to convert 1.5/2.0 models, so you can't use XL models from CivitAI, don't even try. Also added clearing of video memory before each image generation, hence "cuda out of memory" errors will be fewer.
112 |
116 |
117 | -------------------------------------------------------------------------------- /Stable_Diffusion_English.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "id": "view-in-github", 7 | "colab_type": "text" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": { 16 | "id": "A7l39D9u2_De" 17 | }, 18 | "source": [ 19 | "↑ It is recommended to click File --> Save a copy on Disk\n", 20 | "\n", 21 | "This is needed to keep all the data you have entered. For example, the token for CivitAI site, so you don't have to copy and paste it into the corresponding form every time." 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": null, 27 | "metadata": { 28 | "id": "ZKe1AR4FFMr9" 29 | }, 30 | "outputs": [], 31 | "source": [ 32 | "# @title Stable Diffusion Installing and connecting to Google Drive: { vertical-output: true, form-width: \"10%\", display-mode: \"form\" }\n", 33 | "# @markdown Do you wish to use Google Drive?\n", 34 | "use_gdrive = False # @param {type:\"boolean\"}\n", 35 | "# @markdown\n", 36 | "\n", 37 | "import os\n", 38 | "import re\n", 39 | "import torch\n", 40 | "import gc\n", 41 | "import sys\n", 42 | "import shutil\n", 43 | "from google.colab import files\n", 44 | "from PIL import Image\n", 45 | "import io\n", 46 | "import numpy as np\n", 47 | "from datetime import date\n", 48 | "from datetime import datetime\n", 49 | "from IPython.display import clear_output\n", 50 | "from IPython.display import display, update_display\n", 51 | "import ipywidgets as widgets\n", 52 | "import requests\n", 53 | "from tqdm import tqdm\n", 54 | "from urllib.parse import unquote\n", 55 | "\n", 56 | "if use_gdrive:\n", 57 | " from google.colab import drive\n", 58 | " drive.mount('/content/gdrive')\n", 59 | " print(\"GDrive sucessfully mounted to /content/gdrive\")\n", 60 | " # Создаём папку в Google Drive, если её нет\n", 61 | " if not os.path.exists(\"/content/gdrive/MyDrive/SDOutput\"):\n", 62 | " os.makedirs(\"/content/gdrive/MyDrive/SDOutput\", exist_ok=True)\n", 63 | " print(\"Folder successfully created /content/gdrive/MyDrive/SDOutput\")\n", 64 | "\n", 65 | "#!pip install diffusers[\"torch\"] transformers\n", 66 | "!pip install diffusers\n", 67 | "!pip install accelerate\n", 68 | "!pip install compel\n", 69 | "#!pip install git+https://github.com/huggingface/diffusers\n", 70 | "#!pip install compel --upgrade\n", 71 | "\n", 72 | "from diffusers import AutoPipelineForText2Image, AutoPipelineForImage2Image, AutoPipelineForInpainting\n", 73 | "from diffusers import (\n", 74 | " DDPMScheduler,\n", 75 | " DDIMScheduler,\n", 76 | " PNDMScheduler,\n", 77 | " LMSDiscreteScheduler,\n", 78 | " EulerAncestralDiscreteScheduler,\n", 79 | " EulerDiscreteScheduler,\n", 80 | " DPMSolverMultistepScheduler,\n", 81 | ")\n", 82 | "from diffusers.utils import make_image_grid, load_image\n", 83 | "from compel import Compel, ReturnedEmbeddingsType\n", 84 | "import transformers\n", 85 | "used_models_array = [\"\"]\n", 86 | "\n", 87 | "previous_checkpoint = None\n", 88 | "previous_lora_path = None\n", 89 | "pipe = None\n", 90 | "previous_mode = None\n", 91 | "downloaded_model_name = None\n", 92 | "downloaded_model_basename = None\n", 93 | "downloaded_lora_name = None\n", 94 | "downloaded_lora_basename = None\n", 95 | "current_url = None\n", 96 | "previous_url = None\n", 97 | "lora_url = None\n", 98 | "previous_lora_url = None\n", 99 | "civitai_models = []\n", 100 | "previous_clip_skip = None\n", 101 | "\n", 102 | "clear_output()\n", 103 | "print(\"Installation is complete :)\")" 104 | ] 105 | }, 106 | { 107 | "cell_type": "code", 108 | "execution_count": null, 109 | "metadata": { 110 | "id": "mkHQj8AHJKzr" 111 | }, 112 | "outputs": [], 113 | "source": [ 114 | "# @title Stable Diffusion preparing: { vertical-output: true, form-width: \"10%\", display-mode: \"form\" }\n", 115 | "# @markdown\n", 116 | "# @markdown Models to be loaded into the script:\n", 117 | "# @markdown\n", 118 | "# @markdown [CivitAI](https://civitai.com/models)\n", 119 | "# @markdown\n", 120 | "# @markdown [HuggingFace](https://huggingface.co/models?library=diffusers)\n", 121 | "\n", 122 | "#!nvidia-smi\n", 123 | "\n", 124 | "####################\n", 125 | "# Список опробованных мною моделей:\n", 126 | "# PicX_real: GraydientPlatformAPI/picx-real\n", 127 | "# Juggernaut: digiplay/Juggernaut_final\n", 128 | "# Juggernaut XL: frankjoshua/juggernautXL_version6Rundiffusion\n", 129 | "# RealVisXL 3.0: SG161222/RealVisXL_V3.0_Turbo\n", 130 | "# Base 1.5: runwayml/stable-diffusion-v1-5\n", 131 | "# Base SDXL: stabilityai/stable-diffusion-xl-base-1.0\n", 132 | "# Base SDXL Turbo: stabilityai/sdxl-turbo\n", 133 | "####################\n", 134 | "\n", 135 | "\n", 136 | "# @markdown ---\n", 137 | "# @markdown Your token from the CivitAI website (optional for downloading models from CivitAI that require registration on the website.\n", 138 | "# @markdown\n", 139 | "# @markdown You can get it in the settings of your CivitAI account, in the API Keys block):\n", 140 | "civitai_token = \"\" # @param {type:\"string\"}\n", 141 | "# @markdown Модель для загрузки:\n", 142 | "current_checkpoint = \"\" # @param [\"runwayml/stable-diffusion-v1-5\", \"stabilityai/stable-diffusion-xl-base-1.0\", \"runwayml/stable-diffusion-inpainting\", \"stabilityai/sdxl-turbo\", \"digiplay/Juggernaut_final\", \"GraydientPlatformAPI/picx-real\", \"frankjoshua/juggernautXL_version6Rundiffusion\", \"SG161222/RealVisXL_V3.0_Turbo\", \"SG161222/Realistic_Vision_V6.0_B1_noVAE\", \"stablediffusionapi/lob-realvisxl-v20\"] {allow-input: true}\n", 143 | "# @markdown Use safetensors?\n", 144 | "use_safetensors = True # @param [\"True\", \"False\", \"None\"] {type:\"raw\"}\n", 145 | "\n", 146 | "# @markdown ---\n", 147 | "# @markdown Use LoRA?\n", 148 | "use_lora = False # @param {type:\"boolean\"}\n", 149 | "# @markdown Current LoRA:\n", 150 | "lora_path = \"\" # @param [\"nerijs/pixel-art-xl\", \"ntc-ai/SDXL-LoRA-slider.cinematic-lighting\"] {allow-input: true}\n", 151 | "# @markdown LoRA weights name:\n", 152 | "weight_name = \"\" # @param [\"pixel-art-xl.safetensors\", \"cinematic lighting.safetensors\"] {allow-input: true}\n", 153 | "# @markdown Link to LoRA from website CivitAI:\n", 154 | "lora_url = \"\" # @param {type:\"string\"}\n", 155 | "# @markdown ---\n", 156 | "current_device = \"cuda\"\n", 157 | "# @markdown CLIP skip\n", 158 | "# @markdown (1 means that all layers are used, this is the default value):\n", 159 | "clip_skip = 1 # @param {type:\"slider\", min:1, max:12, step:1}\n", 160 | "## @markdown Вариант:\n", 161 | "#current_variant = \"fp16\" # @param [\"\", \"fp16\", \"ema\"]\n", 162 | "\n", 163 | "display_handle = display(None, display_id=True)\n", 164 | "\n", 165 | "def load_civit_model(url):\n", 166 | " global current_checkpoint, previous_checkpoint, downloaded_model_name, downloaded_model_basename, previous_url, current_url, civitai_models\n", 167 | " for element in civitai_models:\n", 168 | " if current_checkpoint in element[0]:\n", 169 | " current_checkpoint = element[1]\n", 170 | " return\n", 171 | "\n", 172 | " if current_url != previous_url:\n", 173 | " if civitai_token:\n", 174 | " url = url + \"&token=\" + civitai_token\n", 175 | " response = requests.get(url, stream=True)\n", 176 | " total_size_in_bytes = int(response.headers.get('content-length', 0))\n", 177 | " block_size = 100000\n", 178 | " progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)\n", 179 | "\n", 180 | " if 'content-disposition' in response.headers:\n", 181 | " content_disposition = response.headers['content-disposition']\n", 182 | " filename_index = content_disposition.find('filename=')\n", 183 | " if filename_index != -1:\n", 184 | " filename = content_disposition[filename_index + len('filename='):]\n", 185 | " filename = unquote(filename)\n", 186 | " filename = filename.strip('\"')\n", 187 | " downloaded_model_name = filename\n", 188 | " if not downloaded_model_name:\n", 189 | " downloaded_model_name = os.path.basename(url)\n", 190 | "\n", 191 | " downloaded_model_basename, _ = os.path.splitext(downloaded_model_name)\n", 192 | " with open(downloaded_model_name, 'wb') as file:\n", 193 | " for data in response.iter_content(block_size):\n", 194 | " progress_bar.update(len(data))\n", 195 | " file.write(data)\n", 196 | " progress_bar.close()\n", 197 | " if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:\n", 198 | " print(\"Model loading error :(\")\n", 199 | "\n", 200 | " print(\"\\nModel \" + downloaded_model_basename + \" successfully loaded :) \")\n", 201 | " print(\"Wait, model conversion is in progress....\\n\")\n", 202 | "\n", 203 | " from pkg_resources import get_distribution\n", 204 | " diffusers_version = get_distribution('diffusers').version\n", 205 | " lib_url = \"https://raw.githubusercontent.com/huggingface/diffusers/v\" + diffusers_version + \"/scripts/convert_original_stable_diffusion_to_diffusers.py\"\n", 206 | " !wget \"$lib_url\"\n", 207 | "\n", 208 | " !python convert_original_stable_diffusion_to_diffusers.py --checkpoint_path \"$downloaded_model_name\" --dump_path \"$downloaded_model_basename/\" --from_safetensors\n", 209 | " previous_url = current_checkpoint\n", 210 | " current_checkpoint = downloaded_model_basename\n", 211 | " civitai_models.append((url, downloaded_model_basename))\n", 212 | " os.remove(downloaded_model_name)\n", 213 | " os.remove(\"convert_original_stable_diffusion_to_diffusers.py\")\n", 214 | " clear_output()\n", 215 | " print(\"Model \" + downloaded_model_basename + \" successfully converted and ready to work :)\")\n", 216 | "\n", 217 | "repo_regexp = r'[^\\/\\s]+\\s*\\/\\s*[^\\/\\s]+'\n", 218 | "link_regexp = r'^https?://\\S+$'\n", 219 | "\n", 220 | "if re.match(repo_regexp, current_checkpoint):\n", 221 | " current_checkpoint = current_checkpoint\n", 222 | "elif re.match(link_regexp, current_checkpoint):\n", 223 | " current_url = current_checkpoint\n", 224 | " load_civit_model(current_checkpoint)\n", 225 | "else:\n", 226 | " print(\"Could not find the model from your link. :( Please provide a link to the HuggingFace repository of the form \\\"author/model_name\\\" or a direct link to the .safetensors file from the CivitAI website.\")\n", 227 | "\n", 228 | "def flush():\n", 229 | " del(pipe)\n", 230 | " gc.collect()\n", 231 | " torch.cuda.empty_cache()\n", 232 | "\n", 233 | "\n", 234 | "if pipe and not use_lora:\n", 235 | " pipe.unload_lora_weights()\n", 236 | "\n", 237 | "\n", 238 | "def run_chkpt(current_checkpoint, lora_path, use_lora, mode):\n", 239 | " global previous_checkpoint, previous_lora_path, previous_mode, lora_url, previous_lora_url, downloaded_lora_basename, downloaded_lora_name, pipe, clip_skip, previous_clip_skip\n", 240 | " if current_checkpoint != previous_checkpoint or mode != previous_mode or previous_clip_skip != clip_skip:\n", 241 | " used_models_array.append(current_checkpoint)\n", 242 | " print(\"Installing the model...\")\n", 243 | " if clip_skip > 1:\n", 244 | " text_encoder = transformers.CLIPTextModel.from_pretrained(current_checkpoint, subfolder = \"text_encoder\", num_hidden_layers = 12 - (clip_skip - 1), torch_dtype = torch.float16)\n", 245 | " if mode == \"txt2img\":\n", 246 | " if clip_skip > 1:\n", 247 | " pipe = AutoPipelineForText2Image.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors, text_encoder = text_encoder)\n", 248 | " else:\n", 249 | " pipe = AutoPipelineForText2Image.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors)\n", 250 | " if mode == \"img2img\":\n", 251 | " if clip_skip > 1:\n", 252 | " pipe = AutoPipelineForImage2Image.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors, text_encoder = text_encoder)\n", 253 | " else:\n", 254 | " pipe = AutoPipelineForImage2Image.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors)\n", 255 | " if mode == \"inpainting\":\n", 256 | " if clip_skip > 1:\n", 257 | " pipe = AutoPipelineForInpainting.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors, text_encoder = text_encoder)\n", 258 | " else:\n", 259 | " pipe = AutoPipelineForInpainting.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors)\n", 260 | " pipe = pipe.to(current_device)\n", 261 | " pipe.safety_checker = None\n", 262 | " if current_scheduler == \"ddpm\":\n", 263 | " pipe.scheduler = ddpm.from_config(pipe.scheduler.config)\n", 264 | " if current_scheduler == \"ddim\":\n", 265 | " pipe.scheduler = ddim.from_config(pipe.scheduler.config)\n", 266 | " if current_scheduler == \"pndm\":\n", 267 | " pipe.scheduler = pndm.from_config(pipe.scheduler.config)\n", 268 | " if current_scheduler == \"lms\":\n", 269 | " pipe.scheduler = lms.from_config(pipe.scheduler.config)\n", 270 | " if current_scheduler == \"euler\":\n", 271 | " pipe.scheduler = euler.from_config(pipe.scheduler.config)\n", 272 | " if current_scheduler == \"euler_anc\":\n", 273 | " pipe.scheduler = euler_anc.from_config(pipe.scheduler.config)\n", 274 | " if current_scheduler == \"dpm\":\n", 275 | " pipe.scheduler = dpm.from_config(pipe.scheduler.config)\n", 276 | " print(\"Everything is ready to go :)\")\n", 277 | " clear_output()\n", 278 | " previous_mode = mode\n", 279 | " previous_checkpoint = current_checkpoint\n", 280 | " if use_lora:\n", 281 | " if lora_path != previous_lora_path and lora_url == \"\":\n", 282 | " if pipe:\n", 283 | " pipe.unload_lora_weights()\n", 284 | " print(\"Installing LoRA model...\")\n", 285 | " pipe.load_lora_weights(lora_path, weight_name=weight_name)\n", 286 | " print(\"Everything is ready to go :)\")\n", 287 | " previous_lora_path = lora_path\n", 288 | " if lora_url != previous_lora_url and lora_path == \"\" and weight_name == \"\":\n", 289 | " if pipe:\n", 290 | " pipe.unload_lora_weights()\n", 291 | " response = requests.get(lora_url, stream=True)\n", 292 | " total_size_in_bytes = int(response.headers.get('content-length', 0))\n", 293 | " block_size = 100000\n", 294 | " progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)\n", 295 | "\n", 296 | " if 'content-disposition' in response.headers:\n", 297 | " content_disposition = response.headers['content-disposition']\n", 298 | " filename_index = content_disposition.find('filename=')\n", 299 | " if filename_index != -1:\n", 300 | " filename = content_disposition[filename_index + len('filename='):]\n", 301 | " filename = unquote(filename)\n", 302 | " filename = filename.strip('\"')\n", 303 | " downloaded_lora_name = filename\n", 304 | " if not downloaded_lora_name:\n", 305 | " downloaded_lora_name = os.path.basename(lora_url)\n", 306 | "\n", 307 | " downloaded_lora_basename, _ = os.path.splitext(downloaded_lora_name)\n", 308 | " with open(downloaded_lora_name, 'wb') as file:\n", 309 | " for data in response.iter_content(block_size):\n", 310 | " progress_bar.update(len(data))\n", 311 | " file.write(data)\n", 312 | " progress_bar.close()\n", 313 | " if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:\n", 314 | " print(\"Model loading error :(\")\n", 315 | " pipe.load_lora_weights(downloaded_lora_name)\n", 316 | " previous_lora_url = lora_url\n", 317 | " print(\"Everything is ready to go :)\")\n", 318 | "\n", 319 | "\n", 320 | "# print(\"\\nList of models used during the session:\")\n", 321 | "# model_fields = []\n", 322 | "# for i, model_name in enumerate(used_models_array, start=1):\n", 323 | "# if model_name:\n", 324 | "# model_field = widgets.Text(\n", 325 | "# value=model_name,\n", 326 | "# description=f'Model {i-1}:',\n", 327 | "# disabled=False,\n", 328 | "# layout=widgets.Layout(width=\"auto\")\n", 329 | "# )\n", 330 | "# model_fields.append(model_field)\n", 331 | "\n", 332 | "# display(widgets.VBox(model_fields))\n", 333 | "\n", 334 | "# if len(used_models_array) == 1:\n", 335 | "# print(\"So far, the list of models is empty :(\")" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": null, 341 | "metadata": { 342 | "id": "WVG80_y8vCpH" 343 | }, 344 | "outputs": [], 345 | "source": [ 346 | "# @title Setting up the generation parameters: { form-width: \"10%\", display-mode: \"form\" }\n", 347 | "# Здесь указываем переменные для пайплайна Stable Diffusion\n", 348 | "# Дефолтный промпт для лучшего качества: (8k, ultra realistic, highly detailed, cinematic lighting)\n", 349 | "\n", 350 | "# @markdown Prompt:\n", 351 | "prompt = \"werewolf, forest, night\" # @param {type:\"string\"}\n", 352 | "# @markdown Negative prompt:\n", 353 | "negs = \"\" # @param {type:\"string\"}\n", 354 | "# @markdown Generated image style:\n", 355 | "styles = \"No style\" # @param [\"No style\", \"ran4erep's style\", \"3D model\", \"Analog film\", \"Anime\", \"Cinematic\", \"Comic book\", \"Plasticine\", \"Digital art\", \"Fantasy\", \"Isometric\", \"Sketch\", \"Low-poly\", \"Neonpunk\", \"Origami\", \"Photo\", \"Pixel art\", \"Texture\", \"Abstraction\", \"Abstract Expressionism\", \"Hyperrealism\", \"Pop-art\", \"Renaissance\", \"Steampunk\", \"Surrealism\", \"Futurism\", \"Syntwave-futurism\", \"Retro-futurism\", \"Sci-Fi\", \"Vaporwave futurism\", \"Dystopian\", \"Gothic\", \"Grunge\", \"Horror\", \"Lovecraftian\", \"Creepy\", \"Minimalism\", \"Noir\", \"Long exposure\", \"Tilt-Shift\", \"iPhone photo\"]\n", 356 | "# @markdown ---\n", 357 | "\n", 358 | "def latents_to_rgb(latents):\n", 359 | " weights = (\n", 360 | " (60, -60, 25, -70),\n", 361 | " (60, -5, 15, -50),\n", 362 | " (60, 10, -5, -35)\n", 363 | " )\n", 364 | "\n", 365 | " weights_tensor = torch.t(torch.tensor(weights, dtype=latents.dtype).to(latents.device))\n", 366 | " biases_tensor = torch.tensor((150, 140, 130), dtype=latents.dtype).to(latents.device)\n", 367 | " rgb_tensor = torch.einsum(\"...lxy,lr -> ...rxy\", latents, weights_tensor) + biases_tensor.unsqueeze(-1).unsqueeze(-1)\n", 368 | " image_array = rgb_tensor.clamp(0, 255)[0].byte().cpu().numpy()\n", 369 | " image_array = image_array.transpose(1, 2, 0) # Change the order of dimensions\n", 370 | "\n", 371 | " return Image.fromarray(image_array)\n", 372 | "\n", 373 | "def decode_tensors(pipe, step, timestep, callback_kwargs):\n", 374 | " if step % 5 == 0:\n", 375 | " latents = callback_kwargs[\"latents\"]\n", 376 | "\n", 377 | " image = latents_to_rgb(latents)\n", 378 | " image_resized = image.resize((412, 412), Image.NEAREST)\n", 379 | " update_display(image_resized, display_id=display_handle.display_id)\n", 380 | "\n", 381 | " return callback_kwargs\n", 382 | "\n", 383 | "if styles != \"No style\":\n", 384 | " if styles == \"ran4erep's style\":\n", 385 | " prompt = prompt + \", 8k, ultra realistic, highly detailed\"\n", 386 | " negs = negs + \", canvas frame, cartoon, 3d, disfigured, bad art, deformed, extra limbs, close up, b&w, wierd colors, blurry, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, ugly, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, out of frame, ugly, extra limbs, bad anatomy, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, mutated hands, fused fingers, too many fingers, long neck, Photoshop, video game, ugly, tiling, poorly drawn hands, poorly drawn feet, poorly drawn face, out of frame, mutation, mutated, extra limbs, extra legs, extra arms, disfigured, deformed, cross-eye, body out of frame, blurry, bad art, bad anatomy, 3d render\"\n", 387 | " if styles == \"3D model\":\n", 388 | " prompt = \"professional 3d model {\" + prompt + \"} . octane render, highly detailed, volumetric, dramatic lighting\"\n", 389 | " negs = negs + \", ugly, deformed, noisy, low poly, blurry, painting\"\n", 390 | " if styles == \"Analog film\":\n", 391 | " prompt = \"analog film photo {\" + prompt + \"} . faded film, desaturated, 35mm photo, grainy, vignette, vintage, Kodachrome, Lomography, stained, highly detailed, found footage\"\n", 392 | " negs = negs + \", painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured\"\n", 393 | " if styles == \"Anime\":\n", 394 | " prompt = \"anime artwork {\" + prompt + \"} . anime style, key visual, vibrant, studio anime, highly detailed\"\n", 395 | " negs = negs + \", photo, deformed, black and white, realism, disfigured, low contrast\"\n", 396 | " if styles == \"Cinematic\":\n", 397 | " prompt = \"cinematic film still {\" + prompt + \"} . shallow depth of field, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy\"\n", 398 | " negs = negs + \", anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured\"\n", 399 | " if styles == \"Comic book\":\n", 400 | " prompt = \"comic {\" + prompt + \"} . graphic illustration, comic art, graphic novel art, vibrant, highly detailed\"\n", 401 | " negs = negs + \", photograph, deformed, glitch, noisy, realistic, stock photo\"\n", 402 | " if styles == \"Plasticine\":\n", 403 | " prompt = \"play-doh style {\" + prompt + \"} . sculpture, clay art, centered composition, Claymation\"\n", 404 | " negs = negs + \", sloppy, messy, grainy, highly detailed, ultra textured, photo\"\n", 405 | " if styles == \"Digital art\":\n", 406 | " prompt = \"concept art {\" + prompt + \"} . digital artwork, illustrative, painterly, matte painting, highly detailed\"\n", 407 | " negs = negs + \", photo, photorealistic, realism, ugly\"\n", 408 | " if styles == \"Fantasy\":\n", 409 | " prompt = \"ethereal fantasy concept art of {\" + prompt + \"} . magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy\"\n", 410 | " negs = negs + \", photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white\"\n", 411 | " if styles == \"Isometric\":\n", 412 | " prompt = \"isometric style {\" + prompt + \"} . vibrant, beautiful, crisp, detailed, ultra detailed, intricate\"\n", 413 | " negs = negs + \", deformed, mutated, ugly, disfigured, blur, blurry, noise, noisy, realistic, photographic\"\n", 414 | " if styles == \"Sketch\":\n", 415 | " prompt = \"line art drawing {\" + prompt + \"} . professional, sleek, modern, minimalist, graphic, line art, vector graphics\"\n", 416 | " negs = negs + \", anime, photorealistic, 35mm film, deformed, glitch, blurry, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, mutated, realism, realistic, impressionism, expressionism, oil, acrylic\"\n", 417 | " if styles == \"Low-poly\":\n", 418 | " prompt = \"low-poly style {\" + prompt + \"} . low-poly game art, polygon mesh, jagged, blocky, wireframe edges, centered composition\"\n", 419 | " negs = negs + \", noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo\"\n", 420 | " if styles == \"Neonpunk\":\n", 421 | " prompt = \"neonpunk style {\" + prompt + \"} . cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional\"\n", 422 | " negs = negs + \", painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured\"\n", 423 | " if styles == \"Origami\":\n", 424 | " prompt = \"origami style {\" + prompt + \"} . paper art, pleated paper, folded, origami art, pleats, cut and fold, centered composition\"\n", 425 | " negs = negs + \", noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo\"\n", 426 | " if styles == \"Photo\":\n", 427 | " prompt = \"cinematic photo {\" + prompt + \"} . 35mm photograph, film, bokeh, professional, 4k, highly detailed\"\n", 428 | " negs = negs + \", drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly\"\n", 429 | " if styles == \"Pixel art\":\n", 430 | " prompt = \"pixel-art {\" + prompt + \"} . low-res, blocky, pixel art style, 8-bit graphics\"\n", 431 | " negs = negs + \", sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic\"\n", 432 | " if styles == \"Texture\":\n", 433 | " prompt = \"texture {\" + prompt + \"} top down close-up\"\n", 434 | " negs = negs + \", ugly, deformed, noisy, blurry\"\n", 435 | " if styles == \"Abstraction\":\n", 436 | " prompt = \"abstract style {\" + prompt + \"} . non-representational, colors and shapes, expression of feelings, imaginative, highly detailed\"\n", 437 | " negs = negs + \", realistic, photographic, figurative, concrete\"\n", 438 | " if styles == \"Abstract Expressionism\":\n", 439 | " prompt = \"abstract expressionist painting {\" + prompt + \"} . energetic brushwork, bold colors, abstract forms, expressive, emotional\"\n", 440 | " negs = negs + \", realistic, photorealistic, low contrast, plain, simple, monochrome\"\n", 441 | " if styles == \"Hyperrealism\":\n", 442 | " prompt = \"hyperrealistic art {\" + prompt + \"} . extremely high-resolution details, photographic, realism pushed to extreme, fine texture, incredibly lifelike\"\n", 443 | " negs = negs + \", simplified, abstract, unrealistic, impressionistic, low resolution\"\n", 444 | " if styles == \"Pop-art\":\n", 445 | " prompt = \"pop Art style {\" + prompt + \"} . bright colors, bold outlines, popular culture themes, ironic or kitsch\"\n", 446 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, minimalist\"\n", 447 | " if styles == \"Renaissance\":\n", 448 | " prompt = \"renaissance style {\" + prompt + \"} . realistic, perspective, light and shadow, religious or mythological themes, highly detailed\"\n", 449 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, modernist, minimalist, abstract\"\n", 450 | " if styles == \"Steampunk\":\n", 451 | " prompt = \"steampunk style {\" + prompt + \"} . antique, mechanical, brass and copper tones, gears, intricate, detailed\"\n", 452 | " negs = negs + \", deformed, glitch, noisy, low contrast, anime, photorealistic\"\n", 453 | " if styles == \"Surrealism\":\n", 454 | " prompt = \"surrealist art {\" + prompt + \"} . dreamlike, mysterious, provocative, symbolic, intricate, detailed\"\n", 455 | " negs = negs + \", anime, photorealistic, realistic, deformed, glitch, noisy, low contrast\"\n", 456 | " if styles == \"Futurism\":\n", 457 | " prompt = \"futuristic style {\" + prompt + \"} . sleek, modern, ultramodern, high tech, detailed\"\n", 458 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vintage, antique\"\n", 459 | " if styles == \"Syntwave-futurism\":\n", 460 | " prompt = \"retro cyberpunk {\" + prompt + \"} . 80’s inspired, synthwave, neon, vibrant, detailed, retro futurism\"\n", 461 | " negs = negs + \", modern, desaturated, black and white, realism, low contrast\"\n", 462 | " if styles == \"Retro-futurism\":\n", 463 | " prompt = \"retro-futuristic {\" + prompt + \"} . vintage sci-fi, 50s and 60s style, atomic age, vibrant, highly detailed\"\n", 464 | " negs = negs + \", contemporary, realistic, rustic, primitive\"\n", 465 | " if styles == \"Sci-Fi\":\n", 466 | " prompt = \"sci-fi style {\" + prompt + \"} . futuristic, technological, alien worlds, space themes, advanced civilizations\"\n", 467 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, historical, medieval\"\n", 468 | " if styles == \"Vaporwave futurism\":\n", 469 | " prompt = \"vaporwave style {\" + prompt + \"} . retro aesthetic, cyberpunk, vibrant, neon colors, vintage 80s and 90s style, highly detailed\"\n", 470 | " negs = negs + \", monochrome, muted colors, realism, rustic, minimalist, dark\"\n", 471 | " if styles == \"Dystopian\":\n", 472 | " prompt = \"dystopian style {\" + prompt + \"} . bleak, post-apocalyptic, somber, dramatic, highly detailed\"\n", 473 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, cheerful, optimistic, vibrant, colorful\"\n", 474 | " if styles == \"Gothic\":\n", 475 | " prompt = \"gothic style {\" + prompt + \"} . dark, mysterious, haunting, dramatic, ornate, detailed\"\n", 476 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, cheerful, optimistic\"\n", 477 | " if styles == \"Grunge\":\n", 478 | " prompt = \"grunge style {\" + prompt + \"} . textured, distressed, vintage, edgy, punk rock vibe, dirty, noisy\"\n", 479 | " negs = negs + \", smooth, clean, minimalist, sleek, modern, photorealistic\"\n", 480 | " if styles == \"Horror\":\n", 481 | " prompt = \"horror-themed {\" + prompt + \"} . eerie, unsettling, dark, spooky, suspenseful, grim, highly detailed\"\n", 482 | " negs = negs + \", cheerful, bright, vibrant, light-hearted, cute\"\n", 483 | " if styles == \"Lovecraftian\":\n", 484 | " prompt = \"lovecraftian horror {\" + prompt + \"} . eldritch, cosmic horror, unknown, mysterious, surreal, highly detailed\"\n", 485 | " negs = negs + \", light-hearted, mundane, familiar, simplistic, realistic\"\n", 486 | " if styles == \"Creepy\":\n", 487 | " prompt = \"macabre style {\" + prompt + \"} . dark, gothic, grim, haunting, highly detailed\"\n", 488 | " negs = negs + \", bright, cheerful, light-hearted, cartoonish, cute\"\n", 489 | " if styles == \"Minimalism\":\n", 490 | " prompt = \"minimalist style {\" + prompt + \"} . simple, clean, uncluttered, modern, elegant\"\n", 491 | " negs = negs + \", ornate, complicated, highly detailed, cluttered, disordered, messy, noisy\"\n", 492 | " if styles == \"Noir\":\n", 493 | " prompt = \"film noir style {\" + prompt + \"} . monochrome, high contrast, dramatic shadows, 1940s style, mysterious, cinematic\"\n", 494 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vibrant, colorful\"\n", 495 | " if styles == \"Long exposure\":\n", 496 | " prompt = \"long exposure photo of {\" + prompt + \"} . Blurred motion, streaks of light, surreal, dreamy, ghosting effect, highly detailed\"\n", 497 | " negs = negs + \", static, noisy, deformed, shaky, abrupt, flat, low contrast\"\n", 498 | " if styles == \"Tilt-Shift\":\n", 499 | " prompt = \"tilt-shift photo of {\" + prompt + \"} . selective focus, miniature effect, blurred background, highly detailed, vibrant, perspective control\"\n", 500 | " negs = negs + \", blurry, noisy, deformed, flat, low contrast, unrealistic, oversaturated, underexposed\"\n", 501 | " if styles == \"iPhone photo\":\n", 502 | " prompt = \"iphone photo {\" + prompt + \"} . large depth of field, deep depth of field, highly detailed\"\n", 503 | " negs = negs + \", drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, shallow depth of field, bokeh\"\n", 504 | "# @markdown For which Stable Diffusion version you have loaded the model? (It's important for workability tokens weight, otherwise there will be an error)\n", 505 | "sd_type = \"Stable Diffusion 1.5/2.0\" # @param [\"Stable Diffusion 1.5/2.0\", \"Stable Diffusion XL (Turbo)\"]\n", 506 | "# @markdown Token weight for SD 1.5 is written as + or - after the word inside the token: \"cat playing with ball+++++\", \"cat+ playing with ball\"\n", 507 | "# @markdown\n", 508 | "# @markdown The weight for SDXL is written as a fractional number after brackets with a word or even a whole token inside it: \"cat (playing with ball)1.5\"\n", 509 | "# @markdown\n", 510 | "# @markdown ---\n", 511 | "# @markdown Width:\n", 512 | "width = 512 # @param {type:\"number\"}\n", 513 | "# @markdown Height:\n", 514 | "height = 512 # @param {type:\"number\"}\n", 515 | "# @markdown Number of images:\n", 516 | "images_count = 1 # @param {type:\"slider\", min:1, max:10, step:1}\n", 517 | "# @markdown Steps:\n", 518 | "steps = 25 # @param {type:\"number\"}\n", 519 | "# @markdown Guidance scale:\n", 520 | "gscale = 7.5 # @param {type:\"number\"}\n", 521 | "# @markdown Current scheduler:\n", 522 | "current_scheduler = \"euler\" # @param [\"ddpm\", \"ddim\", \"pndm\", \"lms\", \"euler_anc\", \"euler\", \"dpm\"] {type:\"string\"}\n", 523 | "\n", 524 | "# @markdown Use random seed?\n", 525 | "randomness = True # @param {type:\"boolean\"}\n", 526 | "# @markdown Seed:\n", 527 | "seed = 5107167905980673 # @param {type:\"integer\"}" 528 | ] 529 | }, 530 | { 531 | "cell_type": "markdown", 532 | "metadata": { 533 | "id": "Vq2nSTBmoWq-" 534 | }, 535 | "source": [ 536 | "### Run Stable Diffusion\n", 537 | "Do not run this block of code in its entirety. Expand it and you will see the different modes of Stable Diffusion. Run the mode you need." 538 | ] 539 | }, 540 | { 541 | "cell_type": "code", 542 | "execution_count": null, 543 | "metadata": { 544 | "id": "Nl8kcwyOqfd_" 545 | }, 546 | "outputs": [], 547 | "source": [ 548 | "# @title Text2Image: { form-width: \"10%\", display-mode: \"form\" }\n", 549 | "# @markdown\n", 550 | "# @markdown <-- Start generation\n", 551 | "# Генерация картинки\n", 552 | "# @markdown\n", 553 | "# @markdown Show diffusion in real time?\n", 554 | "show_diffusion = True # @param {type:\"boolean\"}\n", 555 | "\n", 556 | "ddpm = DDPMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 557 | "ddim = DDIMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 558 | "pndm = PNDMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 559 | "lms = LMSDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 560 | "euler_anc = EulerAncestralDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 561 | "euler = EulerDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 562 | "dpm = DPMSolverMultistepScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 563 | "\n", 564 | "run_chkpt(current_checkpoint, lora_path, use_lora, \"txt2img\")\n", 565 | "\n", 566 | "if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 567 | " compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)\n", 568 | " prompt_embeds = compel_proc(prompt)\n", 569 | "\n", 570 | "if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 571 | " compel = Compel(\n", 572 | " tokenizer=[pipe.tokenizer, pipe.tokenizer_2] ,\n", 573 | " text_encoder=[pipe.text_encoder, pipe.text_encoder_2],\n", 574 | " returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED,\n", 575 | " requires_pooled=[False, True]\n", 576 | " )\n", 577 | " conditioning, pooled = compel(prompt)\n", 578 | "\n", 579 | "#####################################################################\n", 580 | "# Информация о текущей генерации\n", 581 | "output = [\n", 582 | " \"# Current Stable Diffusion model: \" + current_checkpoint,\n", 583 | "]\n", 584 | "if use_lora:\n", 585 | " if lora_url == \"\" and lora_path and weight_name:\n", 586 | " output.append(\"# Current LoRA model: \" + lora_path)\n", 587 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 588 | " output.append(\"# Current LoRA model: \" + downloaded_lora_basename)\n", 589 | "output.extend([\n", 590 | " \"# Current style: \" + styles,\n", 591 | " \"# Prompt: \" + prompt,\n", 592 | " \"# Negative prompt: \" + negs,\n", 593 | " \"# Resolution: \" + str(width) + \"x\" + str(height),\n", 594 | " \"# Number of generated images: \" + str(images_count)\n", 595 | "])\n", 596 | "max_length_string = max(output, key=len)\n", 597 | "\n", 598 | "print(\"#\" * len(max_length_string) )\n", 599 | "for item in output:\n", 600 | " print(item)\n", 601 | "\n", 602 | "######################################################################\n", 603 | "if not randomness:\n", 604 | " generator = torch.Generator(current_device).manual_seed(seed)\n", 605 | " print(\"# Current generation's seed: \" + str(seed) + \"\\n\" + (\"#\" * len(max_length_string)) )\n", 606 | "elif randomness:\n", 607 | " current_seed = torch.Generator(current_device).seed()\n", 608 | " generator = torch.Generator(current_device).manual_seed(current_seed)\n", 609 | " print(\"# Current generation's seed: \" + str(current_seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 610 | "\n", 611 | "\n", 612 | "#result = pipe(prompt=prompt, height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 613 | "\n", 614 | "if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 615 | " if show_diffusion:\n", 616 | " torch.cuda.empty_cache()\n", 617 | " result = pipe(prompt_embeds=prompt_embeds, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 618 | " else:\n", 619 | " torch.cuda.empty_cache()\n", 620 | " result = pipe(prompt_embeds=prompt_embeds, height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 621 | "\n", 622 | "if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 623 | " if show_diffusion:\n", 624 | " torch.cuda.empty_cache()\n", 625 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 626 | " else:\n", 627 | " torch.cuda.empty_cache()\n", 628 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 629 | "\n", 630 | "# Вывод и сохрарнение результата\n", 631 | "\n", 632 | "if use_gdrive:\n", 633 | " today = str(date.today())\n", 634 | " if not os.path.exists(\"/content/gdrive/MyDrive/SDOutput/\" + today):\n", 635 | " os.makedirs(\"/content/gdrive/MyDrive/SDOutput/\" + today, exist_ok=True)\n", 636 | " for i in range(images_count):\n", 637 | " time = datetime.now()\n", 638 | " time = str(time.strftime(\"%H-%M-%S\"))\n", 639 | " file_name = time + \"_\" + \"seed_\" + str(current_seed) + \"_image\" + str(i) +\".png\"\n", 640 | " file_name = \"/content/gdrive/MyDrive/SDOutput/\" + today + \"/\" + file_name\n", 641 | " images = make_image_grid(result.images, rows=1, cols=images_count)\n", 642 | " result.images[i].save(file_name)\n", 643 | " print(\"Saved as \" + file_name)\n", 644 | "\n", 645 | "clear_output()\n", 646 | "#update_display(result, display_id=display_handle.display_id)\n", 647 | "print(\"#\" * len(max_length_string) )\n", 648 | "print(\"# Current Stable Diffusion model: \" + current_checkpoint)\n", 649 | "if use_lora:\n", 650 | " if lora_url == \"\" and lora_path and weight_name:\n", 651 | " output.append(\"# Current LoRA model: \" + lora_path)\n", 652 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 653 | " output.append(\"# Current LoRA model: \" + downloaded_lora_basename)\n", 654 | "print(\"# Current style: \" + styles)\n", 655 | "print(\"# Prompt: \" + prompt)\n", 656 | "print(\"# Negative prompt: \" + negs)\n", 657 | "print(\"# Resolution: \" + str(width) + \"x\" + str(height))\n", 658 | "print(\"# Number of generated images: \" + str(images_count))\n", 659 | "if not randomness:\n", 660 | " print(\"# Current generation's seed: \" + str(seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 661 | "elif randomness:\n", 662 | " print(\"# Current generation's seed: \" + str(current_seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 663 | "make_image_grid(result.images, rows=1, cols=images_count)" 664 | ] 665 | }, 666 | { 667 | "cell_type": "code", 668 | "execution_count": null, 669 | "metadata": { 670 | "cellView": "form", 671 | "id": "FtAIUUMVO8hS" 672 | }, 673 | "outputs": [], 674 | "source": [ 675 | "# @title Image loading for Image2Image module\n", 676 | "print(\"Pick source image: \")\n", 677 | "init_image = files.upload()\n", 678 | "image_key = list(init_image.keys())[0]\n", 679 | "image_data = init_image[image_key]\n", 680 | "img = Image.open(io.BytesIO(image_data))\n", 681 | "img_width, img_height = img.size" 682 | ] 683 | }, 684 | { 685 | "cell_type": "code", 686 | "execution_count": null, 687 | "metadata": { 688 | "cellView": "form", 689 | "id": "kbebpfrLohQX" 690 | }, 691 | "outputs": [], 692 | "source": [ 693 | "# @title Image2Image:\n", 694 | "# @markdown <-- Start generation\n", 695 | "\n", 696 | "# @markdown ---\n", 697 | "# @markdown Strength:\n", 698 | "\n", 699 | "# @markdown The lower the value, the closer the generation will be to the image you uploaded. The higher the value, the stronger the neural network will be creative.\n", 700 | "\n", 701 | "img2img_strength = 0.3 # @param {type:\"slider\", min:0.1, max:1.0, step:0.1}\n", 702 | "\n", 703 | "# @markdown Strength must be combined with steps. The total number of steps for noise generation is calculated by the formula (Steps * Strength).\n", 704 | "\n", 705 | "# @markdown Steps:\n", 706 | "steps = 25 # @param {type:\"number\"}\n", 707 | "# @markdown ---\n", 708 | "# @markdown Show diffusion in real time?\n", 709 | "show_diffusion = True # @param {type:\"boolean\"}\n", 710 | "# @markdown ---\n", 711 | "\n", 712 | "ddpm = DDPMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 713 | "ddim = DDIMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 714 | "pndm = PNDMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 715 | "lms = LMSDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 716 | "euler_anc = EulerAncestralDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 717 | "euler = EulerDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 718 | "dpm = DPMSolverMultistepScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 719 | "\n", 720 | "run_chkpt(current_checkpoint, lora_path, use_lora, \"img2img\")\n", 721 | "\n", 722 | "\n", 723 | "if init_image:\n", 724 | "\n", 725 | " if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 726 | " compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)\n", 727 | " prompt_embeds = compel_proc(prompt)\n", 728 | "\n", 729 | " if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 730 | " compel = Compel(\n", 731 | " tokenizer=[pipe.tokenizer, pipe.tokenizer_2] ,\n", 732 | " text_encoder=[pipe.text_encoder, pipe.text_encoder_2],\n", 733 | " returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED,\n", 734 | " requires_pooled=[False, True]\n", 735 | " )\n", 736 | " conditioning, pooled = compel(prompt)\n", 737 | "\n", 738 | " output = [\n", 739 | " \"# Current Stable Diffusion model: \" + current_checkpoint,\n", 740 | " ]\n", 741 | " if lora_url == \"\" and lora_path and weight_name:\n", 742 | " output.append(\"# Current LoRA model: \" + lora_path)\n", 743 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 744 | " output.append(\"# Current LoRA model: \" + downloaded_lora_basename)\n", 745 | " output.extend([\n", 746 | " \"# Current style: \" + styles,\n", 747 | " \"# Prompt: \" + prompt,\n", 748 | " \"# Negative prompt: \" + negs,\n", 749 | " \"# Resolution: \" + str(img_width) + \"x\" + str(img_height),\n", 750 | " \"# Strength: \" + str(img2img_strength)\n", 751 | " ])\n", 752 | " max_length_string = max(output, key=len)\n", 753 | "\n", 754 | " print(\"#\" * len(max_length_string) )\n", 755 | " for item in output:\n", 756 | " print(item)\n", 757 | "\n", 758 | " if not randomness:\n", 759 | " generator = torch.Generator(current_device).manual_seed(seed)\n", 760 | " print(\"# Current generation's seed: \" + str(seed) + \"\\n\" + (\"#\" * len(max_length_string)) )\n", 761 | " elif randomness:\n", 762 | " current_seed = torch.Generator(current_device).seed()\n", 763 | " generator = torch.Generator(current_device).manual_seed(current_seed)\n", 764 | " print(\"# Current generation's seed: \" + str(current_seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 765 | "\n", 766 | " if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 767 | " if show_diffusion:\n", 768 | " torch.cuda.empty_cache()\n", 769 | " result = pipe(prompt_embeds=prompt_embeds, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator).images[0]\n", 770 | " else:\n", 771 | " torch.cuda.empty_cache()\n", 772 | " result = pipe(prompt_embeds=prompt_embeds, image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator).images[0]\n", 773 | "\n", 774 | " if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 775 | " if show_diffusion:\n", 776 | " torch.cuda.empty_cache()\n", 777 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator).images[0]\n", 778 | " else:\n", 779 | " torch.cuda.empty_cache()\n", 780 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator).images[0]\n", 781 | "\n", 782 | " clear_output()\n", 783 | " print(\"#\" * len(max_length_string) )\n", 784 | " print(\"# Current Stable Diffusion model: \" + current_checkpoint)\n", 785 | " if use_lora:\n", 786 | " if lora_url == \"\" and lora_path and weight_name:\n", 787 | " output.append(\"# Current LoRA model: \" + lora_path)\n", 788 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 789 | " output.append(\"# Current LoRA model: \" + downloaded_lora_basename)\n", 790 | " print(\"# Current style: \" + styles)\n", 791 | " print(\"# Prompt: \" + prompt)\n", 792 | " print(\"# Negative prompt: \" + negs)\n", 793 | " print(\"# Resolution: \" + str(img_width) + \"x\" + str(img_height))\n", 794 | " print(\"# Strength: \" + str(img2img_strength))\n", 795 | " if not randomness:\n", 796 | " print(\"# Current generation's seed: \" + str(seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 797 | " elif randomness:\n", 798 | " print(\"# Current generation's seed: \" + str(current_seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 799 | "\n", 800 | " if use_gdrive:\n", 801 | " today = str(date.today())\n", 802 | " if not os.path.exists(\"/content/gdrive/MyDrive/SDOutput/\" + today):\n", 803 | " os.makedirs(\"/content/gdrive/MyDrive/SDOutput/\" + today, exist_ok=True)\n", 804 | " time = datetime.now()\n", 805 | " time = str(time.strftime(\"%H-%M-%S\"))\n", 806 | " file_name = time + \"_\" + \"seed_\" + str(current_seed) + \"_image\" + \"_img2imged.png\"\n", 807 | " file_name = \"/content/gdrive/MyDrive/SDOutput/\" + today + \"/\" + file_name\n", 808 | " result.save(file_name)\n", 809 | " print(\"Saved as \" + file_name)\n", 810 | "\n", 811 | " display( make_image_grid([img, result], rows=1, cols=2) )\n", 812 | "else:\n", 813 | " print(\"There is no image to generate from :(\")" 814 | ] 815 | }, 816 | { 817 | "cell_type": "code", 818 | "execution_count": null, 819 | "metadata": { 820 | "cellView": "form", 821 | "id": "x0hV1I-eQTMB" 822 | }, 823 | "outputs": [], 824 | "source": [ 825 | "# @title Image loading for Inpainting module\n", 826 | "print(\"Pick source image: \")\n", 827 | "inpaint_image = files.upload()\n", 828 | "print(\"Pick mask image: \")\n", 829 | "inpaint_mask = files.upload()\n", 830 | "\n", 831 | "inpaint_image_key = list(inpaint_image.keys())[0]\n", 832 | "inpaint_mask_image_key = list(inpaint_mask.keys())[0]\n", 833 | "inpaint_image_data = inpaint_image[inpaint_image_key]\n", 834 | "inpaint_mask_image_data = inpaint_mask[inpaint_mask_image_key]\n", 835 | "inpaint_image = Image.open(io.BytesIO(inpaint_image_data)).convert('RGB')\n", 836 | "inpaint_mask_image = Image.open(io.BytesIO(inpaint_mask_image_data)).convert('RGB')\n", 837 | "inpaint_image_width, inpaint_image_height = inpaint_image.size\n", 838 | "inpaint_image_mask_width, inpaint_image_mask_height = inpaint_mask_image.size" 839 | ] 840 | }, 841 | { 842 | "cell_type": "code", 843 | "execution_count": null, 844 | "metadata": { 845 | "cellView": "form", 846 | "id": "ibVBEYWQo2jQ" 847 | }, 848 | "outputs": [], 849 | "source": [ 850 | "# @title Inpainting:\n", 851 | "# @markdown <-- Start generation\n", 852 | "\n", 853 | "# @markdown ---\n", 854 | "# @markdown Strength:\n", 855 | "\n", 856 | "# @markdown The lower the value, the closer the generation will be to the image you uploaded. The higher the value, the stronger the neural network will be creative.\n", 857 | "\n", 858 | "inpaint_strength = 1 # @param {type:\"slider\", min:0.1, max:1.0, step:0.1}\n", 859 | "\n", 860 | "# @markdown Strength must be combined with steps. The total number of steps for noise generation is calculated by the formula (Steps * Strength).\n", 861 | "\n", 862 | "# @markdown Steps:\n", 863 | "steps = 25 # @param {type:\"number\"}\n", 864 | "# @markdown ---\n", 865 | "# @markdown Show diffusion in real time?\n", 866 | "show_diffusion = True # @param {type:\"boolean\"}\n", 867 | "# @markdown ---\n", 868 | "# @markdown When drawing a mask, remember that black areas are ignored by the neural network, while white areas are not. Blurred white areas in masks is also supported.\n", 869 | "\n", 870 | "ddpm = DDPMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 871 | "ddim = DDIMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 872 | "pndm = PNDMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 873 | "lms = LMSDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 874 | "euler_anc = EulerAncestralDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 875 | "euler = EulerDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 876 | "dpm = DPMSolverMultistepScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 877 | "\n", 878 | "run_chkpt(current_checkpoint, lora_path, use_lora, \"inpainting\")\n", 879 | "\n", 880 | "if inpaint_image and inpaint_mask:\n", 881 | "\n", 882 | " if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 883 | " compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)\n", 884 | " prompt_embeds = compel_proc(prompt)\n", 885 | "\n", 886 | " if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 887 | " compel = Compel(\n", 888 | " tokenizer=[pipe.tokenizer, pipe.tokenizer_2] ,\n", 889 | " text_encoder=[pipe.text_encoder, pipe.text_encoder_2],\n", 890 | " returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED,\n", 891 | " requires_pooled=[False, True]\n", 892 | " )\n", 893 | " conditioning, pooled = compel(prompt)\n", 894 | "\n", 895 | " output = [\n", 896 | " \"# Current Stable Diffusion model: \" + current_checkpoint,\n", 897 | " ]\n", 898 | " if lora_url == \"\" and lora_path and weight_name:\n", 899 | " output.append(\"# Current LoRA model: \" + lora_path)\n", 900 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 901 | " output.append(\"# Current LoRA model: \" + downloaded_lora_basename)\n", 902 | " output.extend([\n", 903 | " \"# Current style: \" + styles,\n", 904 | " \"# Prompt: \" + prompt,\n", 905 | " \"# Negative prompt: \" + negs,\n", 906 | " \"# Source image resolution: \" + str(inpaint_image_width) + \"x\" + str(inpaint_image_height),\n", 907 | " \"# Mask image resolution: \" + str(inpaint_image_mask_width) + \"x\" + str(inpaint_image_mask_height),\n", 908 | " \"# Strength: \" + str(inpaint_strength)\n", 909 | " ])\n", 910 | " max_length_string = max(output, key=len)\n", 911 | "\n", 912 | " print(\"#\" * len(max_length_string) )\n", 913 | " for item in output:\n", 914 | " print(item)\n", 915 | "\n", 916 | " if not randomness:\n", 917 | " generator = torch.Generator(current_device).manual_seed(seed)\n", 918 | " print(\"# Current generation's seed: \" + str(seed) + \"\\n\" + (\"#\" * len(max_length_string)) )\n", 919 | " elif randomness:\n", 920 | " current_seed = torch.Generator(current_device).seed()\n", 921 | " generator = torch.Generator(current_device).manual_seed(current_seed)\n", 922 | " print(\"# Current generation's seed: \" + str(current_seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 923 | "\n", 924 | " if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 925 | " if show_diffusion:\n", 926 | " torch.cuda.empty_cache()\n", 927 | " result = pipe(prompt_embeds=prompt_embeds, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator).images[0]\n", 928 | " else:\n", 929 | " torch.cuda.empty_cache()\n", 930 | " result = pipe(prompt_embeds=prompt_embeds, image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator).images[0]\n", 931 | "\n", 932 | " if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 933 | " if show_diffusion:\n", 934 | " torch.cuda.empty_cache()\n", 935 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator).images[0]\n", 936 | " else:\n", 937 | " torch.cuda.empty_cache()\n", 938 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator).images[0]\n", 939 | "\n", 940 | " clear_output()\n", 941 | " print(\"#\" * len(max_length_string) )\n", 942 | " print(\"# Current Stable Diffusion model: \" + current_checkpoint)\n", 943 | " if use_lora:\n", 944 | " if lora_url == \"\" and lora_path and weight_name:\n", 945 | " output.append(\"# Current LoRA model: \" + lora_path)\n", 946 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 947 | " output.append(\"# Current LoRA model: \" + downloaded_lora_basename)\n", 948 | " print(\"# Current style: \" + styles)\n", 949 | " print(\"# Prompt: \" + prompt)\n", 950 | " print(\"# Negative prompt: \" + negs)\n", 951 | " print(\"# Source image resolution: \" + str(inpaint_image_width) + \"x\" + str(inpaint_image_height) )\n", 952 | " print(\"# Mask image resolution: \" + str(inpaint_image_mask_width) + \"x\" + str(inpaint_image_mask_height) )\n", 953 | " print(\"# Strength: \" + str(inpaint_strength))\n", 954 | " if not randomness:\n", 955 | " print(\"# Current generation's seed: \" + str(seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 956 | " elif randomness:\n", 957 | " print(\"# Current generation's seed: \" + str(current_seed) + \"\\n\" + (\"#\" * len(max_length_string) ))\n", 958 | "\n", 959 | " if use_gdrive:\n", 960 | " today = str(date.today())\n", 961 | " if not os.path.exists(\"/content/gdrive/MyDrive/SDOutput/\" + today):\n", 962 | " os.makedirs(\"/content/gdrive/MyDrive/SDOutput/\" + today, exist_ok=True)\n", 963 | " time = datetime.now()\n", 964 | " time = str(time.strftime(\"%H-%M-%S\"))\n", 965 | " file_name = time + \"_\" + \"seed_\" + str(current_seed) + \"_image\" + \"_inpainted.png\"\n", 966 | " file_name = \"/content/gdrive/MyDrive/SDOutput/\" + today + \"/\" + file_name\n", 967 | " result.save(file_name)\n", 968 | " print(\"Saved as \" + file_name)\n", 969 | "\n", 970 | " display( make_image_grid([inpaint_image, inpaint_mask_image, result], rows=1, cols=3) )\n", 971 | "else:\n", 972 | " print(\"You have canceled the image uploading :(\")" 973 | ] 974 | } 975 | ], 976 | "metadata": { 977 | "accelerator": "GPU", 978 | "colab": { 979 | "provenance": [], 980 | "include_colab_link": true 981 | }, 982 | "kernelspec": { 983 | "display_name": "Python 3", 984 | "name": "python3" 985 | }, 986 | "language_info": { 987 | "name": "python" 988 | } 989 | }, 990 | "nbformat": 4, 991 | "nbformat_minor": 0 992 | } -------------------------------------------------------------------------------- /Stable_Diffusion.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "id": "view-in-github", 7 | "colab_type": "text" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "source": [ 16 | "↑ Желательно нажать Файл --> Сохранить копию на Диске\n", 17 | "\n", 18 | "Это нужно чтобы все введённые вами данные сохранялись. Например токен для сайта CivitAI, чтобы не копировать и не вставлять его в соответсвующее поле каждый раз.\n", 19 | "\n", 20 | "[Видео-инструкция](https://www.youtube.com/embed/VQ3YvX0-9wQ?si=19q0p3cpUpul8lVl)\n", 21 | "\n", 22 | "[Ответы на часто задаваемые вопросы и разъяснения по поводу использования LoRA](https://www.youtube.com/embed/-ZI4TH8fjgM?si=QEGKbNAYzPee5RVE)\n", 23 | "\n", 24 | "[Обновлённая инструкция по версии 1.4.2](https://youtu.be/klMvuBeYGIU?si=sJUFZkgy4ZxH0KJQ)\n", 25 | "\n", 26 | "[Stable Colab 1.5.1: Использование моделей с сайта CivitAI](https://youtu.be/_YtwhJWud40?si=1iPy7uuStUNLa4L3)" 27 | ], 28 | "metadata": { 29 | "id": "A7l39D9u2_De" 30 | } 31 | }, 32 | { 33 | "cell_type": "code", 34 | "execution_count": null, 35 | "metadata": { 36 | "id": "ZKe1AR4FFMr9" 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "# @title Установка Stable Diffusion и подключение Google Drive: { vertical-output: true, form-width: \"10%\", display-mode: \"form\" }\n", 41 | "# @markdown Хотите исользовать Google Drive?\n", 42 | "use_gdrive = False # @param {type:\"boolean\"}\n", 43 | "# @markdown\n", 44 | "\n", 45 | "import os\n", 46 | "import re\n", 47 | "import torch\n", 48 | "import gc\n", 49 | "import sys\n", 50 | "import shutil\n", 51 | "from google.colab import files\n", 52 | "from PIL import Image\n", 53 | "import io\n", 54 | "import numpy as np\n", 55 | "from datetime import date\n", 56 | "from datetime import datetime\n", 57 | "from IPython.display import clear_output\n", 58 | "from IPython.display import display, update_display\n", 59 | "import ipywidgets as widgets\n", 60 | "import requests\n", 61 | "from tqdm import tqdm\n", 62 | "from urllib.parse import unquote\n", 63 | "\n", 64 | "if use_gdrive:\n", 65 | " from google.colab import drive\n", 66 | " drive.mount('/content/gdrive')\n", 67 | " print(\"GDrive sucessfully mounted to /content/gdrive\")\n", 68 | " # Создаём папку в Google Drive, если её нет\n", 69 | " if not os.path.exists(\"/content/gdrive/MyDrive/SDOutput\"):\n", 70 | " os.makedirs(\"/content/gdrive/MyDrive/SDOutput\", exist_ok=True)\n", 71 | " print(\"Успешно создана папка /content/gdrive/MyDrive/SDOutput\")\n", 72 | "\n", 73 | "#!pip install diffusers[\"torch\"] transformers\n", 74 | "!pip install transformers==4.38.2\n", 75 | "!pip install peft==0.10.0\n", 76 | "!pip install diffusers[\"torch\"]==0.27.0\n", 77 | "#!pip install diffusers[\"torch\"] transformers\n", 78 | "!pip install accelerate==0.28.0\n", 79 | "!pip install compel==2.0.2\n", 80 | "#!pip install git+https://github.com/huggingface/diffusers\n", 81 | "#!pip install compel --upgrade\n", 82 | "!pip install easygoogletranslate==0.0.4\n", 83 | "\n", 84 | "from diffusers import AutoPipelineForText2Image, AutoPipelineForImage2Image, AutoPipelineForInpainting\n", 85 | "from diffusers import (\n", 86 | " DDPMScheduler,\n", 87 | " DDIMScheduler,\n", 88 | " PNDMScheduler,\n", 89 | " LMSDiscreteScheduler,\n", 90 | " EulerAncestralDiscreteScheduler,\n", 91 | " EulerDiscreteScheduler,\n", 92 | " DPMSolverMultistepScheduler,\n", 93 | ")\n", 94 | "from diffusers.utils import make_image_grid, load_image\n", 95 | "from compel import Compel, ReturnedEmbeddingsType\n", 96 | "import transformers\n", 97 | "\n", 98 | "from easygoogletranslate import EasyGoogleTranslate\n", 99 | "translator = EasyGoogleTranslate()\n", 100 | "\n", 101 | "used_models_array = [\"\"]\n", 102 | "previous_checkpoint = None\n", 103 | "previous_lora_path = None\n", 104 | "pipe = None\n", 105 | "previous_mode = None\n", 106 | "downloaded_model_name = None\n", 107 | "downloaded_model_basename = None\n", 108 | "downloaded_lora_name = None\n", 109 | "downloaded_lora_basename = None\n", 110 | "current_url = None\n", 111 | "previous_url = None\n", 112 | "lora_url = None\n", 113 | "previous_lora_url = None\n", 114 | "civitai_models = []\n", 115 | "previous_clip_skip = 1\n", 116 | "\n", 117 | "clear_output()\n", 118 | "print(\"Установка завершена :)\")" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "metadata": { 125 | "id": "mkHQj8AHJKzr" 126 | }, 127 | "outputs": [], 128 | "source": [ 129 | "# @title Подготовка Stable Diffusion: { vertical-output: true, form-width: \"10%\", display-mode: \"form\" }\n", 130 | "# @markdown\n", 131 | "# @markdown Модели для загрузки в скрипт:\n", 132 | "# @markdown\n", 133 | "# @markdown [CivitAI](https://civitai.com/models)\n", 134 | "# @markdown\n", 135 | "# @markdown [HuggingFace](https://huggingface.co/models?library=diffusers)\n", 136 | "\n", 137 | "#!nvidia-smi\n", 138 | "\n", 139 | "####################\n", 140 | "# Список опробованных мною моделей:\n", 141 | "# PicX_real: GraydientPlatformAPI/picx-real\n", 142 | "# Juggernaut: digiplay/Juggernaut_final\n", 143 | "# Juggernaut XL: frankjoshua/juggernautXL_version6Rundiffusion\n", 144 | "# RealVisXL 3.0: SG161222/RealVisXL_V3.0_Turbo\n", 145 | "# Base 1.5: runwayml/stable-diffusion-v1-5\n", 146 | "# Base SDXL: stabilityai/stable-diffusion-xl-base-1.0\n", 147 | "# Base SDXL Turbo: stabilityai/sdxl-turbo\n", 148 | "####################\n", 149 | "\n", 150 | "\n", 151 | "# @markdown ---\n", 152 | "# @markdown Ваш токен с сайта CivitAI (опционально, для скачивания моделей с CivitAI, которые требуют регистрацию на сайте.\n", 153 | "# @markdown\n", 154 | "# @markdown Взять его можно в настройках вашего аккаунта CivitAI, в блоке API Keys):\n", 155 | "civitai_token = \"\" # @param {type:\"string\"}\n", 156 | "# @markdown Модель для загрузки:\n", 157 | "current_checkpoint = \"\" # @param [\"runwayml/stable-diffusion-v1-5\", \"stabilityai/stable-diffusion-xl-base-1.0\", \"runwayml/stable-diffusion-inpainting\", \"stabilityai/sdxl-turbo\", \"digiplay/Juggernaut_final\", \"GraydientPlatformAPI/picx-real\", \"frankjoshua/juggernautXL_version6Rundiffusion\", \"SG161222/RealVisXL_V3.0_Turbo\", \"SG161222/Realistic_Vision_V6.0_B1_noVAE\", \"stablediffusionapi/lob-realvisxl-v20\", \"kandinsky-community/kandinsky-2-2-decoder-inpaint\", \"fluently/Fluently-v3-inpainting\"] {allow-input: true}\n", 158 | "# @markdown Использовать safetensors?\n", 159 | "use_safetensors = True # @param [\"True\", \"False\", \"None\"] {type:\"raw\"}\n", 160 | "\n", 161 | "# @markdown ---\n", 162 | "# @markdown Использовать LoRA?\n", 163 | "use_lora = False # @param {type:\"boolean\"}\n", 164 | "# @markdown Текущая LoRA:\n", 165 | "# @markdown ---\n", 166 | "# @markdown Для скачивания с HuggingFace:\n", 167 | "lora_path = \"\" # @param [\"nerijs/pixel-art-xl\", \"ntc-ai/SDXL-LoRA-slider.cinematic-lighting\"] {allow-input: true}\n", 168 | "# @markdown Имя файла LoRA:\n", 169 | "weight_name = \"\" # @param [\"pixel-art-xl.safetensors\", \"cinematic lighting.safetensors\"] {allow-input: true}\n", 170 | "# @markdown ---\n", 171 | "# @markdown Ссылка на LoRA для скачивания с сайта CivitAI:\n", 172 | "lora_url = \"\" # @param {type:\"string\"}\n", 173 | "# @markdown ---\n", 174 | "current_device = \"cuda\"\n", 175 | "# @markdown Пропуск CLIP\n", 176 | "# @markdown (1 означает что используются все слои, это является значением по умолчанию):\n", 177 | "clip_skip = 1 # @param {type:\"slider\", min:1, max:12, step:1}\n", 178 | "## @markdown Вариант:\n", 179 | "#current_variant = \"fp16\" # @param [\"\", \"fp16\", \"ema\"]\n", 180 | "\n", 181 | "display_handle = display(None, display_id=True)\n", 182 | "\n", 183 | "def load_civit_model(url):\n", 184 | " global current_checkpoint, previous_checkpoint, downloaded_model_name, downloaded_model_basename, previous_url, current_url, civitai_models\n", 185 | " for element in civitai_models:\n", 186 | " if current_checkpoint in element[0]:\n", 187 | " current_checkpoint = element[1]\n", 188 | " return\n", 189 | "\n", 190 | " if current_url != previous_url:\n", 191 | " if civitai_token:\n", 192 | " url = url + \"&token=\" + civitai_token\n", 193 | " response = requests.get(url, stream=True)\n", 194 | " total_size_in_bytes = int(response.headers.get('content-length', 0))\n", 195 | " block_size = 100000\n", 196 | " progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)\n", 197 | "\n", 198 | " if 'content-disposition' in response.headers:\n", 199 | " content_disposition = response.headers['content-disposition']\n", 200 | " filename_index = content_disposition.find('filename=')\n", 201 | " if filename_index != -1:\n", 202 | " filename = content_disposition[filename_index + len('filename='):]\n", 203 | " filename = unquote(filename)\n", 204 | " filename = filename.strip('\"')\n", 205 | " downloaded_model_name = filename\n", 206 | " if not downloaded_model_name:\n", 207 | " downloaded_model_name = os.path.basename(url)\n", 208 | "\n", 209 | " downloaded_model_basename, _ = os.path.splitext(downloaded_model_name)\n", 210 | " with open(downloaded_model_name, 'wb') as file:\n", 211 | " for data in response.iter_content(block_size):\n", 212 | " progress_bar.update(len(data))\n", 213 | " file.write(data)\n", 214 | " progress_bar.close()\n", 215 | " if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:\n", 216 | " print(\"Ошибка при скачивании модели :(\")\n", 217 | "\n", 218 | " print(\"\\nМодель \" + downloaded_model_basename + \" успешно загружена :) \")\n", 219 | " print(\"Подождите, идёт конвертация модели...\\n\")\n", 220 | "\n", 221 | " from pkg_resources import get_distribution\n", 222 | " diffusers_version = get_distribution('diffusers').version\n", 223 | " lib_url = \"https://raw.githubusercontent.com/huggingface/diffusers/v\" + diffusers_version + \"/scripts/convert_original_stable_diffusion_to_diffusers.py\"\n", 224 | " !wget \"$lib_url\"\n", 225 | "\n", 226 | " !python convert_original_stable_diffusion_to_diffusers.py --checkpoint_path \"$downloaded_model_name\" --dump_path \"$downloaded_model_basename/\" --from_safetensors\n", 227 | " previous_url = current_checkpoint\n", 228 | " current_checkpoint = downloaded_model_basename\n", 229 | " civitai_models.append((url, downloaded_model_basename))\n", 230 | " os.remove(downloaded_model_name)\n", 231 | " os.remove(\"convert_original_stable_diffusion_to_diffusers.py\")\n", 232 | " clear_output()\n", 233 | " print(\"Модель \" + downloaded_model_basename + \" успешно сконвертирована и готова к работе :)\")\n", 234 | "\n", 235 | "repo_regexp = r'[^\\/\\s]+\\s*\\/\\s*[^\\/\\s]+'\n", 236 | "link_regexp = r'^https?://\\S+$'\n", 237 | "\n", 238 | "if re.match(repo_regexp, current_checkpoint):\n", 239 | " current_checkpoint = current_checkpoint\n", 240 | "elif re.match(link_regexp, current_checkpoint):\n", 241 | " current_url = current_checkpoint\n", 242 | " load_civit_model(current_checkpoint)\n", 243 | "else:\n", 244 | " print(\"Не удалось найти модель по вашей ссылке. :( Укажите ссылку на репозиторий HuggingFace вида \\\"author/model_name\\\" или прямую ссылку на файл .safetensors с сайта CivitAI\")\n", 245 | "\n", 246 | "def flush():\n", 247 | " del(pipe)\n", 248 | " gc.collect()\n", 249 | " torch.cuda.empty_cache()\n", 250 | "\n", 251 | "\n", 252 | "if 'pipe' in locals() and use_lora:\n", 253 | " pipe.unload_lora_weights()\n", 254 | "\n", 255 | "def run_chkpt(current_checkpoint, lora_path, use_lora, mode):\n", 256 | " global previous_checkpoint, previous_lora_path, previous_mode, lora_url, previous_lora_url, downloaded_lora_basename, downloaded_lora_name, pipe, clip_skip, previous_clip_skip\n", 257 | " if current_checkpoint != previous_checkpoint or mode != previous_mode or previous_clip_skip != clip_skip:\n", 258 | " used_models_array.append(current_checkpoint)\n", 259 | " print(\"Устанавливаю модель...\")\n", 260 | " if clip_skip > 1:\n", 261 | " text_encoder = transformers.CLIPTextModel.from_pretrained(current_checkpoint, subfolder = \"text_encoder\", num_hidden_layers = 12 - (clip_skip - 1), torch_dtype = torch.float16)\n", 262 | " if mode == \"txt2img\":\n", 263 | " if clip_skip > 1:\n", 264 | " pipe = AutoPipelineForText2Image.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors, text_encoder = text_encoder)\n", 265 | " else:\n", 266 | " pipe = AutoPipelineForText2Image.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors)\n", 267 | " if mode == \"img2img\":\n", 268 | " if clip_skip > 1:\n", 269 | " pipe = AutoPipelineForImage2Image.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors, text_encoder = text_encoder)\n", 270 | " else:\n", 271 | " pipe = AutoPipelineForImage2Image.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors)\n", 272 | " if mode == \"inpainting\":\n", 273 | " if clip_skip > 1:\n", 274 | " pipe = AutoPipelineForInpainting.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors, text_encoder = text_encoder)\n", 275 | " else:\n", 276 | " pipe = AutoPipelineForInpainting.from_pretrained(current_checkpoint, torch_dtype=torch.float16, use_safetensors=use_safetensors)\n", 277 | " pipe = pipe.to(current_device)\n", 278 | " pipe.safety_checker = None\n", 279 | " if current_scheduler == \"ddpm\":\n", 280 | " pipe.scheduler = ddpm.from_config(pipe.scheduler.config)\n", 281 | " if current_scheduler == \"ddim\":\n", 282 | " pipe.scheduler = ddim.from_config(pipe.scheduler.config)\n", 283 | " if current_scheduler == \"pndm\":\n", 284 | " pipe.scheduler = pndm.from_config(pipe.scheduler.config)\n", 285 | " if current_scheduler == \"lms\":\n", 286 | " pipe.scheduler = lms.from_config(pipe.scheduler.config)\n", 287 | " if current_scheduler == \"euler\":\n", 288 | " pipe.scheduler = euler.from_config(pipe.scheduler.config)\n", 289 | " if current_scheduler == \"euler_anc\":\n", 290 | " pipe.scheduler = euler_anc.from_config(pipe.scheduler.config)\n", 291 | " if current_scheduler == \"dpm\":\n", 292 | " pipe.scheduler = dpm.from_config(pipe.scheduler.config)\n", 293 | " print(\"Всё готово к работе :)\")\n", 294 | " clear_output()\n", 295 | " previous_mode = mode\n", 296 | " previous_checkpoint = current_checkpoint\n", 297 | " previous_clip_skip = clip_skip\n", 298 | " if use_lora:\n", 299 | " if lora_path != previous_lora_path and lora_url == \"\":\n", 300 | " if pipe:\n", 301 | " pipe.unload_lora_weights()\n", 302 | " print(\"Устанавливаю LoRA модель...\")\n", 303 | " pipe.load_lora_weights(lora_path, weight_name=weight_name)\n", 304 | " print(\"Всё готово к работе :)\")\n", 305 | " previous_lora_path = lora_path\n", 306 | " if lora_url != previous_lora_url and lora_path == \"\" and weight_name == \"\":\n", 307 | " if pipe:\n", 308 | " pipe.unload_lora_weights()\n", 309 | " response = requests.get(lora_url, stream=True)\n", 310 | " total_size_in_bytes = int(response.headers.get('content-length', 0))\n", 311 | " block_size = 100000\n", 312 | " progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True)\n", 313 | "\n", 314 | " if 'content-disposition' in response.headers:\n", 315 | " content_disposition = response.headers['content-disposition']\n", 316 | " filename_index = content_disposition.find('filename=')\n", 317 | " if filename_index != -1:\n", 318 | " filename = content_disposition[filename_index + len('filename='):]\n", 319 | " filename = unquote(filename)\n", 320 | " filename = filename.strip('\"')\n", 321 | " downloaded_lora_name = filename\n", 322 | " if not downloaded_lora_name:\n", 323 | " downloaded_lora_name = os.path.basename(lora_url)\n", 324 | "\n", 325 | " downloaded_lora_basename, _ = os.path.splitext(downloaded_lora_name)\n", 326 | " with open(downloaded_lora_name, 'wb') as file:\n", 327 | " for data in response.iter_content(block_size):\n", 328 | " progress_bar.update(len(data))\n", 329 | " file.write(data)\n", 330 | " progress_bar.close()\n", 331 | " if total_size_in_bytes != 0 and progress_bar.n != total_size_in_bytes:\n", 332 | " print(\"Ошибка при скачивании модели :(\")\n", 333 | " pipe.load_lora_weights(downloaded_lora_name)\n", 334 | " previous_lora_url = lora_url\n", 335 | " print(\"Всё готово к работе :)\")\n", 336 | "\n", 337 | "\n", 338 | "# print(\"\\nСписок использованных моделей в течении сессии:\")\n", 339 | "# model_fields = []\n", 340 | "# for i, model_name in enumerate(used_models_array, start=1):\n", 341 | "# if model_name:\n", 342 | "# model_field = widgets.Text(\n", 343 | "# value=model_name,\n", 344 | "# description=f'Модель {i-1}:',\n", 345 | "# disabled=False,\n", 346 | "# layout=widgets.Layout(width=\"auto\")\n", 347 | "# )\n", 348 | "# model_fields.append(model_field)\n", 349 | "\n", 350 | "# display(widgets.VBox(model_fields))\n", 351 | "\n", 352 | "# if len(used_models_array) == 1:\n", 353 | "# print(\"Пока что список моделей пуст :(\")" 354 | ] 355 | }, 356 | { 357 | "cell_type": "code", 358 | "source": [ 359 | "# @title Настройка параметров генерации: { form-width: \"10%\", display-mode: \"form\" }\n", 360 | "# Здесь указываем переменные для пайплайна Stable Diffusion\n", 361 | "# Дефолтный промпт для лучшего качества: (8k, ultra realistic, highly detailed, cinematic lighting)\n", 362 | "\n", 363 | "# @markdown Язык промпта и негативного промпта:\n", 364 | "language = \"English\" # @param [\"English\", \"Русский\", \"Автоопределение\"]\n", 365 | "# @markdown Промпт:\n", 366 | "prompt = \"cute cat\" # @param {type:\"string\"}\n", 367 | "# @markdown Негативный промпт:\n", 368 | "negs = \"\" # @param {type:\"string\"}\n", 369 | "if language == \"Русский\":\n", 370 | " prompt = translator.translate(prompt, source_language='ru', target_language='en')\n", 371 | " negs = translator.translate(negs, source_language='ru', target_language='en')\n", 372 | "elif language == \"Автоопределение\":\n", 373 | " prompt = translator.translate(prompt, target_language='en')\n", 374 | " negs = translator.translate(negs, target_language='en')\n", 375 | "else:\n", 376 | " prompt = prompt\n", 377 | " negs = negs\n", 378 | "\n", 379 | "# @markdown Стиль генерируемого изображения:\n", 380 | "styles = \"Без стиля\" # @param [\"Без стиля\", \"ran4erep's style\", \"3D модель\", \"Аналоговая плёнка\", \"Аниме\", \"Кинематографичный\", \"Комикс\", \"Пластилин\", \"Цифровой арт\", \"Фентези\", \"Изометрический\", \"Набросок\", \"Лоу-поли\", \"Неонпанк\", \"Оригами\", \"Фотография\", \"Пиксель-арт\", \"Текстура\", \"Абстракция\", \"Абстрактный экспрессионизм\", \"Гиперреализм\", \"Поп-арт\", \"Ренесанс\", \"Стимпанк\", \"Сюрреализм\", \"Футуризм\", \"Синтвейв-футуризм\", \"Ретро-футуризм\", \"Сай-фай\", \"Вапорвейв-футуризм\", \"Антиутопический\", \"Готический\", \"Гранж\", \"Хоррор\", \"Лавкрафтовский\", \"Жуткий\", \"Минимализм\", \"Нуар\", \"Длинная выдержка\", \"Tilt-Shift\", \"Фото со смартфона\"]\n", 381 | "# @markdown ---\n", 382 | "\n", 383 | "def latents_to_rgb(latents):\n", 384 | " weights = (\n", 385 | " (60, -60, 25, -70),\n", 386 | " (60, -5, 15, -50),\n", 387 | " (60, 10, -5, -35)\n", 388 | " )\n", 389 | "\n", 390 | " weights_tensor = torch.t(torch.tensor(weights, dtype=latents.dtype).to(latents.device))\n", 391 | " biases_tensor = torch.tensor((150, 140, 130), dtype=latents.dtype).to(latents.device)\n", 392 | " rgb_tensor = torch.einsum(\"...lxy,lr -> ...rxy\", latents, weights_tensor) + biases_tensor.unsqueeze(-1).unsqueeze(-1)\n", 393 | " image_array = rgb_tensor.clamp(0, 255)[0].byte().cpu().numpy()\n", 394 | " image_array = image_array.transpose(1, 2, 0) # Change the order of dimensions\n", 395 | "\n", 396 | " return Image.fromarray(image_array)\n", 397 | "\n", 398 | "def decode_tensors(pipe, step, timestep, callback_kwargs):\n", 399 | " if step % 5 == 0:\n", 400 | " latents = callback_kwargs[\"latents\"]\n", 401 | "\n", 402 | " image = latents_to_rgb(latents)\n", 403 | " image_resized = image.resize((412, 412), Image.NEAREST)\n", 404 | " update_display(image_resized, display_id=display_handle.display_id)\n", 405 | "\n", 406 | " return callback_kwargs\n", 407 | "\n", 408 | "if styles != \"Без стиля\":\n", 409 | " if styles == \"ran4erep's style\":\n", 410 | " prompt = prompt + \", 8k, ultra realistic, highly detailed\"\n", 411 | " negs = negs + \", canvas frame, cartoon, 3d, disfigured, bad art, deformed, extra limbs, close up, b&w, wierd colors, blurry, duplicate, morbid, mutilated, out of frame, extra fingers, mutated hands, poorly drawn hands, poorly drawn face, mutation, deformed, ugly, blurry, bad anatomy, bad proportions, extra limbs, cloned face, disfigured, out of frame, ugly, extra limbs, bad anatomy, gross proportions, malformed limbs, missing arms, missing legs, extra arms, extra legs, mutated hands, fused fingers, too many fingers, long neck, Photoshop, video game, ugly, tiling, poorly drawn hands, poorly drawn feet, poorly drawn face, out of frame, mutation, mutated, extra limbs, extra legs, extra arms, disfigured, deformed, cross-eye, body out of frame, blurry, bad art, bad anatomy, 3d render\"\n", 412 | " if styles == \"3D модель\":\n", 413 | " prompt = \"professional 3d model {\" + prompt + \"} . octane render, highly detailed, volumetric, dramatic lighting\"\n", 414 | " negs = negs + \", ugly, deformed, noisy, low poly, blurry, painting\"\n", 415 | " if styles == \"Аналоговая плёнка\":\n", 416 | " prompt = \"analog film photo {\" + prompt + \"} . faded film, desaturated, 35mm photo, grainy, vignette, vintage, Kodachrome, Lomography, stained, highly detailed, found footage\"\n", 417 | " negs = negs + \", painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured\"\n", 418 | " if styles == \"Аниме\":\n", 419 | " prompt = \"anime artwork {\" + prompt + \"} . anime style, key visual, vibrant, studio anime, highly detailed\"\n", 420 | " negs = negs + \", photo, deformed, black and white, realism, disfigured, low contrast\"\n", 421 | " if styles == \"Кинематографичный\":\n", 422 | " prompt = \"cinematic film still {\" + prompt + \"} . shallow depth of field, vignette, highly detailed, high budget, bokeh, cinemascope, moody, epic, gorgeous, film grain, grainy\"\n", 423 | " negs = negs + \", anime, cartoon, graphic, text, painting, crayon, graphite, abstract, glitch, deformed, mutated, ugly, disfigured\"\n", 424 | " if styles == \"Комикс\":\n", 425 | " prompt = \"comic {\" + prompt + \"} . graphic illustration, comic art, graphic novel art, vibrant, highly detailed\"\n", 426 | " negs = negs + \", photograph, deformed, glitch, noisy, realistic, stock photo\"\n", 427 | " if styles == \"Пластилин\":\n", 428 | " prompt = \"play-doh style {\" + prompt + \"} . sculpture, clay art, centered composition, Claymation\"\n", 429 | " negs = negs + \", sloppy, messy, grainy, highly detailed, ultra textured, photo\"\n", 430 | " if styles == \"Цифровой арт\":\n", 431 | " prompt = \"concept art {\" + prompt + \"} . digital artwork, illustrative, painterly, matte painting, highly detailed\"\n", 432 | " negs = negs + \", photo, photorealistic, realism, ugly\"\n", 433 | " if styles == \"Фентези\":\n", 434 | " prompt = \"ethereal fantasy concept art of {\" + prompt + \"} . magnificent, celestial, ethereal, painterly, epic, majestic, magical, fantasy art, cover art, dreamy\"\n", 435 | " negs = negs + \", photographic, realistic, realism, 35mm film, dslr, cropped, frame, text, deformed, glitch, noise, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, sloppy, duplicate, mutated, black and white\"\n", 436 | " if styles == \"Изометрический\":\n", 437 | " prompt = \"isometric style {\" + prompt + \"} . vibrant, beautiful, crisp, detailed, ultra detailed, intricate\"\n", 438 | " negs = negs + \", deformed, mutated, ugly, disfigured, blur, blurry, noise, noisy, realistic, photographic\"\n", 439 | " if styles == \"Набросок\":\n", 440 | " prompt = \"line art drawing {\" + prompt + \"} . professional, sleek, modern, minimalist, graphic, line art, vector graphics\"\n", 441 | " negs = negs + \", anime, photorealistic, 35mm film, deformed, glitch, blurry, noisy, off-center, deformed, cross-eyed, closed eyes, bad anatomy, ugly, disfigured, mutated, realism, realistic, impressionism, expressionism, oil, acrylic\"\n", 442 | " if styles == \"Лоу-поли\":\n", 443 | " prompt = \"low-poly style {\" + prompt + \"} . low-poly game art, polygon mesh, jagged, blocky, wireframe edges, centered composition\"\n", 444 | " negs = negs + \", noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo\"\n", 445 | " if styles == \"Неонпанк\":\n", 446 | " prompt = \"neonpunk style {\" + prompt + \"} . cyberpunk, vaporwave, neon, vibes, vibrant, stunningly beautiful, crisp, detailed, sleek, ultramodern, magenta highlights, dark purple shadows, high contrast, cinematic, ultra detailed, intricate, professional\"\n", 447 | " negs = negs + \", painting, drawing, illustration, glitch, deformed, mutated, cross-eyed, ugly, disfigured\"\n", 448 | " if styles == \"Оригами\":\n", 449 | " prompt = \"origami style {\" + prompt + \"} . paper art, pleated paper, folded, origami art, pleats, cut and fold, centered composition\"\n", 450 | " negs = negs + \", noisy, sloppy, messy, grainy, highly detailed, ultra textured, photo\"\n", 451 | " if styles == \"Фотография\":\n", 452 | " prompt = \"cinematic photo {\" + prompt + \"} . 35mm photograph, film, bokeh, professional, 4k, highly detailed\"\n", 453 | " negs = negs + \", drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly\"\n", 454 | " if styles == \"Пиксель-арт\":\n", 455 | " prompt = \"pixel-art {\" + prompt + \"} . low-res, blocky, pixel art style, 8-bit graphics\"\n", 456 | " negs = negs + \", sloppy, messy, blurry, noisy, highly detailed, ultra textured, photo, realistic\"\n", 457 | " if styles == \"Текстура\":\n", 458 | " prompt = \"texture {\" + prompt + \"} top down close-up\"\n", 459 | " negs = negs + \", ugly, deformed, noisy, blurry\"\n", 460 | " if styles == \"Абстракция\":\n", 461 | " prompt = \"abstract style {\" + prompt + \"} . non-representational, colors and shapes, expression of feelings, imaginative, highly detailed\"\n", 462 | " negs = negs + \", realistic, photographic, figurative, concrete\"\n", 463 | " if styles == \"Абстрактный экспрессионизм\":\n", 464 | " prompt = \"abstract expressionist painting {\" + prompt + \"} . energetic brushwork, bold colors, abstract forms, expressive, emotional\"\n", 465 | " negs = negs + \", realistic, photorealistic, low contrast, plain, simple, monochrome\"\n", 466 | " if styles == \"Гиперреализм\":\n", 467 | " prompt = \"hyperrealistic art {\" + prompt + \"} . extremely high-resolution details, photographic, realism pushed to extreme, fine texture, incredibly lifelike\"\n", 468 | " negs = negs + \", simplified, abstract, unrealistic, impressionistic, low resolution\"\n", 469 | " if styles == \"Поп-арт\":\n", 470 | " prompt = \"pop Art style {\" + prompt + \"} . bright colors, bold outlines, popular culture themes, ironic or kitsch\"\n", 471 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, minimalist\"\n", 472 | " if styles == \"Ренесанс\":\n", 473 | " prompt = \"renaissance style {\" + prompt + \"} . realistic, perspective, light and shadow, religious or mythological themes, highly detailed\"\n", 474 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, modernist, minimalist, abstract\"\n", 475 | " if styles == \"Стимпанк\":\n", 476 | " prompt = \"steampunk style {\" + prompt + \"} . antique, mechanical, brass and copper tones, gears, intricate, detailed\"\n", 477 | " negs = negs + \", deformed, glitch, noisy, low contrast, anime, photorealistic\"\n", 478 | " if styles == \"Сюрреализм\":\n", 479 | " prompt = \"surrealist art {\" + prompt + \"} . dreamlike, mysterious, provocative, symbolic, intricate, detailed\"\n", 480 | " negs = negs + \", anime, photorealistic, realistic, deformed, glitch, noisy, low contrast\"\n", 481 | " if styles == \"Футуризм\":\n", 482 | " prompt = \"futuristic style {\" + prompt + \"} . sleek, modern, ultramodern, high tech, detailed\"\n", 483 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vintage, antique\"\n", 484 | " if styles == \"Синтвейв-футуризм\":\n", 485 | " prompt = \"retro cyberpunk {\" + prompt + \"} . 80’s inspired, synthwave, neon, vibrant, detailed, retro futurism\"\n", 486 | " negs = negs + \", modern, desaturated, black and white, realism, low contrast\"\n", 487 | " if styles == \"Ретро-футуризм\":\n", 488 | " prompt = \"retro-futuristic {\" + prompt + \"} . vintage sci-fi, 50s and 60s style, atomic age, vibrant, highly detailed\"\n", 489 | " negs = negs + \", contemporary, realistic, rustic, primitive\"\n", 490 | " if styles == \"Сай-фай\":\n", 491 | " prompt = \"sci-fi style {\" + prompt + \"} . futuristic, technological, alien worlds, space themes, advanced civilizations\"\n", 492 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, historical, medieval\"\n", 493 | " if styles == \"Вапорвейв-футуризм\":\n", 494 | " prompt = \"vaporwave style {\" + prompt + \"} . retro aesthetic, cyberpunk, vibrant, neon colors, vintage 80s and 90s style, highly detailed\"\n", 495 | " negs = negs + \", monochrome, muted colors, realism, rustic, minimalist, dark\"\n", 496 | " if styles == \"Антиутопический\":\n", 497 | " prompt = \"dystopian style {\" + prompt + \"} . bleak, post-apocalyptic, somber, dramatic, highly detailed\"\n", 498 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, cheerful, optimistic, vibrant, colorful\"\n", 499 | " if styles == \"Готический\":\n", 500 | " prompt = \"gothic style {\" + prompt + \"} . dark, mysterious, haunting, dramatic, ornate, detailed\"\n", 501 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, cheerful, optimistic\"\n", 502 | " if styles == \"Гранж\":\n", 503 | " prompt = \"grunge style {\" + prompt + \"} . textured, distressed, vintage, edgy, punk rock vibe, dirty, noisy\"\n", 504 | " negs = negs + \", smooth, clean, minimalist, sleek, modern, photorealistic\"\n", 505 | " if styles == \"Хоррор\":\n", 506 | " prompt = \"horror-themed {\" + prompt + \"} . eerie, unsettling, dark, spooky, suspenseful, grim, highly detailed\"\n", 507 | " negs = negs + \", cheerful, bright, vibrant, light-hearted, cute\"\n", 508 | " if styles == \"Лавкрафтовский\":\n", 509 | " prompt = \"lovecraftian horror {\" + prompt + \"} . eldritch, cosmic horror, unknown, mysterious, surreal, highly detailed\"\n", 510 | " negs = negs + \", light-hearted, mundane, familiar, simplistic, realistic\"\n", 511 | " if styles == \"Жуткий\":\n", 512 | " prompt = \"macabre style {\" + prompt + \"} . dark, gothic, grim, haunting, highly detailed\"\n", 513 | " negs = negs + \", bright, cheerful, light-hearted, cartoonish, cute\"\n", 514 | " if styles == \"Минимализм\":\n", 515 | " prompt = \"minimalist style {\" + prompt + \"} . simple, clean, uncluttered, modern, elegant\"\n", 516 | " negs = negs + \", ornate, complicated, highly detailed, cluttered, disordered, messy, noisy\"\n", 517 | " if styles == \"Нуар\":\n", 518 | " prompt = \"film noir style {\" + prompt + \"} . monochrome, high contrast, dramatic shadows, 1940s style, mysterious, cinematic\"\n", 519 | " negs = negs + \", ugly, deformed, noisy, blurry, low contrast, realism, photorealistic, vibrant, colorful\"\n", 520 | " if styles == \"Длинная выдержка\":\n", 521 | " prompt = \"long exposure photo of {\" + prompt + \"} . Blurred motion, streaks of light, surreal, dreamy, ghosting effect, highly detailed\"\n", 522 | " negs = negs + \", static, noisy, deformed, shaky, abrupt, flat, low contrast\"\n", 523 | " if styles == \"Tilt-Shift\":\n", 524 | " prompt = \"tilt-shift photo of {\" + prompt + \"} . selective focus, miniature effect, blurred background, highly detailed, vibrant, perspective control\"\n", 525 | " negs = negs + \", blurry, noisy, deformed, flat, low contrast, unrealistic, oversaturated, underexposed\"\n", 526 | " if styles == \"Фото со смартфона\":\n", 527 | " prompt = \"iphone photo {\" + prompt + \"} . large depth of field, deep depth of field, highly detailed\"\n", 528 | " negs = negs + \", drawing, painting, crayon, sketch, graphite, impressionist, noisy, blurry, soft, deformed, ugly, shallow depth of field, bokeh\"\n", 529 | "# @markdown Для какой версии Stable Diffusion вы загрузили модель? (Это важно для работоспособности веса токенов, иначе будет ошибка)\n", 530 | "sd_type = \"Stable Diffusion 1.5/2.0\" # @param [\"Stable Diffusion 1.5/2.0\", \"Stable Diffusion XL (Turbo)\", \"Отключить веса токенов (для совместимости)\"]\n", 531 | "# @markdown Вес для SD 1.5 записывается как + или - после слова внутри токена: \"cat playing with ball+++++\", \"cat+ playing with ball\"\n", 532 | "# @markdown\n", 533 | "# @markdown Вес для SDXL записывается как дробное число после скобок, внутри которых есть слово или даже целый токен: \"cat (playing with ball)1.5\"\n", 534 | "# @markdown\n", 535 | "# @markdown ---\n", 536 | "# @markdown Ширина:\n", 537 | "width = 512 # @param {type:\"number\"}\n", 538 | "# @markdown Высота:\n", 539 | "height = 512 # @param {type:\"number\"}\n", 540 | "# @markdown Количество изображений:\n", 541 | "images_count = 2 # @param {type:\"slider\", min:1, max:10, step:1}\n", 542 | "# @markdown Шаги:\n", 543 | "steps = 25 # @param {type:\"number\"}\n", 544 | "# @markdown Шкала инструкции:\n", 545 | "gscale = 7.5 # @param {type:\"number\"}\n", 546 | "# @markdown Текущий планировщик:\n", 547 | "current_scheduler = \"euler_anc\" # @param [\"ddpm\", \"ddim\", \"pndm\", \"lms\", \"euler_anc\", \"euler\", \"dpm\"] {type:\"string\"}\n", 548 | "\n", 549 | "if pipe in globals() or pipe is not None:\n", 550 | " if current_scheduler == \"ddpm\":\n", 551 | " pipe.scheduler = ddpm.from_config(pipe.scheduler.config)\n", 552 | " if current_scheduler == \"ddim\":\n", 553 | " pipe.scheduler = ddim.from_config(pipe.scheduler.config)\n", 554 | " if current_scheduler == \"pndm\":\n", 555 | " pipe.scheduler = pndm.from_config(pipe.scheduler.config)\n", 556 | " if current_scheduler == \"lms\":\n", 557 | " pipe.scheduler = lms.from_config(pipe.scheduler.config)\n", 558 | " if current_scheduler == \"euler\":\n", 559 | " pipe.scheduler = euler.from_config(pipe.scheduler.config)\n", 560 | " if current_scheduler == \"euler_anc\":\n", 561 | " pipe.scheduler = euler_anc.from_config(pipe.scheduler.config)\n", 562 | " if current_scheduler == \"dpm\":\n", 563 | " pipe.scheduler = dpm.from_config(pipe.scheduler.config)\n", 564 | "\n", 565 | "# @markdown Использовать случайный seed?\n", 566 | "randomness = True # @param {type:\"boolean\"}\n", 567 | "# @markdown Seed:\n", 568 | "seed = 1171722174033674 # @param {type:\"integer\"}" 569 | ], 570 | "metadata": { 571 | "id": "WVG80_y8vCpH" 572 | }, 573 | "execution_count": null, 574 | "outputs": [] 575 | }, 576 | { 577 | "cell_type": "markdown", 578 | "source": [ 579 | "### Работа Stable Diffusion\n", 580 | "Не запускайте этот блок кода целиком. Разверните его и вы увидите различные режимы работы Stable Diffusion. Запустите нужный вам режим." 581 | ], 582 | "metadata": { 583 | "id": "Vq2nSTBmoWq-" 584 | } 585 | }, 586 | { 587 | "cell_type": "code", 588 | "source": [ 589 | "# @title Text2Image (Генерация изображения из текста): { form-width: \"10%\", display-mode: \"form\" }\n", 590 | "# @markdown\n", 591 | "# @markdown <-- Начать генерацию\n", 592 | "# Генерация картинки\n", 593 | "# @markdown\n", 594 | "# @markdown Показывать диффузию в реальном времени?\n", 595 | "show_diffusion = True # @param {type:\"boolean\"}\n", 596 | "\n", 597 | "ddpm = DDPMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 598 | "ddim = DDIMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 599 | "pndm = PNDMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 600 | "lms = LMSDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 601 | "euler_anc = EulerAncestralDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 602 | "euler = EulerDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 603 | "dpm = DPMSolverMultistepScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 604 | "\n", 605 | "run_chkpt(current_checkpoint, lora_path, use_lora, \"txt2img\")\n", 606 | "\n", 607 | "if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 608 | " compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)\n", 609 | " prompt_embeds = compel_proc(prompt)\n", 610 | "\n", 611 | "if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 612 | " compel = Compel(\n", 613 | " tokenizer=[pipe.tokenizer, pipe.tokenizer_2] ,\n", 614 | " text_encoder=[pipe.text_encoder, pipe.text_encoder_2],\n", 615 | " returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED,\n", 616 | " requires_pooled=[False, True]\n", 617 | " )\n", 618 | " conditioning, pooled = compel(prompt)\n", 619 | "\n", 620 | "#####################################################################\n", 621 | "# Информация о текущей генерации\n", 622 | "prompt_display = '\\n'.join([prompt[i:i+60] for i in range(0, len(prompt), 60)])\n", 623 | "negs_display = '\\n'.join([negs[i:i+60] for i in range(0, len(negs), 60)])\n", 624 | "\n", 625 | "output = [\n", 626 | " \"# Текущая модель Stable Diffusion: \" + current_checkpoint,\n", 627 | "]\n", 628 | "if use_lora:\n", 629 | " if lora_url == \"\" and lora_path and weight_name:\n", 630 | " output.append(\"# Текущая модель LoRA: \" + lora_path)\n", 631 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 632 | " output.append(\"# Текущая модель LoRA: \" + downloaded_lora_basename)\n", 633 | "output.extend([\n", 634 | " \"# Текущий стиль: \" + styles,\n", 635 | " \"# Промпт: \" + prompt_display,\n", 636 | " \"# Негативный промпт: \" + negs_display,\n", 637 | " \"# Разрешение: \" + str(width) + \"x\" + str(height),\n", 638 | " \"# Количество генерируемых изображений: \" + str(images_count)\n", 639 | "])\n", 640 | "#max_length_string = max(len(s.replace('\\n', '')) for s in output)\n", 641 | "max_length_string = 70\n", 642 | "\n", 643 | "print(\"#\" * max_length_string )\n", 644 | "for item in output:\n", 645 | " print(item)\n", 646 | "\n", 647 | "######################################################################\n", 648 | "if not randomness:\n", 649 | " generator = torch.Generator(current_device).manual_seed(seed)\n", 650 | " print(\"# Seed этой генерации: \" + str(seed) + \"\\n\" + (\"#\" * max_length_string) )\n", 651 | "elif randomness:\n", 652 | " current_seed = torch.Generator(current_device).seed()\n", 653 | " generator = torch.Generator(current_device).manual_seed(current_seed)\n", 654 | " print(\"# Seed этой генерации: \" + str(current_seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 655 | "\n", 656 | "\n", 657 | "#result = pipe(prompt=prompt, height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 658 | "\n", 659 | "if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 660 | " if show_diffusion:\n", 661 | " torch.cuda.empty_cache()\n", 662 | " result = pipe(prompt_embeds=prompt_embeds, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 663 | " else:\n", 664 | " torch.cuda.empty_cache()\n", 665 | " result = pipe(prompt_embeds=prompt_embeds, height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 666 | "\n", 667 | "if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 668 | " if show_diffusion:\n", 669 | " torch.cuda.empty_cache()\n", 670 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 671 | " else:\n", 672 | " torch.cuda.empty_cache()\n", 673 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 674 | "\n", 675 | "if sd_type == \"Отключить веса токенов (для совместимости)\":\n", 676 | " if show_diffusion:\n", 677 | " torch.cuda.empty_cache()\n", 678 | " result = pipe(prompt=prompt, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 679 | " else:\n", 680 | " torch.cuda.empty_cache()\n", 681 | " result = pipe(prompt=prompt, height=height, width=width, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count)\n", 682 | "\n", 683 | "# Вывод и сохрарнение результата\n", 684 | "\n", 685 | "if use_gdrive:\n", 686 | " today = str(date.today())\n", 687 | " if not os.path.exists(\"/content/gdrive/MyDrive/SDOutput/\" + today):\n", 688 | " os.makedirs(\"/content/gdrive/MyDrive/SDOutput/\" + today, exist_ok=True)\n", 689 | " for i in range(images_count):\n", 690 | " time = datetime.now()\n", 691 | " time = str(time.strftime(\"%H-%M-%S\"))\n", 692 | " file_name = time + \"_\" + \"seed_\" + str(current_seed) + \"_image\" + str(i) +\".png\"\n", 693 | " file_name = \"/content/gdrive/MyDrive/SDOutput/\" + today + \"/\" + file_name\n", 694 | " images = make_image_grid(result.images, rows=1, cols=images_count)\n", 695 | " result.images[i].save(file_name)\n", 696 | " print(\"Сохранено: \" + file_name)\n", 697 | "\n", 698 | "clear_output()\n", 699 | "#update_display(result, display_id=display_handle.display_id)\n", 700 | "print(\"#\" * max_length_string )\n", 701 | "print(\"# Текущая модель Stable Diffusion: \" + current_checkpoint)\n", 702 | "if use_lora:\n", 703 | " if lora_url == \"\" and lora_path and weight_name:\n", 704 | " output.append(\"# Текущая модель LoRA: \" + lora_path)\n", 705 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 706 | " output.append(\"# Текущая модель LoRA: \" + downloaded_lora_basename)\n", 707 | "print(\"# Текущий стиль: \" + styles)\n", 708 | "print(\"# Промпт: \" + prompt_display)\n", 709 | "print(\"# Негативный промпт: \" + negs_display)\n", 710 | "print(\"# Разрешение: \" + str(width) + \"x\" + str(height))\n", 711 | "print(\"# Количество генерируемых изображений: \" + str(images_count))\n", 712 | "if not randomness:\n", 713 | " print(\"# Seed этой генерации: \" + str(seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 714 | "elif randomness:\n", 715 | " print(\"# Seed этой генерации: \" + str(current_seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 716 | "make_image_grid(result.images, rows=1, cols=images_count)" 717 | ], 718 | "metadata": { 719 | "id": "Nl8kcwyOqfd_" 720 | }, 721 | "execution_count": null, 722 | "outputs": [] 723 | }, 724 | { 725 | "cell_type": "code", 726 | "source": [ 727 | "# @title Загрузка изображения для модуля Image2Image\n", 728 | "# @markdown Ширина и высота вашего изображения должны делиться на 8 без остатка, иначе будет ошибка.\n", 729 | "print(\"Выберите исходное изображение: \")\n", 730 | "init_image = files.upload()\n", 731 | "image_key = list(init_image.keys())[0]\n", 732 | "image_data = init_image[image_key]\n", 733 | "img = Image.open(io.BytesIO(image_data))\n", 734 | "img_width, img_height = img.size\n", 735 | "clear_output()\n", 736 | "new_size = (128, 128)\n", 737 | "img_preview = img.resize(new_size)\n", 738 | "print(\"Изображение успешно загружено :)\")\n", 739 | "display(img_preview)" 740 | ], 741 | "metadata": { 742 | "cellView": "form", 743 | "id": "FtAIUUMVO8hS" 744 | }, 745 | "execution_count": null, 746 | "outputs": [] 747 | }, 748 | { 749 | "cell_type": "code", 750 | "source": [ 751 | "# @title Image2Image (Генерация изображения из другого изображения): { form-width: \"10%\", display-mode: \"form\" }\n", 752 | "# @markdown <-- Начать генерацию\n", 753 | "\n", 754 | "# @markdown ---\n", 755 | "# @markdown Сила:\n", 756 | "\n", 757 | "# @markdown Чем ниже значене, тем ближе генерация будет к изображению, которое вы загрузили. Чем больше значение, тем сильнее нейросеть будет креативничать.\n", 758 | "\n", 759 | "img2img_strength = 0.3 # @param {type:\"slider\", min:0.1, max:1.0, step:0.1}\n", 760 | "\n", 761 | "# @markdown Силу нужно комбинировать с шагами. Итоговое количество шагов для генерации шума рассчитывается по формуле (Шаги * Сила).\n", 762 | "\n", 763 | "# @markdown Шаги:\n", 764 | "steps = 25 # @param {type:\"number\"}\n", 765 | "# @markdown ---\n", 766 | "# @markdown Показывать диффузию в реальном времени?\n", 767 | "show_diffusion = True # @param {type:\"boolean\"}\n", 768 | "# @markdown ---\n", 769 | "\n", 770 | "ddpm = DDPMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 771 | "ddim = DDIMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 772 | "pndm = PNDMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 773 | "lms = LMSDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 774 | "euler_anc = EulerAncestralDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 775 | "euler = EulerDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 776 | "dpm = DPMSolverMultistepScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 777 | "\n", 778 | "run_chkpt(current_checkpoint, lora_path, use_lora, \"img2img\")\n", 779 | "\n", 780 | "\n", 781 | "if init_image:\n", 782 | "\n", 783 | " if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 784 | " compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)\n", 785 | " prompt_embeds = compel_proc(prompt)\n", 786 | "\n", 787 | " if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 788 | " compel = Compel(\n", 789 | " tokenizer=[pipe.tokenizer, pipe.tokenizer_2] ,\n", 790 | " text_encoder=[pipe.text_encoder, pipe.text_encoder_2],\n", 791 | " returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED,\n", 792 | " requires_pooled=[False, True]\n", 793 | " )\n", 794 | " conditioning, pooled = compel(prompt)\n", 795 | " prompt_display = '\\n'.join([prompt[i:i+60] for i in range(0, len(prompt), 60)])\n", 796 | " negs_display = '\\n'.join([negs[i:i+60] for i in range(0, len(negs), 60)])\n", 797 | " output = [\n", 798 | " \"# Текущая модель Stable Diffusion: \" + current_checkpoint,\n", 799 | " ]\n", 800 | " if lora_url == \"\" and lora_path and weight_name:\n", 801 | " output.append(\"# Текущая модель LoRA: \" + lora_path)\n", 802 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 803 | " output.append(\"# Текущая модель LoRA: \" + downloaded_lora_basename)\n", 804 | " output.extend([\n", 805 | " \"# Текущий стиль: \" + styles,\n", 806 | " \"# Промпт: \" + prompt_display,\n", 807 | " \"# Негативный промпт: \" + negs_display,\n", 808 | " \"# Разрешение: \" + str(img_width) + \"x\" + str(img_height),\n", 809 | " \"# Сила: \" + str(img2img_strength)\n", 810 | " ])\n", 811 | " max_length_string = 70\n", 812 | "\n", 813 | " print(\"#\" * max_length_string )\n", 814 | " for item in output:\n", 815 | " print(item)\n", 816 | "\n", 817 | " if not randomness:\n", 818 | " generator = torch.Generator(current_device).manual_seed(seed)\n", 819 | " print(\"# Seed этой генерации: \" + str(seed) + \"\\n\" + (\"#\" * max_length_string) )\n", 820 | " elif randomness:\n", 821 | " current_seed = torch.Generator(current_device).seed()\n", 822 | " generator = torch.Generator(current_device).manual_seed(current_seed)\n", 823 | " print(\"# Seed этой генерации: \" + str(current_seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 824 | "\n", 825 | " if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 826 | " if show_diffusion:\n", 827 | " torch.cuda.empty_cache()\n", 828 | " result = pipe(prompt_embeds=prompt_embeds, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 829 | " else:\n", 830 | " torch.cuda.empty_cache()\n", 831 | " result = pipe(prompt_embeds=prompt_embeds, image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 832 | "\n", 833 | " if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 834 | " if show_diffusion:\n", 835 | " torch.cuda.empty_cache()\n", 836 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 837 | " else:\n", 838 | " torch.cuda.empty_cache()\n", 839 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 840 | "\n", 841 | " if sd_type == \"Отключить веса токенов (для совместимости)\":\n", 842 | " if show_diffusion:\n", 843 | " torch.cuda.empty_cache()\n", 844 | " result = pipe(prompt=prompt, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 845 | " else:\n", 846 | " torch.cuda.empty_cache()\n", 847 | " result = pipe(prompt=prompt, image=img, strength = img2img_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 848 | "\n", 849 | " result.insert(0, img)\n", 850 | "\n", 851 | " clear_output()\n", 852 | " print(\"#\" * max_length_string )\n", 853 | " print(\"# Текущая модель Stable Diffusion: \" + current_checkpoint)\n", 854 | " if use_lora:\n", 855 | " if lora_url == \"\" and lora_path and weight_name:\n", 856 | " output.append(\"# Текущая модель LoRA: \" + lora_path)\n", 857 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 858 | " output.append(\"# Текущая модель LoRA: \" + downloaded_lora_basename)\n", 859 | " print(\"# Текущий стиль: \" + styles)\n", 860 | " print(\"# Промпт: \" + prompt_display)\n", 861 | " print(\"# Негативный промпт: \" + negs_display)\n", 862 | " print(\"# Разрешение: \" + str(img_width) + \"x\" + str(img_height))\n", 863 | " print(\"# Сила: \" + str(img2img_strength))\n", 864 | " if not randomness:\n", 865 | " print(\"# Seed этой генерации: \" + str(seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 866 | " elif randomness:\n", 867 | " print(\"# Seed этой генерации: \" + str(current_seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 868 | "\n", 869 | " if use_gdrive:\n", 870 | " today = str(date.today())\n", 871 | " if not os.path.exists(\"/content/gdrive/MyDrive/SDOutput/\" + today):\n", 872 | " os.makedirs(\"/content/gdrive/MyDrive/SDOutput/\" + today, exist_ok=True)\n", 873 | " for i in range(images_count+1):\n", 874 | " if i > 0:\n", 875 | " time = datetime.now()\n", 876 | " time = str(time.strftime(\"%H-%M-%S\"))\n", 877 | " file_name = time + \"_\" + \"seed_\" + str(current_seed) + \"_image_\" + str(i) + \"_img2imged.png\"\n", 878 | " file_name = \"/content/gdrive/MyDrive/SDOutput/\" + today + \"/\" + file_name\n", 879 | " result[i].save(file_name)\n", 880 | " print(\"Сохранено: \" + file_name)\n", 881 | " else:\n", 882 | " pass\n", 883 | "\n", 884 | " display( make_image_grid(result, rows=1, cols=len(result) ) )\n", 885 | "else:\n", 886 | " print(\"Отсутствует изображение для генерации :(\")" 887 | ], 888 | "metadata": { 889 | "id": "kbebpfrLohQX" 890 | }, 891 | "execution_count": null, 892 | "outputs": [] 893 | }, 894 | { 895 | "cell_type": "code", 896 | "source": [ 897 | "# @title Загрузка изображений для модуля Inpainting\n", 898 | "# @markdown Ширина и высота ваших изображений должны делиться на 8 без остатка, иначе будет ошибка.\n", 899 | "print(\"Выберите исходное изображение: \")\n", 900 | "inpaint_image = files.upload()\n", 901 | "print(\"Выберите изображение маски: \")\n", 902 | "inpaint_mask = files.upload()\n", 903 | "\n", 904 | "inpaint_image_key = list(inpaint_image.keys())[0]\n", 905 | "inpaint_mask_image_key = list(inpaint_mask.keys())[0]\n", 906 | "inpaint_image_data = inpaint_image[inpaint_image_key]\n", 907 | "inpaint_mask_image_data = inpaint_mask[inpaint_mask_image_key]\n", 908 | "inpaint_image = Image.open(io.BytesIO(inpaint_image_data)).convert('RGB')\n", 909 | "inpaint_mask_image = Image.open(io.BytesIO(inpaint_mask_image_data)).convert('RGB')\n", 910 | "inpaint_image_width, inpaint_image_height = inpaint_image.size\n", 911 | "inpaint_image_mask_width, inpaint_image_mask_height = inpaint_mask_image.size\n", 912 | "clear_output()\n", 913 | "new_size = (128, 128)\n", 914 | "inpaint_image_preview = inpaint_image.resize(new_size)\n", 915 | "inpaint_mask_image_preview = inpaint_mask_image.resize(new_size)\n", 916 | "print(\"Изображения успешно загружены :)\")\n", 917 | "display( make_image_grid([inpaint_image_preview, inpaint_mask_image_preview], rows=1, cols=2 ) )" 918 | ], 919 | "metadata": { 920 | "cellView": "form", 921 | "id": "x0hV1I-eQTMB" 922 | }, 923 | "execution_count": null, 924 | "outputs": [] 925 | }, 926 | { 927 | "cell_type": "code", 928 | "source": [ 929 | "# @title Inpainting (Генерация изображения из другого изображения с использованием маски): { form-width: \"10%\", display-mode: \"form\" }\n", 930 | "# @markdown <-- Начать генерацию\n", 931 | "\n", 932 | "# @markdown ---\n", 933 | "# @markdown Сила:\n", 934 | "\n", 935 | "# @markdown Чем ниже значене, тем ближе генерация будет к изображению, которое вы загрузили. Чем больше значение, тем сильнее нейросеть будет креативничать.\n", 936 | "\n", 937 | "inpaint_strength = 0.4 # @param {type:\"slider\", min:0.1, max:1.0, step:0.1}\n", 938 | "\n", 939 | "# @markdown Силу нужно комбинировать с шагами. Итоговое количество шагов для генерации шума рассчитывается по формуле (Шаги * Сила).\n", 940 | "\n", 941 | "# @markdown Шаги:\n", 942 | "steps = 25 # @param {type:\"number\"}\n", 943 | "# @markdown ---\n", 944 | "# @markdown Показывать диффузию в реальном времени?\n", 945 | "show_diffusion = True # @param {type:\"boolean\"}\n", 946 | "# @markdown ---\n", 947 | "# @markdown При рисовании маски помните, что чёрные области игнорируются нейросетью, а белые - нет. Размытия белых областей в масках тоже поддерживаются.\n", 948 | "\n", 949 | "ddpm = DDPMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 950 | "ddim = DDIMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 951 | "pndm = PNDMScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 952 | "lms = LMSDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 953 | "euler_anc = EulerAncestralDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 954 | "euler = EulerDiscreteScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 955 | "dpm = DPMSolverMultistepScheduler.from_pretrained(current_checkpoint, subfolder=\"scheduler\")\n", 956 | "\n", 957 | "run_chkpt(current_checkpoint, lora_path, use_lora, \"inpainting\")\n", 958 | "\n", 959 | "if inpaint_image and inpaint_mask:\n", 960 | "\n", 961 | " if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 962 | " compel_proc = Compel(tokenizer=pipe.tokenizer, text_encoder=pipe.text_encoder)\n", 963 | " prompt_embeds = compel_proc(prompt)\n", 964 | "\n", 965 | " if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 966 | " compel = Compel(\n", 967 | " tokenizer=[pipe.tokenizer, pipe.tokenizer_2] ,\n", 968 | " text_encoder=[pipe.text_encoder, pipe.text_encoder_2],\n", 969 | " returned_embeddings_type=ReturnedEmbeddingsType.PENULTIMATE_HIDDEN_STATES_NON_NORMALIZED,\n", 970 | " requires_pooled=[False, True]\n", 971 | " )\n", 972 | " conditioning, pooled = compel(prompt)\n", 973 | "\n", 974 | " prompt_display = '\\n'.join([prompt[i:i+60] for i in range(0, len(prompt), 60)])\n", 975 | " negs_display = '\\n'.join([negs[i:i+60] for i in range(0, len(negs), 60)])\n", 976 | " output = [\n", 977 | " \"# Текущая модель Stable Diffusion: \" + current_checkpoint,\n", 978 | " ]\n", 979 | " if lora_url == \"\" and lora_path and weight_name:\n", 980 | " output.append(\"# Текущая модель LoRA: \" + lora_path)\n", 981 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 982 | " output.append(\"# Текущая модель LoRA: \" + downloaded_lora_basename)\n", 983 | " output.extend([\n", 984 | " \"# Текущий стиль: \" + styles,\n", 985 | " \"# Промпт: \" + prompt_display,\n", 986 | " \"# Негативный промпт: \" + negs_display,\n", 987 | " \"# Разрешение изображения: \" + str(inpaint_image_width) + \"x\" + str(inpaint_image_height),\n", 988 | " \"# Разрешение маски: \" + str(inpaint_image_mask_width) + \"x\" + str(inpaint_image_mask_height),\n", 989 | " \"# Сила: \" + str(inpaint_strength)\n", 990 | " ])\n", 991 | " max_length_string = 70\n", 992 | "\n", 993 | " print(\"#\" * max_length_string )\n", 994 | " for item in output:\n", 995 | " print(item)\n", 996 | "\n", 997 | " if not randomness:\n", 998 | " generator = torch.Generator(current_device).manual_seed(seed)\n", 999 | " print(\"# Seed этой генерации: \" + str(seed) + \"\\n\" + (\"#\" * max_length_string) )\n", 1000 | " elif randomness:\n", 1001 | " current_seed = torch.Generator(current_device).seed()\n", 1002 | " generator = torch.Generator(current_device).manual_seed(current_seed)\n", 1003 | " print(\"# Seed этой генерации: \" + str(current_seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 1004 | "\n", 1005 | " if sd_type == \"Stable Diffusion 1.5/2.0\":\n", 1006 | " if show_diffusion:\n", 1007 | " torch.cuda.empty_cache()\n", 1008 | " result = pipe(prompt_embeds=prompt_embeds, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 1009 | " else:\n", 1010 | " torch.cuda.empty_cache()\n", 1011 | " result = pipe(prompt_embeds=prompt_embeds, image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 1012 | "\n", 1013 | " if sd_type == \"Stable Diffusion XL (Turbo)\":\n", 1014 | " if show_diffusion:\n", 1015 | " torch.cuda.empty_cache()\n", 1016 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 1017 | " else:\n", 1018 | " torch.cuda.empty_cache()\n", 1019 | " result = pipe(prompt_embeds=conditioning, pooled_prompt_embeds=pooled, image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 1020 | "\n", 1021 | " if sd_type == \"Отключить веса токенов (для совместимости)\":\n", 1022 | " if show_diffusion:\n", 1023 | " torch.cuda.empty_cache()\n", 1024 | " result = pipe(prompt=prompt, callback_on_step_end=decode_tensors, callback_on_step_end_tensor_inputs=[\"latents\"], image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 1025 | " else:\n", 1026 | " torch.cuda.empty_cache()\n", 1027 | " result = pipe(prompt=prompt, image=inpaint_image, mask_image=inpaint_mask_image, width=inpaint_image_width, height=inpaint_image_height, strength = inpaint_strength, num_inference_steps=steps, guidance_scale=gscale, negative_prompt=negs, generator=generator, num_images_per_prompt=images_count).images\n", 1028 | "\n", 1029 | " result.insert(0, inpaint_image)\n", 1030 | " result.insert(1, inpaint_mask_image)\n", 1031 | "\n", 1032 | " clear_output()\n", 1033 | " print(\"#\" * max_length_string )\n", 1034 | " print(\"# Текущая модель Stable Diffusion: \" + current_checkpoint)\n", 1035 | " if use_lora:\n", 1036 | " if lora_url == \"\" and lora_path and weight_name:\n", 1037 | " output.append(\"# Текущая модель LoRA: \" + lora_path)\n", 1038 | " elif lora_url and lora_path == \"\" and weight_name == \"\":\n", 1039 | " output.append(\"# Текущая модель LoRA: \" + downloaded_lora_basename)\n", 1040 | " print(\"# Текущий стиль: \" + styles)\n", 1041 | " print(\"# Промпт: \" + prompt_display)\n", 1042 | " print(\"# Негативный промпт: \" + negs_display)\n", 1043 | " print(\"# Разрешение изображения: \" + str(inpaint_image_width) + \"x\" + str(inpaint_image_height) )\n", 1044 | " print(\"# Разрешение маски: \" + str(inpaint_image_mask_width) + \"x\" + str(inpaint_image_mask_height) )\n", 1045 | " print(\"# Сила: \" + str(inpaint_strength))\n", 1046 | " if not randomness:\n", 1047 | " print(\"# Seed этой генерации: \" + str(seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 1048 | " elif randomness:\n", 1049 | " print(\"# Seed этой генерации: \" + str(current_seed) + \"\\n\" + (\"#\" * max_length_string ))\n", 1050 | "\n", 1051 | " if use_gdrive:\n", 1052 | " today = str(date.today())\n", 1053 | " if not os.path.exists(\"/content/gdrive/MyDrive/SDOutput/\" + today):\n", 1054 | " os.makedirs(\"/content/gdrive/MyDrive/SDOutput/\" + today, exist_ok=True)\n", 1055 | " for i in range(images_count+2):\n", 1056 | " if i > 1:\n", 1057 | " time = datetime.now()\n", 1058 | " time = str(time.strftime(\"%H-%M-%S\"))\n", 1059 | " file_name = time + \"_\" + \"seed_\" + str(current_seed) + \"_image_\" + str(i-1) + \"_inpainted.png\"\n", 1060 | " file_name = \"/content/gdrive/MyDrive/SDOutput/\" + today + \"/\" + file_name\n", 1061 | " result[i].save(file_name)\n", 1062 | " print(\"Сохранено: \" + file_name)\n", 1063 | " else:\n", 1064 | " pass\n", 1065 | "\n", 1066 | " display( make_image_grid(result, rows=1, cols=len(result) ) )\n", 1067 | "else:\n", 1068 | " print(\"Вы отменили загрузку изображения :(\")" 1069 | ], 1070 | "metadata": { 1071 | "id": "ibVBEYWQo2jQ" 1072 | }, 1073 | "execution_count": null, 1074 | "outputs": [] 1075 | } 1076 | ], 1077 | "metadata": { 1078 | "accelerator": "GPU", 1079 | "colab": { 1080 | "provenance": [], 1081 | "collapsed_sections": [ 1082 | "Vq2nSTBmoWq-" 1083 | ], 1084 | "include_colab_link": true 1085 | }, 1086 | "kernelspec": { 1087 | "display_name": "Python 3", 1088 | "name": "python3" 1089 | }, 1090 | "language_info": { 1091 | "name": "python" 1092 | } 1093 | }, 1094 | "nbformat": 4, 1095 | "nbformat_minor": 0 1096 | } --------------------------------------------------------------------------------