├── DiffusingColab.ipynb └── README.md /DiffusingColab.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "private_outputs": true, 7 | "provenance": [], 8 | "gpuType": "T4", 9 | "collapsed_sections": [ 10 | "qJZ-zuXV0JmT", 11 | "5BC7kJb6hqiK" 12 | ], 13 | "include_colab_link": true 14 | }, 15 | "kernelspec": { 16 | "name": "python3", 17 | "display_name": "Python 3" 18 | }, 19 | "language_info": { 20 | "name": "python" 21 | }, 22 | "accelerator": "GPU" 23 | }, 24 | "cells": [ 25 | { 26 | "cell_type": "markdown", 27 | "metadata": { 28 | "id": "view-in-github", 29 | "colab_type": "text" 30 | }, 31 | "source": [ 32 | "\"Open" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "source": [ 38 | "**Diffusing colab by using python! the way god intended**\n", 39 | "---\n", 40 | "\n" 41 | ], 42 | "metadata": { 43 | "id": "qJZ-zuXV0JmT" 44 | } 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": { 50 | "id": "gDkEJvt4e1-Y", 51 | "cellView": "form" 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "#@title **Installing** and **importing** all necessary and semi necessary stuff\n", 56 | "import numpy as np\n", 57 | "import matplotlib.pyplot as plt\n", 58 | "import sys\n", 59 | "import os\n", 60 | "import shutil\n", 61 | "import time\n", 62 | "from PIL import Image\n", 63 | "import torch\n", 64 | "from IPython.utils import io\n", 65 | "import re\n", 66 | "import cv2\n", 67 | "from google.colab.patches import cv2_imshow\n", 68 | "with io.capture_output() as captured:\n", 69 | " !pip install --upgrade gradio diffusers accelerate transformers xformers safetensors\n", 70 | " !apt-get install aria2\n", 71 | " output_text = captured.stdout\n", 72 | " errors = re.findall(r'(?i).error.', output_text)\n", 73 | " for error in errors:\n", 74 | " print(error)\n", 75 | "import gradio as gr\n", 76 | "from diffusers import DiffusionPipeline, StableDiffusionPipeline, StableDiffusionXLPipeline, AutoencoderTiny, EulerDiscreteScheduler, DDPMScheduler, KDPM2DiscreteScheduler, DPMSolverMultistepScheduler" 77 | ] 78 | }, 79 | { 80 | "cell_type": "code", 81 | "source": [ 82 | "#@title create the setup folders (Necessary) and use Google Drive (optional)\n", 83 | "\n", 84 | "USE_GDRIVE = False #@param {type: \"boolean\"}\n", 85 | "if USE_GDRIVE:\n", 86 | " from google.colab import drive\n", 87 | " drive.mount('/content/drive')\n", 88 | "!mkdir Loras\n", 89 | "!mkdir Outputs\n", 90 | "!mkdir Plots\n", 91 | "lora_folder = '/content/Loras'\n", 92 | "output_folder = '/content/Outputs'\n", 93 | "plot_folder = \"/content/Plots\"" 94 | ], 95 | "metadata": { 96 | "id": "zaXRyA4xwbHA", 97 | "cellView": "form" 98 | }, 99 | "execution_count": null, 100 | "outputs": [] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "source": [ 105 | "#@title Download Loras from Civitai (provide a link with api otherwise it will be a faulty download)(Dont interlink between 1.5 and sdxl loras)\n", 106 | "link = \"https://civitai.com/api/download/models/145829/\" #@param {type: \"string\"}\n", 107 | "name = \"cutecomicstylexl.safetensors\" #@param {type: \"string\"}\n", 108 | "\n", 109 | "if not name.endswith('.safetensors'):\n", 110 | " raise ValueError(\"doesnt have .safetensors in the name\")\n", 111 | "\n", 112 | "!aria2c -x 16 {link} -d {lora_folder} -o {name}\n" 113 | ], 114 | "metadata": { 115 | "cellView": "form", 116 | "id": "JAbtvCAD-LAz" 117 | }, 118 | "execution_count": null, 119 | "outputs": [] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "source": [ 124 | "#@title select which model and optimization to use (Necessary)\n", 125 | "Enter_model = \"BaseSdxl\" # @param [\"BaseSdxl\", \"base-1.5\", \"openjourney(realistic1.5)\"]\n", 126 | "Enter_optimisation = \"optimised\" # @param [\"none\", 'optimised']\n", 127 | "\n", 128 | "match Enter_model:\n", 129 | " case 'BaseSdxl':\n", 130 | " model_id = \"stabilityai/stable-diffusion-xl-base-1.0\"\n", 131 | " Pipeline = StableDiffusionXLPipeline.from_pretrained(model_id, torch_dtype=torch.float16, variant=\"fp16\", safety_checker=None, use_safetensors=True)\n", 132 | " case 'base-1.5':\n", 133 | " model_id = \"runwayml/stable-diffusion-v1-5\"\n", 134 | " Pipeline = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16, variant=\"fp16\", safety_checker=None, use_safetensors=True)\n", 135 | " case 'openjourney(realistic1.5)':\n", 136 | " model_id = \"upro/openjourney\"\n", 137 | " Pipeline = StableDiffusionPipeline.from_pretrained(model_id, torch_dtype=torch.float16, variant=\"fp16\", safety_checker=None, use_safetensors=True)\n", 138 | "\n", 139 | "match Enter_optimisation:\n", 140 | " case 'optimised':\n", 141 | " if Enter_model == \"BaseSdxl\":\n", 142 | " Pipeline.vae = AutoencoderTiny.from_pretrained(\"madebyollin/taesdxl\", torch_dtype=torch.float16)\n", 143 | " Pipeline.enable_attention_slicing()\n", 144 | " Pipeline.enable_vae_slicing()\n", 145 | " Pipeline.enable_vae_tiling()\n", 146 | " else:\n", 147 | " Pipeline.vae = AutoencoderTiny.from_pretrained(\"madebyollin/taesd\", torch_dtype=torch.float16)\n", 148 | " Pipeline.enable_attention_slicing()\n", 149 | " Pipeline.enable_vae_slicing()\n", 150 | " Pipeline.enable_vae_tiling()\n", 151 | " case \"none\":\n", 152 | " Pipeline.disable_attention_slicing()\n", 153 | " Pipeline.disable_vae_tiling()\n", 154 | " Pipeline.disable_vae_slicing()\n" 155 | ], 156 | "metadata": { 157 | "cellView": "form", 158 | "id": "bPu4OrqN8FRK" 159 | }, 160 | "execution_count": null, 161 | "outputs": [] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "source": [ 166 | "# @title Generate (-1 seed value = random generate)\n", 167 | "def seed_selector(seed):\n", 168 | " with torch.no_grad():\n", 169 | " if seed != -1:\n", 170 | " return torch.Generator(device = \"cuda\").manual_seed(seed)\n", 171 | " random_seed = torch.Generator().seed()\n", 172 | " print(f\"seed for the image is {random_seed}\")\n", 173 | " return torch.Generator(device = \"cuda\").manual_seed(random_seed)\n", 174 | "\n", 175 | "def Loading_Lora(lora_name_string):\n", 176 | " lora_list = os.listdir(lora_folder)\n", 177 | " matching_files = [filename for filename in lora_list if lora_name_string in filename and filename.endswith(\".safetensors\")]\n", 178 | "\n", 179 | " if not matching_files:\n", 180 | " print(f\"No matching files found for '{lora_name_string}' in {lora_folder}.\")\n", 181 | " return None\n", 182 | "\n", 183 | " if len(matching_files) == 1:\n", 184 | "\n", 185 | " selected_file = matching_files[0]\n", 186 | " Pipeline.load_lora_weights(os.path.join(lora_folder, selected_file))\n", 187 | " return Pipeline\n", 188 | " else:\n", 189 | " print(\"more than one lora with matching names, be more specific in the naming\")\n", 190 | "\n", 191 | "def basic_generator(input_prompt: str, neg_prompt:str, number_of_pics: int, steps: int, width = 1024, height = 1024, seed: int = -1, Use_Lora: bool = False, Lora_name: str = \"\", Lora_comparision: bool = False, scheduler=\"DPMSolverMultistep\") -> list:\n", 192 | " number_of_pics = int(number_of_pics)\n", 193 | " steps = int(steps)\n", 194 | " width = int(width)\n", 195 | " height = int(height)\n", 196 | " seed = int(seed)\n", 197 | " output = []\n", 198 | " generator = None\n", 199 | " if len(Lora_name) == 0:\n", 200 | " Lora_name = None\n", 201 | " match scheduler:\n", 202 | " case \"EulerDiscrete\":\n", 203 | " Pipeline.scheduler = EulerDiscreteScheduler.from_config(Pipeline.scheduler.config)\n", 204 | " case \"DDPM\":\n", 205 | " Pipeline.scheduler = DDPMScheduler.from_config(Pipeline.scheduler.config)\n", 206 | " case \"KDPM2Discrete\":\n", 207 | " Pipeline.scheduler = KDPM2DiscreteScheduler.from_config(Pipeline.scheduler.config)\n", 208 | " case \"DPMSolverMultistep\":\n", 209 | " Pipeline.scheduler = DPMSolverMultistepScheduler.from_config(Pipeline.scheduler.config)\n", 210 | " case _:\n", 211 | " print(f\"Unknown scheduler: {scheduler}\")\n", 212 | " Pipeline.to('cuda')\n", 213 | "\n", 214 | " if Use_Lora and Lora_name is None:\n", 215 | " raise ValueError(\"If 'Use_Lora' is True, 'Lora_name' must be provided.\")\n", 216 | " elif not Use_Lora and Lora_name is not None:\n", 217 | " raise ValueError(\"If 'Use_Lora' is False, 'Lora_name' should not be provided.\")\n", 218 | "\n", 219 | "\n", 220 | " if Use_Lora:\n", 221 | " Loading_Lora(Lora_name)\n", 222 | " for i in range(number_of_pics):\n", 223 | " output.append(Pipeline(prompt = input_prompt, num_inference_steps= steps, generator = seed_selector(seed), width = width, height = height).images)\n", 224 | " Pipeline.unload_lora_weights()\n", 225 | "\n", 226 | " elif Lora_comparision:\n", 227 | " for lora in os.listdir(lora_folder):\n", 228 | " if lora.endswith(\".safetensors\"):\n", 229 | " Loading_Lora(lora)\n", 230 | " output.append(Pipeline(prompt = input_prompt, num_inference_steps= steps, generator = seed_selector(seed), width = width, height = height).images)\n", 231 | " Pipeline.unload_lora_weights()\n", 232 | "\n", 233 | " else:\n", 234 | " for i in range(number_of_pics):\n", 235 | " output.append(Pipeline(prompt = input_prompt, num_inference_steps= steps, generator = seed_selector(seed), width = width, height = height).images)\n", 236 | "\n", 237 | "\n", 238 | " image_paths = []\n", 239 | " for index, image in enumerate(output):\n", 240 | " while True:\n", 241 | " file_name = f\"image{index}.png\"\n", 242 | " if file_name not in os.listdir(output_folder):\n", 243 | " break\n", 244 | " index += 1\n", 245 | " image[0].save(os.path.join(output_folder, file_name), \"PNG\")\n", 246 | " image_paths.append(os.path.join(output_folder, file_name))\n", 247 | " return image_paths\n", 248 | "\n", 249 | "def plot_images(image_paths:list = None):\n", 250 | " if image_paths is None:\n", 251 | " image_paths = [\n", 252 | " os.path.join(output_folder, filename)\n", 253 | " for filename in os.listdir(output_folder)\n", 254 | " if os.path.isfile(os.path.join(output_folder, filename))\n", 255 | " ]\n", 256 | " num_images = len(image_paths)\n", 257 | " num_rows = int(num_images ** 0.5)\n", 258 | " num_cols = (num_images + num_rows - 1) // num_rows\n", 259 | " total_width = max(img.width for img in map(Image.open, image_paths)) * num_cols\n", 260 | " total_height = max(img.height for img in map(Image.open, image_paths)) * num_rows\n", 261 | " fig, axes = plt.subplots(num_rows, num_cols, figsize=(total_width/100 , total_height/100))\n", 262 | " for i, ax in enumerate(axes.ravel()):\n", 263 | " if i < len(image_paths):\n", 264 | " img = Image.open(image_paths[i])\n", 265 | " ax.imshow(img)\n", 266 | " ax.axis('off')\n", 267 | " filename = os.path.basename(image_paths[i])\n", 268 | " ax.set_title(filename, fontsize=20)\n", 269 | " plt.subplots_adjust(wspace=0.01, hspace=0.01)\n", 270 | " i = len(os.listdir(plot_folder))\n", 271 | " while True:\n", 272 | " plt_name = os.path.join(plot_folder, f\"plot{i}.jpg\")\n", 273 | " if plt_name in os.listdir(plot_folder):\n", 274 | " plt_name = os.path.join(plot_folder, f\"plot{i+1}.jpg\")\n", 275 | " i += 1\n", 276 | " else:\n", 277 | " break\n", 278 | "\n", 279 | " plt.savefig(plt_name, bbox_inches=\"tight\")\n", 280 | "\n", 281 | "def showcase(Image_paths : list):\n", 282 | " for filename in Image_paths:\n", 283 | " img = cv2.imread(filename)\n", 284 | " cv2_imshow(img)\n", 285 | "prompt = \"comic style image of a woman riding a bike\" # @param {type:\"string\"}\n", 286 | "neg_prompt = \"dull, realistic, broken, incomplete, out of shape\" # @param {type:\"string\"}\n", 287 | "height = 1024 # @param {type:\"integer\"}\n", 288 | "width = 1024 # @param {type:\"integer\"}\n", 289 | "images = 1 # @param {type:\"integer\"}\n", 290 | "steps = 25 # @param {type:\"integer\"}\n", 291 | "seed = -1 #@param {type: \"integer\"}\n", 292 | "clean_before_gen = True # @param {type:\"boolean\"}\n", 293 | "scheduler = \"EulerDiscrete\" # @param [\"EulerDiscrete\",\"DDPM\",\"KDPM2Discrete\",\"DPMSolverMultistep\"]\n", 294 | "plot_generated_images = False #@param {type:'boolean'}\n", 295 | "Use_Lora = True #@param {type:'boolean'}\n", 296 | "Lora_name = 'cutecomicstylexl' # @param {type:\"string\"}\n", 297 | "Lora_comparision = False #@param {type: \"boolean\"}\n", 298 | "# @markdown comapares all loras in the lora folder and plots them (disregards number of pics)\n", 299 | "if clean_before_gen:\n", 300 | " !find {output_folder} -type f -delete\n", 301 | " !find {plot_folder} -type f -delete\n", 302 | "if plot_generated_images:\n", 303 | " if images == 1 and Lora_comparision == False:\n", 304 | " raise ValueError(\"cant plot a single image\")\n", 305 | " else:\n", 306 | " plot_images(basic_generator(prompt,neg_prompt,images,steps,height = height,width= width, scheduler = scheduler, seed = seed, Use_Lora = Use_Lora, Lora_name = Lora_name, Lora_comparision = Lora_comparision))\n", 307 | "else:\n", 308 | " showcase(basic_generator(prompt,neg_prompt,images,steps,height = height,width= width, scheduler = scheduler, seed = seed, Use_Lora = Use_Lora, Lora_name = Lora_name, Lora_comparision = Lora_comparision))" 309 | ], 310 | "metadata": { 311 | "id": "4sLH-Q9Xz-yB", 312 | "cellView": "form" 313 | }, 314 | "execution_count": null, 315 | "outputs": [] 316 | }, 317 | { 318 | "cell_type": "markdown", 319 | "source": [ 320 | "**Utility cells below**\n", 321 | "---\n", 322 | "\n" 323 | ], 324 | "metadata": { 325 | "id": "5BC7kJb6hqiK" 326 | } 327 | }, 328 | { 329 | "cell_type": "code", 330 | "source": [ 331 | "#@title run the cell to copy stuff from gdrive like loras, to the appropriate folders\n", 332 | "user_input = \"Marcelinexl\" #@param {type:\"string\"}\n", 333 | "google_drive_folder = \"/content/drive/\" #@param {type:\"string\"}\n", 334 | "directoryto = lora_folder # @param [\"lora_folder\"] {type:\"raw\"}\n", 335 | "\n", 336 | "\n", 337 | "\n", 338 | "\n", 339 | "full_content = os.listdir(google_drive_folder)\n", 340 | "\n", 341 | "\n", 342 | "for file in full_content:\n", 343 | " if user_input in file:\n", 344 | " source_path = os.path.join(google_drive_folder, file)\n", 345 | " shutil.copy(source_path, directoryto)\n" 346 | ], 347 | "metadata": { 348 | "id": "M0GCgjFP1Kh3", 349 | "cellView": "form" 350 | }, 351 | "execution_count": null, 352 | "outputs": [] 353 | }, 354 | { 355 | "cell_type": "code", 356 | "source": [ 357 | "#@title run the cell to plot all images in images\n", 358 | "plot_images()" 359 | ], 360 | "metadata": { 361 | "cellView": "form", 362 | "id": "e9Fe9f5KK3IF" 363 | }, 364 | "execution_count": null, 365 | "outputs": [] 366 | }, 367 | { 368 | "cell_type": "code", 369 | "source": [ 370 | "#@title run the **`Gradio`** interface (not completed)\n", 371 | "#Iface = gr.Interface(fn=user_inputs, inputs= [\"text\",\"number\"], outputs= \"image\")\n", 372 | "#Iface.launch(debug=True)" 373 | ], 374 | "metadata": { 375 | "id": "dg4vYAZnVaK1", 376 | "cellView": "form" 377 | }, 378 | "execution_count": null, 379 | "outputs": [] 380 | } 381 | ] 382 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DiffusingColab (SDXL support) 2 | a colab notebook repo for using Diffusers library for various tasks using pre-defined functions by me yourself! 3 | 4 | 5 | # Google wont ban this for free users as it is purely python based and we dont even import external scripts from anywhere, just like the god intended way of using colab 6 | -ckperry 7 | 8 | 9 | click on the .ipynb file and open in colab to open it in colab and the notebook should be easy to follow along- 10 | 11 | 12 | has features like plotting your generated images, downloading loras from civitai, lora comparision, using manual seeds! more on the way in the future hopefully- 13 | 14 | 15 | some features that may come in future: Custom Model download, inpainting, control-net 16 | 17 | 18 | img2img and face restoration will be there in a seperate branch before being merged, so quite a while 19 | 20 | 21 | Big thanks to SilverandJade on Discord for helping and suggesting some wonderful features for this colab!! 22 | --------------------------------------------------------------------------------