processing.py 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287
  1. import json
  2. import math
  3. import os
  4. import sys
  5. import hashlib
  6. import torch
  7. import numpy as np
  8. from PIL import Image, ImageFilter, ImageOps
  9. import random
  10. import cv2
  11. from skimage import exposure
  12. from typing import Any, Dict, List
  13. import modules.sd_hijack
  14. from modules import devices, prompt_parser, masking, sd_samplers, lowvram, generation_parameters_copypaste, extra_networks, sd_vae_approx, scripts, sd_samplers_common
  15. from modules.sd_hijack import model_hijack
  16. from modules.shared import opts, cmd_opts, state
  17. import modules.shared as shared
  18. import modules.paths as paths
  19. import modules.face_restoration
  20. import modules.images as images
  21. import modules.styles
  22. import modules.sd_models as sd_models
  23. import modules.sd_vae as sd_vae
  24. import logging
  25. from ldm.data.util import AddMiDaS
  26. from ldm.models.diffusion.ddpm import LatentDepth2ImageDiffusion
  27. from einops import repeat, rearrange
  28. from blendmodes.blend import blendLayers, BlendType
  29. # some of those options should not be changed at all because they would break the model, so I removed them from options.
  30. opt_C = 4
  31. opt_f = 8
  32. def setup_color_correction(image):
  33. logging.info("Calibrating color correction.")
  34. correction_target = cv2.cvtColor(np.asarray(image.copy()), cv2.COLOR_RGB2LAB)
  35. return correction_target
  36. def apply_color_correction(correction, original_image):
  37. logging.info("Applying color correction.")
  38. image = Image.fromarray(cv2.cvtColor(exposure.match_histograms(
  39. cv2.cvtColor(
  40. np.asarray(original_image),
  41. cv2.COLOR_RGB2LAB
  42. ),
  43. correction,
  44. channel_axis=2
  45. ), cv2.COLOR_LAB2RGB).astype("uint8"))
  46. image = blendLayers(image, original_image, BlendType.LUMINOSITY)
  47. return image
  48. def apply_overlay(image, paste_loc, index, overlays):
  49. if overlays is None or index >= len(overlays):
  50. return image
  51. overlay = overlays[index]
  52. if paste_loc is not None:
  53. x, y, w, h = paste_loc
  54. base_image = Image.new('RGBA', (overlay.width, overlay.height))
  55. image = images.resize_image(1, image, w, h)
  56. base_image.paste(image, (x, y))
  57. image = base_image
  58. image = image.convert('RGBA')
  59. image.alpha_composite(overlay)
  60. image = image.convert('RGB')
  61. return image
  62. def txt2img_image_conditioning(sd_model, x, width, height):
  63. if sd_model.model.conditioning_key in {'hybrid', 'concat'}: # Inpainting models
  64. # The "masked-image" in this case will just be all zeros since the entire image is masked.
  65. image_conditioning = torch.zeros(x.shape[0], 3, height, width, device=x.device)
  66. image_conditioning = sd_model.get_first_stage_encoding(sd_model.encode_first_stage(image_conditioning))
  67. # Add the fake full 1s mask to the first dimension.
  68. image_conditioning = torch.nn.functional.pad(image_conditioning, (0, 0, 0, 0, 1, 0), value=1.0)
  69. image_conditioning = image_conditioning.to(x.dtype)
  70. return image_conditioning
  71. elif sd_model.model.conditioning_key == "crossattn-adm": # UnCLIP models
  72. return x.new_zeros(x.shape[0], 2*sd_model.noise_augmentor.time_embed.dim, dtype=x.dtype, device=x.device)
  73. else:
  74. # Dummy zero conditioning if we're not using inpainting or unclip models.
  75. # Still takes up a bit of memory, but no encoder call.
  76. # Pretty sure we can just make this a 1x1 image since its not going to be used besides its batch size.
  77. return x.new_zeros(x.shape[0], 5, 1, 1, dtype=x.dtype, device=x.device)
  78. class StableDiffusionProcessing:
  79. """
  80. The first set of paramaters: sd_models -> do_not_reload_embeddings represent the minimum required to create a StableDiffusionProcessing
  81. """
  82. def __init__(self, sd_model=None, outpath_samples=None, outpath_grids=None, prompt: str = "", styles: List[str] = None, seed: int = -1, subseed: int = -1, subseed_strength: float = 0, seed_resize_from_h: int = -1, seed_resize_from_w: int = -1, seed_enable_extras: bool = True, sampler_name: str = None, batch_size: int = 1, n_iter: int = 1, steps: int = 50, cfg_scale: float = 7.0, width: int = 512, height: int = 512, restore_faces: bool = False, tiling: bool = False, do_not_save_samples: bool = False, do_not_save_grid: bool = False, extra_generation_params: Dict[Any, Any] = None, overlay_images: Any = None, negative_prompt: str = None, eta: float = None, do_not_reload_embeddings: bool = False, denoising_strength: float = 0, ddim_discretize: str = None, s_min_uncond: float = 0.0, s_churn: float = 0.0, s_tmax: float = None, s_tmin: float = 0.0, s_noise: float = 1.0, override_settings: Dict[str, Any] = None, override_settings_restore_afterwards: bool = True, sampler_index: int = None, script_args: list = None, enable_custom_k_sched: bool = False, k_sched_type: str = "", sigma_min: float=0.0, sigma_max: float=0.0, rho: float=0.0):
  83. if sampler_index is not None:
  84. print("sampler_index argument for StableDiffusionProcessing does not do anything; use sampler_name", file=sys.stderr)
  85. self.outpath_samples: str = outpath_samples
  86. self.outpath_grids: str = outpath_grids
  87. self.prompt: str = prompt
  88. self.prompt_for_display: str = None
  89. self.negative_prompt: str = (negative_prompt or "")
  90. self.styles: list = styles or []
  91. self.seed: int = seed
  92. self.subseed: int = subseed
  93. self.subseed_strength: float = subseed_strength
  94. self.seed_resize_from_h: int = seed_resize_from_h
  95. self.seed_resize_from_w: int = seed_resize_from_w
  96. self.sampler_name: str = sampler_name
  97. self.batch_size: int = batch_size
  98. self.n_iter: int = n_iter
  99. self.steps: int = steps
  100. self.cfg_scale: float = cfg_scale
  101. self.width: int = width
  102. self.height: int = height
  103. self.restore_faces: bool = restore_faces
  104. self.tiling: bool = tiling
  105. self.do_not_save_samples: bool = do_not_save_samples
  106. self.do_not_save_grid: bool = do_not_save_grid
  107. self.extra_generation_params: dict = extra_generation_params or {}
  108. self.overlay_images = overlay_images
  109. self.eta = eta
  110. self.do_not_reload_embeddings = do_not_reload_embeddings
  111. self.paste_to = None
  112. self.color_corrections = None
  113. self.denoising_strength: float = denoising_strength
  114. self.sampler_noise_scheduler_override = None
  115. self.ddim_discretize = ddim_discretize or opts.ddim_discretize
  116. self.s_min_uncond = s_min_uncond or opts.s_min_uncond
  117. self.s_churn = s_churn or opts.s_churn
  118. self.s_tmin = s_tmin or opts.s_tmin
  119. self.s_tmax = s_tmax or float('inf') # not representable as a standard ui option
  120. self.s_noise = s_noise or opts.s_noise
  121. self.enable_custom_k_sched = opts.custom_k_sched
  122. self.k_sched_type = k_sched_type or opts.k_sched_type
  123. self.sigma_max = sigma_max or opts.sigma_max
  124. self.sigma_min = sigma_min or opts.sigma_min
  125. self.rho = rho or opts.rho
  126. self.override_settings = {k: v for k, v in (override_settings or {}).items() if k not in shared.restricted_opts}
  127. self.override_settings_restore_afterwards = override_settings_restore_afterwards
  128. self.is_using_inpainting_conditioning = False
  129. self.disable_extra_networks = False
  130. self.token_merging_ratio = 0
  131. self.token_merging_ratio_hr = 0
  132. if not seed_enable_extras:
  133. self.subseed = -1
  134. self.subseed_strength = 0
  135. self.seed_resize_from_h = 0
  136. self.seed_resize_from_w = 0
  137. self.scripts = None
  138. self.script_args = script_args
  139. self.all_prompts = None
  140. self.all_negative_prompts = None
  141. self.all_seeds = None
  142. self.all_subseeds = None
  143. self.iteration = 0
  144. self.is_hr_pass = False
  145. self.sampler = None
  146. self.prompts = None
  147. self.negative_prompts = None
  148. self.seeds = None
  149. self.subseeds = None
  150. self.step_multiplier = 1
  151. self.cached_uc = [None, None]
  152. self.cached_c = [None, None]
  153. self.uc = None
  154. self.c = None
  155. @property
  156. def sd_model(self):
  157. return shared.sd_model
  158. def txt2img_image_conditioning(self, x, width=None, height=None):
  159. self.is_using_inpainting_conditioning = self.sd_model.model.conditioning_key in {'hybrid', 'concat'}
  160. return txt2img_image_conditioning(self.sd_model, x, width or self.width, height or self.height)
  161. def depth2img_image_conditioning(self, source_image):
  162. # Use the AddMiDaS helper to Format our source image to suit the MiDaS model
  163. transformer = AddMiDaS(model_type="dpt_hybrid")
  164. transformed = transformer({"jpg": rearrange(source_image[0], "c h w -> h w c")})
  165. midas_in = torch.from_numpy(transformed["midas_in"][None, ...]).to(device=shared.device)
  166. midas_in = repeat(midas_in, "1 ... -> n ...", n=self.batch_size)
  167. conditioning_image = self.sd_model.get_first_stage_encoding(self.sd_model.encode_first_stage(source_image))
  168. conditioning = torch.nn.functional.interpolate(
  169. self.sd_model.depth_model(midas_in),
  170. size=conditioning_image.shape[2:],
  171. mode="bicubic",
  172. align_corners=False,
  173. )
  174. (depth_min, depth_max) = torch.aminmax(conditioning)
  175. conditioning = 2. * (conditioning - depth_min) / (depth_max - depth_min) - 1.
  176. return conditioning
  177. def edit_image_conditioning(self, source_image):
  178. conditioning_image = self.sd_model.encode_first_stage(source_image).mode()
  179. return conditioning_image
  180. def unclip_image_conditioning(self, source_image):
  181. c_adm = self.sd_model.embedder(source_image)
  182. if self.sd_model.noise_augmentor is not None:
  183. noise_level = 0 # TODO: Allow other noise levels?
  184. c_adm, noise_level_emb = self.sd_model.noise_augmentor(c_adm, noise_level=repeat(torch.tensor([noise_level]).to(c_adm.device), '1 -> b', b=c_adm.shape[0]))
  185. c_adm = torch.cat((c_adm, noise_level_emb), 1)
  186. return c_adm
  187. def inpainting_image_conditioning(self, source_image, latent_image, image_mask=None):
  188. self.is_using_inpainting_conditioning = True
  189. # Handle the different mask inputs
  190. if image_mask is not None:
  191. if torch.is_tensor(image_mask):
  192. conditioning_mask = image_mask
  193. else:
  194. conditioning_mask = np.array(image_mask.convert("L"))
  195. conditioning_mask = conditioning_mask.astype(np.float32) / 255.0
  196. conditioning_mask = torch.from_numpy(conditioning_mask[None, None])
  197. # Inpainting model uses a discretized mask as input, so we round to either 1.0 or 0.0
  198. conditioning_mask = torch.round(conditioning_mask)
  199. else:
  200. conditioning_mask = source_image.new_ones(1, 1, *source_image.shape[-2:])
  201. # Create another latent image, this time with a masked version of the original input.
  202. # Smoothly interpolate between the masked and unmasked latent conditioning image using a parameter.
  203. conditioning_mask = conditioning_mask.to(device=source_image.device, dtype=source_image.dtype)
  204. conditioning_image = torch.lerp(
  205. source_image,
  206. source_image * (1.0 - conditioning_mask),
  207. getattr(self, "inpainting_mask_weight", shared.opts.inpainting_mask_weight)
  208. )
  209. # Encode the new masked image using first stage of network.
  210. conditioning_image = self.sd_model.get_first_stage_encoding(self.sd_model.encode_first_stage(conditioning_image))
  211. # Create the concatenated conditioning tensor to be fed to `c_concat`
  212. conditioning_mask = torch.nn.functional.interpolate(conditioning_mask, size=latent_image.shape[-2:])
  213. conditioning_mask = conditioning_mask.expand(conditioning_image.shape[0], -1, -1, -1)
  214. image_conditioning = torch.cat([conditioning_mask, conditioning_image], dim=1)
  215. image_conditioning = image_conditioning.to(shared.device).type(self.sd_model.dtype)
  216. return image_conditioning
  217. def img2img_image_conditioning(self, source_image, latent_image, image_mask=None):
  218. source_image = devices.cond_cast_float(source_image)
  219. # HACK: Using introspection as the Depth2Image model doesn't appear to uniquely
  220. # identify itself with a field common to all models. The conditioning_key is also hybrid.
  221. if isinstance(self.sd_model, LatentDepth2ImageDiffusion):
  222. return self.depth2img_image_conditioning(source_image)
  223. if self.sd_model.cond_stage_key == "edit":
  224. return self.edit_image_conditioning(source_image)
  225. if self.sampler.conditioning_key in {'hybrid', 'concat'}:
  226. return self.inpainting_image_conditioning(source_image, latent_image, image_mask=image_mask)
  227. if self.sampler.conditioning_key == "crossattn-adm":
  228. return self.unclip_image_conditioning(source_image)
  229. # Dummy zero conditioning if we're not using inpainting or depth model.
  230. return latent_image.new_zeros(latent_image.shape[0], 5, 1, 1)
  231. def init(self, all_prompts, all_seeds, all_subseeds):
  232. pass
  233. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  234. raise NotImplementedError()
  235. def close(self):
  236. self.sampler = None
  237. self.c = None
  238. self.uc = None
  239. self.cached_c = [None, None]
  240. self.cached_uc = [None, None]
  241. def get_token_merging_ratio(self, for_hr=False):
  242. if for_hr:
  243. return self.token_merging_ratio_hr or opts.token_merging_ratio_hr or self.token_merging_ratio or opts.token_merging_ratio
  244. return self.token_merging_ratio or opts.token_merging_ratio
  245. def setup_prompts(self):
  246. if type(self.prompt) == list:
  247. self.all_prompts = self.prompt
  248. else:
  249. self.all_prompts = self.batch_size * self.n_iter * [self.prompt]
  250. if type(self.negative_prompt) == list:
  251. self.all_negative_prompts = self.negative_prompt
  252. else:
  253. self.all_negative_prompts = self.batch_size * self.n_iter * [self.negative_prompt]
  254. self.all_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_prompts]
  255. self.all_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_negative_prompts]
  256. def get_conds_with_caching(self, function, required_prompts, steps, cache):
  257. """
  258. Returns the result of calling function(shared.sd_model, required_prompts, steps)
  259. using a cache to store the result if the same arguments have been used before.
  260. cache is an array containing two elements. The first element is a tuple
  261. representing the previously used arguments, or None if no arguments
  262. have been used before. The second element is where the previously
  263. computed result is stored.
  264. """
  265. if cache[0] is not None and (required_prompts, steps) == cache[0]:
  266. return cache[1]
  267. with devices.autocast():
  268. cache[1] = function(shared.sd_model, required_prompts, steps)
  269. cache[0] = (required_prompts, steps)
  270. return cache[1]
  271. def setup_conds(self):
  272. sampler_config = sd_samplers.find_sampler_config(self.sampler_name)
  273. self.step_multiplier = 2 if sampler_config and sampler_config.options.get("second_order", False) else 1
  274. self.uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, self.negative_prompts, self.steps * self.step_multiplier, self.cached_uc)
  275. self.c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, self.prompts, self.steps * self.step_multiplier, self.cached_c)
  276. def parse_extra_network_prompts(self):
  277. self.prompts, extra_network_data = extra_networks.parse_prompts(self.prompts)
  278. return extra_network_data
  279. class Processed:
  280. def __init__(self, p: StableDiffusionProcessing, images_list, seed=-1, info="", subseed=None, all_prompts=None, all_negative_prompts=None, all_seeds=None, all_subseeds=None, index_of_first_image=0, infotexts=None, comments=""):
  281. self.images = images_list
  282. self.prompt = p.prompt
  283. self.negative_prompt = p.negative_prompt
  284. self.seed = seed
  285. self.subseed = subseed
  286. self.subseed_strength = p.subseed_strength
  287. self.info = info
  288. self.comments = comments
  289. self.width = p.width
  290. self.height = p.height
  291. self.sampler_name = p.sampler_name
  292. self.cfg_scale = p.cfg_scale
  293. self.image_cfg_scale = getattr(p, 'image_cfg_scale', None)
  294. self.steps = p.steps
  295. self.batch_size = p.batch_size
  296. self.restore_faces = p.restore_faces
  297. self.face_restoration_model = opts.face_restoration_model if p.restore_faces else None
  298. self.sd_model_hash = shared.sd_model.sd_model_hash
  299. self.seed_resize_from_w = p.seed_resize_from_w
  300. self.seed_resize_from_h = p.seed_resize_from_h
  301. self.denoising_strength = getattr(p, 'denoising_strength', None)
  302. self.extra_generation_params = p.extra_generation_params
  303. self.index_of_first_image = index_of_first_image
  304. self.styles = p.styles
  305. self.job_timestamp = state.job_timestamp
  306. self.clip_skip = opts.CLIP_stop_at_last_layers
  307. self.token_merging_ratio = p.token_merging_ratio
  308. self.token_merging_ratio_hr = p.token_merging_ratio_hr
  309. self.eta = p.eta
  310. self.ddim_discretize = p.ddim_discretize
  311. self.s_churn = p.s_churn
  312. self.s_tmin = p.s_tmin
  313. self.s_tmax = p.s_tmax
  314. self.s_noise = p.s_noise
  315. self.s_min_uncond = p.s_min_uncond
  316. self.sampler_noise_scheduler_override = p.sampler_noise_scheduler_override
  317. self.prompt = self.prompt if type(self.prompt) != list else self.prompt[0]
  318. self.negative_prompt = self.negative_prompt if type(self.negative_prompt) != list else self.negative_prompt[0]
  319. self.seed = int(self.seed if type(self.seed) != list else self.seed[0]) if self.seed is not None else -1
  320. self.subseed = int(self.subseed if type(self.subseed) != list else self.subseed[0]) if self.subseed is not None else -1
  321. self.is_using_inpainting_conditioning = p.is_using_inpainting_conditioning
  322. self.all_prompts = all_prompts or p.all_prompts or [self.prompt]
  323. self.all_negative_prompts = all_negative_prompts or p.all_negative_prompts or [self.negative_prompt]
  324. self.all_seeds = all_seeds or p.all_seeds or [self.seed]
  325. self.all_subseeds = all_subseeds or p.all_subseeds or [self.subseed]
  326. self.infotexts = infotexts or [info]
  327. def js(self):
  328. obj = {
  329. "prompt": self.all_prompts[0],
  330. "all_prompts": self.all_prompts,
  331. "negative_prompt": self.all_negative_prompts[0],
  332. "all_negative_prompts": self.all_negative_prompts,
  333. "seed": self.seed,
  334. "all_seeds": self.all_seeds,
  335. "subseed": self.subseed,
  336. "all_subseeds": self.all_subseeds,
  337. "subseed_strength": self.subseed_strength,
  338. "width": self.width,
  339. "height": self.height,
  340. "sampler_name": self.sampler_name,
  341. "cfg_scale": self.cfg_scale,
  342. "steps": self.steps,
  343. "batch_size": self.batch_size,
  344. "restore_faces": self.restore_faces,
  345. "face_restoration_model": self.face_restoration_model,
  346. "sd_model_hash": self.sd_model_hash,
  347. "seed_resize_from_w": self.seed_resize_from_w,
  348. "seed_resize_from_h": self.seed_resize_from_h,
  349. "denoising_strength": self.denoising_strength,
  350. "extra_generation_params": self.extra_generation_params,
  351. "index_of_first_image": self.index_of_first_image,
  352. "infotexts": self.infotexts,
  353. "styles": self.styles,
  354. "job_timestamp": self.job_timestamp,
  355. "clip_skip": self.clip_skip,
  356. "is_using_inpainting_conditioning": self.is_using_inpainting_conditioning,
  357. }
  358. return json.dumps(obj)
  359. def infotext(self, p: StableDiffusionProcessing, index):
  360. return create_infotext(p, self.all_prompts, self.all_seeds, self.all_subseeds, comments=[], position_in_batch=index % self.batch_size, iteration=index // self.batch_size)
  361. def get_token_merging_ratio(self, for_hr=False):
  362. return self.token_merging_ratio_hr if for_hr else self.token_merging_ratio
  363. # from https://discuss.pytorch.org/t/help-regarding-slerp-function-for-generative-model-sampling/32475/3
  364. def slerp(val, low, high):
  365. low_norm = low/torch.norm(low, dim=1, keepdim=True)
  366. high_norm = high/torch.norm(high, dim=1, keepdim=True)
  367. dot = (low_norm*high_norm).sum(1)
  368. if dot.mean() > 0.9995:
  369. return low * val + high * (1 - val)
  370. omega = torch.acos(dot)
  371. so = torch.sin(omega)
  372. res = (torch.sin((1.0-val)*omega)/so).unsqueeze(1)*low + (torch.sin(val*omega)/so).unsqueeze(1) * high
  373. return res
  374. def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, seed_resize_from_h=0, seed_resize_from_w=0, p=None):
  375. eta_noise_seed_delta = opts.eta_noise_seed_delta or 0
  376. xs = []
  377. # if we have multiple seeds, this means we are working with batch size>1; this then
  378. # enables the generation of additional tensors with noise that the sampler will use during its processing.
  379. # Using those pre-generated tensors instead of simple torch.randn allows a batch with seeds [100, 101] to
  380. # produce the same images as with two batches [100], [101].
  381. if p is not None and p.sampler is not None and (len(seeds) > 1 and opts.enable_batch_seeds or eta_noise_seed_delta > 0):
  382. sampler_noises = [[] for _ in range(p.sampler.number_of_needed_noises(p))]
  383. else:
  384. sampler_noises = None
  385. for i, seed in enumerate(seeds):
  386. noise_shape = shape if seed_resize_from_h <= 0 or seed_resize_from_w <= 0 else (shape[0], seed_resize_from_h//8, seed_resize_from_w//8)
  387. subnoise = None
  388. if subseeds is not None:
  389. subseed = 0 if i >= len(subseeds) else subseeds[i]
  390. subnoise = devices.randn(subseed, noise_shape)
  391. # randn results depend on device; gpu and cpu get different results for same seed;
  392. # the way I see it, it's better to do this on CPU, so that everyone gets same result;
  393. # but the original script had it like this, so I do not dare change it for now because
  394. # it will break everyone's seeds.
  395. noise = devices.randn(seed, noise_shape)
  396. if subnoise is not None:
  397. noise = slerp(subseed_strength, noise, subnoise)
  398. if noise_shape != shape:
  399. x = devices.randn(seed, shape)
  400. dx = (shape[2] - noise_shape[2]) // 2
  401. dy = (shape[1] - noise_shape[1]) // 2
  402. w = noise_shape[2] if dx >= 0 else noise_shape[2] + 2 * dx
  403. h = noise_shape[1] if dy >= 0 else noise_shape[1] + 2 * dy
  404. tx = 0 if dx < 0 else dx
  405. ty = 0 if dy < 0 else dy
  406. dx = max(-dx, 0)
  407. dy = max(-dy, 0)
  408. x[:, ty:ty+h, tx:tx+w] = noise[:, dy:dy+h, dx:dx+w]
  409. noise = x
  410. if sampler_noises is not None:
  411. cnt = p.sampler.number_of_needed_noises(p)
  412. if eta_noise_seed_delta > 0:
  413. torch.manual_seed(seed + eta_noise_seed_delta)
  414. for j in range(cnt):
  415. sampler_noises[j].append(devices.randn_without_seed(tuple(noise_shape)))
  416. xs.append(noise)
  417. if sampler_noises is not None:
  418. p.sampler.sampler_noises = [torch.stack(n).to(shared.device) for n in sampler_noises]
  419. x = torch.stack(xs).to(shared.device)
  420. return x
  421. def decode_first_stage(model, x):
  422. with devices.autocast(disable=x.dtype == devices.dtype_vae):
  423. x = model.decode_first_stage(x)
  424. return x
  425. def get_fixed_seed(seed):
  426. if seed is None or seed == '' or seed == -1:
  427. return int(random.randrange(4294967294))
  428. return seed
  429. def fix_seed(p):
  430. p.seed = get_fixed_seed(p.seed)
  431. p.subseed = get_fixed_seed(p.subseed)
  432. def program_version():
  433. import launch
  434. res = launch.git_tag()
  435. if res == "<none>":
  436. res = None
  437. return res
  438. def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iteration=0, position_in_batch=0):
  439. index = position_in_batch + iteration * p.batch_size
  440. clip_skip = getattr(p, 'clip_skip', opts.CLIP_stop_at_last_layers)
  441. enable_hr = getattr(p, 'enable_hr', False)
  442. token_merging_ratio = p.get_token_merging_ratio()
  443. token_merging_ratio_hr = p.get_token_merging_ratio(for_hr=True)
  444. uses_ensd = opts.eta_noise_seed_delta != 0
  445. if uses_ensd:
  446. uses_ensd = sd_samplers_common.is_sampler_using_eta_noise_seed_delta(p)
  447. # avoid loop import
  448. from modules import sd_samplers_kdiffusion
  449. use_custom_k_sched = p.enable_custom_k_sched and p.sampler_name in sd_samplers_kdiffusion.k_diffusion_samplers_map
  450. generation_params = {
  451. "Steps": p.steps,
  452. "Sampler": p.sampler_name,
  453. "Enable Custom KDiffusion Schedule": use_custom_k_sched or None,
  454. "KDiffusion Scheduler Type": p.k_sched_type if use_custom_k_sched else None,
  455. "KDiffusion Scheduler sigma_max": p.sigma_max if use_custom_k_sched else None,
  456. "KDiffusion Scheduler sigma_min": p.sigma_min if use_custom_k_sched else None,
  457. "KDiffusion Scheduler rho": p.rho if use_custom_k_sched else None,
  458. "CFG scale": p.cfg_scale,
  459. "Image CFG scale": getattr(p, 'image_cfg_scale', None),
  460. "Seed": all_seeds[index],
  461. "Face restoration": (opts.face_restoration_model if p.restore_faces else None),
  462. "Size": f"{p.width}x{p.height}",
  463. "Model hash": getattr(p, 'sd_model_hash', None if not opts.add_model_hash_to_info or not shared.sd_model.sd_model_hash else shared.sd_model.sd_model_hash),
  464. "Model": (None if not opts.add_model_name_to_info or not shared.sd_model.sd_checkpoint_info.model_name else shared.sd_model.sd_checkpoint_info.model_name.replace(',', '').replace(':', '')),
  465. "Variation seed": (None if p.subseed_strength == 0 else all_subseeds[index]),
  466. "Variation seed strength": (None if p.subseed_strength == 0 else p.subseed_strength),
  467. "Seed resize from": (None if p.seed_resize_from_w == 0 or p.seed_resize_from_h == 0 else f"{p.seed_resize_from_w}x{p.seed_resize_from_h}"),
  468. "Denoising strength": getattr(p, 'denoising_strength', None),
  469. "Conditional mask weight": getattr(p, "inpainting_mask_weight", shared.opts.inpainting_mask_weight) if p.is_using_inpainting_conditioning else None,
  470. "Clip skip": None if clip_skip <= 1 else clip_skip,
  471. "ENSD": opts.eta_noise_seed_delta if uses_ensd else None,
  472. "Token merging ratio": None if token_merging_ratio == 0 else token_merging_ratio,
  473. "Token merging ratio hr": None if not enable_hr or token_merging_ratio_hr == 0 else token_merging_ratio_hr,
  474. "Init image hash": getattr(p, 'init_img_hash', None),
  475. "RNG": opts.randn_source if opts.randn_source != "GPU" else None,
  476. "NGMS": None if p.s_min_uncond == 0 else p.s_min_uncond,
  477. **p.extra_generation_params,
  478. "Version": program_version() if opts.add_version_to_infotext else None,
  479. }
  480. generation_params_text = ", ".join([k if k == v else f'{k}: {generation_parameters_copypaste.quote(v)}' for k, v in generation_params.items() if v is not None])
  481. negative_prompt_text = f"\nNegative prompt: {p.all_negative_prompts[index]}" if p.all_negative_prompts[index] else ""
  482. return f"{all_prompts[index]}{negative_prompt_text}\n{generation_params_text}".strip()
  483. def process_images(p: StableDiffusionProcessing) -> Processed:
  484. stored_opts = {k: opts.data[k] for k in p.override_settings.keys()}
  485. try:
  486. # if no checkpoint override or the override checkpoint can't be found, remove override entry and load opts checkpoint
  487. if sd_models.checkpoint_alisases.get(p.override_settings.get('sd_model_checkpoint')) is None:
  488. p.override_settings.pop('sd_model_checkpoint', None)
  489. sd_models.reload_model_weights()
  490. for k, v in p.override_settings.items():
  491. setattr(opts, k, v)
  492. if k == 'sd_model_checkpoint':
  493. sd_models.reload_model_weights()
  494. if k == 'sd_vae':
  495. sd_vae.reload_vae_weights()
  496. sd_models.apply_token_merging(p.sd_model, p.get_token_merging_ratio())
  497. res = process_images_inner(p)
  498. finally:
  499. sd_models.apply_token_merging(p.sd_model, 0)
  500. # restore opts to original state
  501. if p.override_settings_restore_afterwards:
  502. for k, v in stored_opts.items():
  503. setattr(opts, k, v)
  504. if k == 'sd_vae':
  505. sd_vae.reload_vae_weights()
  506. return res
  507. def process_images_inner(p: StableDiffusionProcessing) -> Processed:
  508. """this is the main loop that both txt2img and img2img use; it calls func_init once inside all the scopes and func_sample once per batch"""
  509. if type(p.prompt) == list:
  510. assert(len(p.prompt) > 0)
  511. else:
  512. assert p.prompt is not None
  513. devices.torch_gc()
  514. seed = get_fixed_seed(p.seed)
  515. subseed = get_fixed_seed(p.subseed)
  516. modules.sd_hijack.model_hijack.apply_circular(p.tiling)
  517. modules.sd_hijack.model_hijack.clear_comments()
  518. comments = {}
  519. p.setup_prompts()
  520. if type(seed) == list:
  521. p.all_seeds = seed
  522. else:
  523. p.all_seeds = [int(seed) + (x if p.subseed_strength == 0 else 0) for x in range(len(p.all_prompts))]
  524. if type(subseed) == list:
  525. p.all_subseeds = subseed
  526. else:
  527. p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))]
  528. def infotext(iteration=0, position_in_batch=0):
  529. return create_infotext(p, p.all_prompts, p.all_seeds, p.all_subseeds, comments, iteration, position_in_batch)
  530. if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
  531. model_hijack.embedding_db.load_textual_inversion_embeddings()
  532. if p.scripts is not None:
  533. p.scripts.process(p)
  534. infotexts = []
  535. output_images = []
  536. with torch.no_grad(), p.sd_model.ema_scope():
  537. with devices.autocast():
  538. p.init(p.all_prompts, p.all_seeds, p.all_subseeds)
  539. # for OSX, loading the model during sampling changes the generated picture, so it is loaded here
  540. if shared.opts.live_previews_enable and opts.show_progress_type == "Approx NN":
  541. sd_vae_approx.model()
  542. if state.job_count == -1:
  543. state.job_count = p.n_iter
  544. extra_network_data = None
  545. for n in range(p.n_iter):
  546. p.iteration = n
  547. if state.skipped:
  548. state.skipped = False
  549. if state.interrupted:
  550. break
  551. p.prompts = p.all_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  552. p.negative_prompts = p.all_negative_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  553. p.seeds = p.all_seeds[n * p.batch_size:(n + 1) * p.batch_size]
  554. p.subseeds = p.all_subseeds[n * p.batch_size:(n + 1) * p.batch_size]
  555. if p.scripts is not None:
  556. p.scripts.before_process_batch(p, batch_number=n, prompts=p.prompts, seeds=p.seeds, subseeds=p.subseeds)
  557. if len(p.prompts) == 0:
  558. break
  559. extra_network_data = p.parse_extra_network_prompts()
  560. if not p.disable_extra_networks:
  561. with devices.autocast():
  562. extra_networks.activate(p, extra_network_data)
  563. if p.scripts is not None:
  564. p.scripts.process_batch(p, batch_number=n, prompts=p.prompts, seeds=p.seeds, subseeds=p.subseeds)
  565. # params.txt should be saved after scripts.process_batch, since the
  566. # infotext could be modified by that callback
  567. # Example: a wildcard processed by process_batch sets an extra model
  568. # strength, which is saved as "Model Strength: 1.0" in the infotext
  569. if n == 0:
  570. with open(os.path.join(paths.data_path, "params.txt"), "w", encoding="utf8") as file:
  571. processed = Processed(p, [], p.seed, "")
  572. file.write(processed.infotext(p, 0))
  573. p.setup_conds()
  574. if len(model_hijack.comments) > 0:
  575. for comment in model_hijack.comments:
  576. comments[comment] = 1
  577. if p.n_iter > 1:
  578. shared.state.job = f"Batch {n+1} out of {p.n_iter}"
  579. with devices.without_autocast() if devices.unet_needs_upcast else devices.autocast():
  580. samples_ddim = p.sample(conditioning=p.c, unconditional_conditioning=p.uc, seeds=p.seeds, subseeds=p.subseeds, subseed_strength=p.subseed_strength, prompts=p.prompts)
  581. x_samples_ddim = [decode_first_stage(p.sd_model, samples_ddim[i:i+1].to(dtype=devices.dtype_vae))[0].cpu() for i in range(samples_ddim.size(0))]
  582. for x in x_samples_ddim:
  583. devices.test_for_nans(x, "vae")
  584. x_samples_ddim = torch.stack(x_samples_ddim).float()
  585. x_samples_ddim = torch.clamp((x_samples_ddim + 1.0) / 2.0, min=0.0, max=1.0)
  586. del samples_ddim
  587. if shared.cmd_opts.lowvram or shared.cmd_opts.medvram:
  588. lowvram.send_everything_to_cpu()
  589. devices.torch_gc()
  590. if p.scripts is not None:
  591. p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n)
  592. for i, x_sample in enumerate(x_samples_ddim):
  593. p.batch_index = i
  594. x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
  595. x_sample = x_sample.astype(np.uint8)
  596. if p.restore_faces:
  597. if opts.save and not p.do_not_save_samples and opts.save_images_before_face_restoration:
  598. images.save_image(Image.fromarray(x_sample), p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p, suffix="-before-face-restoration")
  599. devices.torch_gc()
  600. x_sample = modules.face_restoration.restore_faces(x_sample)
  601. devices.torch_gc()
  602. image = Image.fromarray(x_sample)
  603. if p.scripts is not None:
  604. pp = scripts.PostprocessImageArgs(image)
  605. p.scripts.postprocess_image(p, pp)
  606. image = pp.image
  607. if p.color_corrections is not None and i < len(p.color_corrections):
  608. if opts.save and not p.do_not_save_samples and opts.save_images_before_color_correction:
  609. image_without_cc = apply_overlay(image, p.paste_to, i, p.overlay_images)
  610. images.save_image(image_without_cc, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p, suffix="-before-color-correction")
  611. image = apply_color_correction(p.color_corrections[i], image)
  612. image = apply_overlay(image, p.paste_to, i, p.overlay_images)
  613. if opts.samples_save and not p.do_not_save_samples:
  614. images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p)
  615. text = infotext(n, i)
  616. infotexts.append(text)
  617. if opts.enable_pnginfo:
  618. image.info["parameters"] = text
  619. output_images.append(image)
  620. if hasattr(p, 'mask_for_overlay') and p.mask_for_overlay and any([opts.save_mask, opts.save_mask_composite, opts.return_mask, opts.return_mask_composite]):
  621. image_mask = p.mask_for_overlay.convert('RGB')
  622. image_mask_composite = Image.composite(image.convert('RGBA').convert('RGBa'), Image.new('RGBa', image.size), images.resize_image(2, p.mask_for_overlay, image.width, image.height).convert('L')).convert('RGBA')
  623. if opts.save_mask:
  624. images.save_image(image_mask, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p, suffix="-mask")
  625. if opts.save_mask_composite:
  626. images.save_image(image_mask_composite, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(n, i), p=p, suffix="-mask-composite")
  627. if opts.return_mask:
  628. output_images.append(image_mask)
  629. if opts.return_mask_composite:
  630. output_images.append(image_mask_composite)
  631. del x_samples_ddim
  632. devices.torch_gc()
  633. state.nextjob()
  634. p.color_corrections = None
  635. index_of_first_image = 0
  636. unwanted_grid_because_of_img_count = len(output_images) < 2 and opts.grid_only_if_multiple
  637. if (opts.return_grid or opts.grid_save) and not p.do_not_save_grid and not unwanted_grid_because_of_img_count:
  638. grid = images.image_grid(output_images, p.batch_size)
  639. if opts.return_grid:
  640. text = infotext()
  641. infotexts.insert(0, text)
  642. if opts.enable_pnginfo:
  643. grid.info["parameters"] = text
  644. output_images.insert(0, grid)
  645. index_of_first_image = 1
  646. if opts.grid_save:
  647. images.save_image(grid, p.outpath_grids, "grid", p.all_seeds[0], p.all_prompts[0], opts.grid_format, info=infotext(), short_filename=not opts.grid_extended_filename, p=p, grid=True)
  648. if not p.disable_extra_networks and extra_network_data:
  649. extra_networks.deactivate(p, extra_network_data)
  650. devices.torch_gc()
  651. res = Processed(
  652. p,
  653. images_list=output_images,
  654. seed=p.all_seeds[0],
  655. info=infotext(),
  656. comments="".join(f"{comment}\n" for comment in comments),
  657. subseed=p.all_subseeds[0],
  658. index_of_first_image=index_of_first_image,
  659. infotexts=infotexts,
  660. )
  661. if p.scripts is not None:
  662. p.scripts.postprocess(p, res)
  663. return res
  664. def old_hires_fix_first_pass_dimensions(width, height):
  665. """old algorithm for auto-calculating first pass size"""
  666. desired_pixel_count = 512 * 512
  667. actual_pixel_count = width * height
  668. scale = math.sqrt(desired_pixel_count / actual_pixel_count)
  669. width = math.ceil(scale * width / 64) * 64
  670. height = math.ceil(scale * height / 64) * 64
  671. return width, height
  672. class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
  673. sampler = None
  674. def __init__(self, enable_hr: bool = False, denoising_strength: float = 0.75, firstphase_width: int = 0, firstphase_height: int = 0, hr_scale: float = 2.0, hr_upscaler: str = None, hr_second_pass_steps: int = 0, hr_resize_x: int = 0, hr_resize_y: int = 0, hr_sampler_name: str = None, hr_prompt: str = '', hr_negative_prompt: str = '', **kwargs):
  675. super().__init__(**kwargs)
  676. self.enable_hr = enable_hr
  677. self.denoising_strength = denoising_strength
  678. self.hr_scale = hr_scale
  679. self.hr_upscaler = hr_upscaler
  680. self.hr_second_pass_steps = hr_second_pass_steps
  681. self.hr_resize_x = hr_resize_x
  682. self.hr_resize_y = hr_resize_y
  683. self.hr_upscale_to_x = hr_resize_x
  684. self.hr_upscale_to_y = hr_resize_y
  685. self.hr_sampler_name = hr_sampler_name
  686. self.hr_prompt = hr_prompt
  687. self.hr_negative_prompt = hr_negative_prompt
  688. self.all_hr_prompts = None
  689. self.all_hr_negative_prompts = None
  690. if firstphase_width != 0 or firstphase_height != 0:
  691. self.hr_upscale_to_x = self.width
  692. self.hr_upscale_to_y = self.height
  693. self.width = firstphase_width
  694. self.height = firstphase_height
  695. self.truncate_x = 0
  696. self.truncate_y = 0
  697. self.applied_old_hires_behavior_to = None
  698. self.hr_prompts = None
  699. self.hr_negative_prompts = None
  700. self.hr_extra_network_data = None
  701. self.hr_c = None
  702. self.hr_uc = None
  703. def init(self, all_prompts, all_seeds, all_subseeds):
  704. if self.enable_hr:
  705. if self.hr_sampler_name is not None and self.hr_sampler_name != self.sampler_name:
  706. self.extra_generation_params["Hires sampler"] = self.hr_sampler_name
  707. if tuple(self.hr_prompt) != tuple(self.prompt):
  708. self.extra_generation_params["Hires prompt"] = self.hr_prompt
  709. if tuple(self.hr_negative_prompt) != tuple(self.negative_prompt):
  710. self.extra_generation_params["Hires negative prompt"] = self.hr_negative_prompt
  711. if opts.use_old_hires_fix_width_height and self.applied_old_hires_behavior_to != (self.width, self.height):
  712. self.hr_resize_x = self.width
  713. self.hr_resize_y = self.height
  714. self.hr_upscale_to_x = self.width
  715. self.hr_upscale_to_y = self.height
  716. self.width, self.height = old_hires_fix_first_pass_dimensions(self.width, self.height)
  717. self.applied_old_hires_behavior_to = (self.width, self.height)
  718. if self.hr_resize_x == 0 and self.hr_resize_y == 0:
  719. self.extra_generation_params["Hires upscale"] = self.hr_scale
  720. self.hr_upscale_to_x = int(self.width * self.hr_scale)
  721. self.hr_upscale_to_y = int(self.height * self.hr_scale)
  722. else:
  723. self.extra_generation_params["Hires resize"] = f"{self.hr_resize_x}x{self.hr_resize_y}"
  724. if self.hr_resize_y == 0:
  725. self.hr_upscale_to_x = self.hr_resize_x
  726. self.hr_upscale_to_y = self.hr_resize_x * self.height // self.width
  727. elif self.hr_resize_x == 0:
  728. self.hr_upscale_to_x = self.hr_resize_y * self.width // self.height
  729. self.hr_upscale_to_y = self.hr_resize_y
  730. else:
  731. target_w = self.hr_resize_x
  732. target_h = self.hr_resize_y
  733. src_ratio = self.width / self.height
  734. dst_ratio = self.hr_resize_x / self.hr_resize_y
  735. if src_ratio < dst_ratio:
  736. self.hr_upscale_to_x = self.hr_resize_x
  737. self.hr_upscale_to_y = self.hr_resize_x * self.height // self.width
  738. else:
  739. self.hr_upscale_to_x = self.hr_resize_y * self.width // self.height
  740. self.hr_upscale_to_y = self.hr_resize_y
  741. self.truncate_x = (self.hr_upscale_to_x - target_w) // opt_f
  742. self.truncate_y = (self.hr_upscale_to_y - target_h) // opt_f
  743. # special case: the user has chosen to do nothing
  744. if self.hr_upscale_to_x == self.width and self.hr_upscale_to_y == self.height:
  745. self.enable_hr = False
  746. self.denoising_strength = None
  747. self.extra_generation_params.pop("Hires upscale", None)
  748. self.extra_generation_params.pop("Hires resize", None)
  749. return
  750. if not state.processing_has_refined_job_count:
  751. if state.job_count == -1:
  752. state.job_count = self.n_iter
  753. shared.total_tqdm.updateTotal((self.steps + (self.hr_second_pass_steps or self.steps)) * state.job_count)
  754. state.job_count = state.job_count * 2
  755. state.processing_has_refined_job_count = True
  756. if self.hr_second_pass_steps:
  757. self.extra_generation_params["Hires steps"] = self.hr_second_pass_steps
  758. if self.hr_upscaler is not None:
  759. self.extra_generation_params["Hires upscaler"] = self.hr_upscaler
  760. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  761. self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
  762. latent_scale_mode = shared.latent_upscale_modes.get(self.hr_upscaler, None) if self.hr_upscaler is not None else shared.latent_upscale_modes.get(shared.latent_upscale_default_mode, "nearest")
  763. if self.enable_hr and latent_scale_mode is None:
  764. assert len([x for x in shared.sd_upscalers if x.name == self.hr_upscaler]) > 0, f"could not find upscaler named {self.hr_upscaler}"
  765. x = create_random_tensors([opt_C, self.height // opt_f, self.width // opt_f], seeds=seeds, subseeds=subseeds, subseed_strength=self.subseed_strength, seed_resize_from_h=self.seed_resize_from_h, seed_resize_from_w=self.seed_resize_from_w, p=self)
  766. samples = self.sampler.sample(self, x, conditioning, unconditional_conditioning, image_conditioning=self.txt2img_image_conditioning(x))
  767. if not self.enable_hr:
  768. return samples
  769. self.is_hr_pass = True
  770. target_width = self.hr_upscale_to_x
  771. target_height = self.hr_upscale_to_y
  772. def save_intermediate(image, index):
  773. """saves image before applying hires fix, if enabled in options; takes as an argument either an image or batch with latent space images"""
  774. if not opts.save or self.do_not_save_samples or not opts.save_images_before_highres_fix:
  775. return
  776. if not isinstance(image, Image.Image):
  777. image = sd_samplers.sample_to_image(image, index, approximation=0)
  778. info = create_infotext(self, self.all_prompts, self.all_seeds, self.all_subseeds, [], iteration=self.iteration, position_in_batch=index)
  779. images.save_image(image, self.outpath_samples, "", seeds[index], prompts[index], opts.samples_format, info=info, suffix="-before-highres-fix")
  780. if latent_scale_mode is not None:
  781. for i in range(samples.shape[0]):
  782. save_intermediate(samples, i)
  783. samples = torch.nn.functional.interpolate(samples, size=(target_height // opt_f, target_width // opt_f), mode=latent_scale_mode["mode"], antialias=latent_scale_mode["antialias"])
  784. # Avoid making the inpainting conditioning unless necessary as
  785. # this does need some extra compute to decode / encode the image again.
  786. if getattr(self, "inpainting_mask_weight", shared.opts.inpainting_mask_weight) < 1.0:
  787. image_conditioning = self.img2img_image_conditioning(decode_first_stage(self.sd_model, samples), samples)
  788. else:
  789. image_conditioning = self.txt2img_image_conditioning(samples)
  790. else:
  791. decoded_samples = decode_first_stage(self.sd_model, samples)
  792. lowres_samples = torch.clamp((decoded_samples + 1.0) / 2.0, min=0.0, max=1.0)
  793. batch_images = []
  794. for i, x_sample in enumerate(lowres_samples):
  795. x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
  796. x_sample = x_sample.astype(np.uint8)
  797. image = Image.fromarray(x_sample)
  798. save_intermediate(image, i)
  799. image = images.resize_image(0, image, target_width, target_height, upscaler_name=self.hr_upscaler)
  800. image = np.array(image).astype(np.float32) / 255.0
  801. image = np.moveaxis(image, 2, 0)
  802. batch_images.append(image)
  803. decoded_samples = torch.from_numpy(np.array(batch_images))
  804. decoded_samples = decoded_samples.to(shared.device)
  805. decoded_samples = 2. * decoded_samples - 1.
  806. samples = self.sd_model.get_first_stage_encoding(self.sd_model.encode_first_stage(decoded_samples))
  807. image_conditioning = self.img2img_image_conditioning(decoded_samples, samples)
  808. shared.state.nextjob()
  809. img2img_sampler_name = self.hr_sampler_name or self.sampler_name
  810. if self.sampler_name in ['PLMS', 'UniPC']: # PLMS/UniPC do not support img2img so we just silently switch to DDIM
  811. img2img_sampler_name = 'DDIM'
  812. self.sampler = sd_samplers.create_sampler(img2img_sampler_name, self.sd_model)
  813. samples = samples[:, :, self.truncate_y//2:samples.shape[2]-(self.truncate_y+1)//2, self.truncate_x//2:samples.shape[3]-(self.truncate_x+1)//2]
  814. noise = create_random_tensors(samples.shape[1:], seeds=seeds, subseeds=subseeds, subseed_strength=subseed_strength, p=self)
  815. # GC now before running the next img2img to prevent running out of memory
  816. x = None
  817. devices.torch_gc()
  818. if not self.disable_extra_networks:
  819. with devices.autocast():
  820. extra_networks.activate(self, self.hr_extra_network_data)
  821. sd_models.apply_token_merging(self.sd_model, self.get_token_merging_ratio(for_hr=True))
  822. samples = self.sampler.sample_img2img(self, samples, noise, self.hr_c, self.hr_uc, steps=self.hr_second_pass_steps or self.steps, image_conditioning=image_conditioning)
  823. sd_models.apply_token_merging(self.sd_model, self.get_token_merging_ratio())
  824. self.is_hr_pass = False
  825. return samples
  826. def close(self):
  827. self.hr_c = None
  828. self.hr_uc = None
  829. def setup_prompts(self):
  830. super().setup_prompts()
  831. if not self.enable_hr:
  832. return
  833. if self.hr_prompt == '':
  834. self.hr_prompt = self.prompt
  835. if self.hr_negative_prompt == '':
  836. self.hr_negative_prompt = self.negative_prompt
  837. if type(self.hr_prompt) == list:
  838. self.all_hr_prompts = self.hr_prompt
  839. else:
  840. self.all_hr_prompts = self.batch_size * self.n_iter * [self.hr_prompt]
  841. if type(self.hr_negative_prompt) == list:
  842. self.all_hr_negative_prompts = self.hr_negative_prompt
  843. else:
  844. self.all_hr_negative_prompts = self.batch_size * self.n_iter * [self.hr_negative_prompt]
  845. self.all_hr_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_hr_prompts]
  846. self.all_hr_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_hr_negative_prompts]
  847. def setup_conds(self):
  848. super().setup_conds()
  849. if self.enable_hr:
  850. self.hr_uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, self.hr_negative_prompts, self.steps * self.step_multiplier, self.cached_uc)
  851. self.hr_c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, self.hr_prompts, self.steps * self.step_multiplier, self.cached_c)
  852. def parse_extra_network_prompts(self):
  853. res = super().parse_extra_network_prompts()
  854. if self.enable_hr:
  855. self.hr_prompts = self.all_hr_prompts[self.iteration * self.batch_size:(self.iteration + 1) * self.batch_size]
  856. self.hr_negative_prompts = self.all_hr_negative_prompts[self.iteration * self.batch_size:(self.iteration + 1) * self.batch_size]
  857. self.hr_prompts, self.hr_extra_network_data = extra_networks.parse_prompts(self.hr_prompts)
  858. return res
  859. class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
  860. sampler = None
  861. def __init__(self, init_images: list = None, resize_mode: int = 0, denoising_strength: float = 0.75, image_cfg_scale: float = None, mask: Any = None, mask_blur: int = 4, inpainting_fill: int = 0, inpaint_full_res: bool = True, inpaint_full_res_padding: int = 0, inpainting_mask_invert: int = 0, initial_noise_multiplier: float = None, **kwargs):
  862. super().__init__(**kwargs)
  863. self.init_images = init_images
  864. self.resize_mode: int = resize_mode
  865. self.denoising_strength: float = denoising_strength
  866. self.image_cfg_scale: float = image_cfg_scale if shared.sd_model.cond_stage_key == "edit" else None
  867. self.init_latent = None
  868. self.image_mask = mask
  869. self.latent_mask = None
  870. self.mask_for_overlay = None
  871. self.mask_blur = mask_blur
  872. self.inpainting_fill = inpainting_fill
  873. self.inpaint_full_res = inpaint_full_res
  874. self.inpaint_full_res_padding = inpaint_full_res_padding
  875. self.inpainting_mask_invert = inpainting_mask_invert
  876. self.initial_noise_multiplier = opts.initial_noise_multiplier if initial_noise_multiplier is None else initial_noise_multiplier
  877. self.mask = None
  878. self.nmask = None
  879. self.image_conditioning = None
  880. def init(self, all_prompts, all_seeds, all_subseeds):
  881. self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
  882. crop_region = None
  883. image_mask = self.image_mask
  884. if image_mask is not None:
  885. image_mask = image_mask.convert('L')
  886. if self.inpainting_mask_invert:
  887. image_mask = ImageOps.invert(image_mask)
  888. if self.mask_blur > 0:
  889. image_mask = image_mask.filter(ImageFilter.GaussianBlur(self.mask_blur))
  890. if self.inpaint_full_res:
  891. self.mask_for_overlay = image_mask
  892. mask = image_mask.convert('L')
  893. crop_region = masking.get_crop_region(np.array(mask), self.inpaint_full_res_padding)
  894. crop_region = masking.expand_crop_region(crop_region, self.width, self.height, mask.width, mask.height)
  895. x1, y1, x2, y2 = crop_region
  896. mask = mask.crop(crop_region)
  897. image_mask = images.resize_image(2, mask, self.width, self.height)
  898. self.paste_to = (x1, y1, x2-x1, y2-y1)
  899. else:
  900. image_mask = images.resize_image(self.resize_mode, image_mask, self.width, self.height)
  901. np_mask = np.array(image_mask)
  902. np_mask = np.clip((np_mask.astype(np.float32)) * 2, 0, 255).astype(np.uint8)
  903. self.mask_for_overlay = Image.fromarray(np_mask)
  904. self.overlay_images = []
  905. latent_mask = self.latent_mask if self.latent_mask is not None else image_mask
  906. add_color_corrections = opts.img2img_color_correction and self.color_corrections is None
  907. if add_color_corrections:
  908. self.color_corrections = []
  909. imgs = []
  910. for img in self.init_images:
  911. # Save init image
  912. if opts.save_init_img:
  913. self.init_img_hash = hashlib.md5(img.tobytes()).hexdigest()
  914. images.save_image(img, path=opts.outdir_init_images, basename=None, forced_filename=self.init_img_hash, save_to_dirs=False)
  915. image = images.flatten(img, opts.img2img_background_color)
  916. if crop_region is None and self.resize_mode != 3:
  917. image = images.resize_image(self.resize_mode, image, self.width, self.height)
  918. if image_mask is not None:
  919. image_masked = Image.new('RGBa', (image.width, image.height))
  920. image_masked.paste(image.convert("RGBA").convert("RGBa"), mask=ImageOps.invert(self.mask_for_overlay.convert('L')))
  921. self.overlay_images.append(image_masked.convert('RGBA'))
  922. # crop_region is not None if we are doing inpaint full res
  923. if crop_region is not None:
  924. image = image.crop(crop_region)
  925. image = images.resize_image(2, image, self.width, self.height)
  926. if image_mask is not None:
  927. if self.inpainting_fill != 1:
  928. image = masking.fill(image, latent_mask)
  929. if add_color_corrections:
  930. self.color_corrections.append(setup_color_correction(image))
  931. image = np.array(image).astype(np.float32) / 255.0
  932. image = np.moveaxis(image, 2, 0)
  933. imgs.append(image)
  934. if len(imgs) == 1:
  935. batch_images = np.expand_dims(imgs[0], axis=0).repeat(self.batch_size, axis=0)
  936. if self.overlay_images is not None:
  937. self.overlay_images = self.overlay_images * self.batch_size
  938. if self.color_corrections is not None and len(self.color_corrections) == 1:
  939. self.color_corrections = self.color_corrections * self.batch_size
  940. elif len(imgs) <= self.batch_size:
  941. self.batch_size = len(imgs)
  942. batch_images = np.array(imgs)
  943. else:
  944. raise RuntimeError(f"bad number of images passed: {len(imgs)}; expecting {self.batch_size} or less")
  945. image = torch.from_numpy(batch_images)
  946. image = 2. * image - 1.
  947. image = image.to(shared.device)
  948. self.init_latent = self.sd_model.get_first_stage_encoding(self.sd_model.encode_first_stage(image))
  949. if self.resize_mode == 3:
  950. self.init_latent = torch.nn.functional.interpolate(self.init_latent, size=(self.height // opt_f, self.width // opt_f), mode="bilinear")
  951. if image_mask is not None:
  952. init_mask = latent_mask
  953. latmask = init_mask.convert('RGB').resize((self.init_latent.shape[3], self.init_latent.shape[2]))
  954. latmask = np.moveaxis(np.array(latmask, dtype=np.float32), 2, 0) / 255
  955. latmask = latmask[0]
  956. latmask = np.around(latmask)
  957. latmask = np.tile(latmask[None], (4, 1, 1))
  958. self.mask = torch.asarray(1.0 - latmask).to(shared.device).type(self.sd_model.dtype)
  959. self.nmask = torch.asarray(latmask).to(shared.device).type(self.sd_model.dtype)
  960. # this needs to be fixed to be done in sample() using actual seeds for batches
  961. if self.inpainting_fill == 2:
  962. self.init_latent = self.init_latent * self.mask + create_random_tensors(self.init_latent.shape[1:], all_seeds[0:self.init_latent.shape[0]]) * self.nmask
  963. elif self.inpainting_fill == 3:
  964. self.init_latent = self.init_latent * self.mask
  965. self.image_conditioning = self.img2img_image_conditioning(image, self.init_latent, image_mask)
  966. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  967. x = create_random_tensors([opt_C, self.height // opt_f, self.width // opt_f], seeds=seeds, subseeds=subseeds, subseed_strength=self.subseed_strength, seed_resize_from_h=self.seed_resize_from_h, seed_resize_from_w=self.seed_resize_from_w, p=self)
  968. if self.initial_noise_multiplier != 1.0:
  969. self.extra_generation_params["Noise multiplier"] = self.initial_noise_multiplier
  970. x *= self.initial_noise_multiplier
  971. samples = self.sampler.sample_img2img(self, self.init_latent, x, conditioning, unconditional_conditioning, image_conditioning=self.image_conditioning)
  972. if self.mask is not None:
  973. samples = samples * self.nmask + self.init_latent * self.mask
  974. del x
  975. devices.torch_gc()
  976. return samples
  977. def get_token_merging_ratio(self, for_hr=False):
  978. return self.token_merging_ratio or ("token_merging_ratio" in self.override_settings and opts.token_merging_ratio) or opts.token_merging_ratio_img2img or opts.token_merging_ratio