processing.py 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823
  1. from __future__ import annotations
  2. import json
  3. import logging
  4. import math
  5. import os
  6. import sys
  7. import hashlib
  8. from dataclasses import dataclass, field
  9. import torch
  10. import numpy as np
  11. from PIL import Image, ImageOps
  12. import random
  13. import cv2
  14. from skimage import exposure
  15. from typing import Any
  16. import modules.sd_hijack
  17. from modules import devices, prompt_parser, masking, sd_samplers, lowvram, infotext_utils, extra_networks, sd_vae_approx, scripts, sd_samplers_common, sd_unet, errors, rng, profiling, util
  18. from modules.rng import slerp # noqa: F401
  19. from modules.sd_hijack import model_hijack
  20. from modules.sd_samplers_common import images_tensor_to_samples, decode_first_stage, approximation_indexes
  21. from modules.shared import opts, cmd_opts, state
  22. import modules.shared as shared
  23. import modules.paths as paths
  24. import modules.face_restoration
  25. import modules.images as images
  26. import modules.styles
  27. import modules.sd_models as sd_models
  28. import modules.sd_vae as sd_vae
  29. from ldm.data.util import AddMiDaS
  30. from ldm.models.diffusion.ddpm import LatentDepth2ImageDiffusion
  31. from einops import repeat, rearrange
  32. from blendmodes.blend import blendLayers, BlendType
  33. # some of those options should not be changed at all because they would break the model, so I removed them from options.
  34. opt_C = 4
  35. opt_f = 8
  36. def setup_color_correction(image):
  37. logging.info("Calibrating color correction.")
  38. correction_target = cv2.cvtColor(np.asarray(image.copy()), cv2.COLOR_RGB2LAB)
  39. return correction_target
  40. def apply_color_correction(correction, original_image):
  41. logging.info("Applying color correction.")
  42. image = Image.fromarray(cv2.cvtColor(exposure.match_histograms(
  43. cv2.cvtColor(
  44. np.asarray(original_image),
  45. cv2.COLOR_RGB2LAB
  46. ),
  47. correction,
  48. channel_axis=2
  49. ), cv2.COLOR_LAB2RGB).astype("uint8"))
  50. image = blendLayers(image, original_image, BlendType.LUMINOSITY)
  51. return image.convert('RGB')
  52. def uncrop(image, dest_size, paste_loc):
  53. x, y, w, h = paste_loc
  54. base_image = Image.new('RGBA', dest_size)
  55. image = images.resize_image(1, image, w, h)
  56. base_image.paste(image, (x, y))
  57. image = base_image
  58. return image
  59. def apply_overlay(image, paste_loc, overlay):
  60. if overlay is None:
  61. return image, image.copy()
  62. if paste_loc is not None:
  63. image = uncrop(image, (overlay.width, overlay.height), paste_loc)
  64. original_denoised_image = image.copy()
  65. image = image.convert('RGBA')
  66. image.alpha_composite(overlay)
  67. image = image.convert('RGB')
  68. return image, original_denoised_image
  69. def create_binary_mask(image, round=True):
  70. if image.mode == 'RGBA' and image.getextrema()[-1] != (255, 255):
  71. if round:
  72. image = image.split()[-1].convert("L").point(lambda x: 255 if x > 128 else 0)
  73. else:
  74. image = image.split()[-1].convert("L")
  75. else:
  76. image = image.convert('L')
  77. return image
  78. def txt2img_image_conditioning(sd_model, x, width, height):
  79. if sd_model.model.conditioning_key in {'hybrid', 'concat'}: # Inpainting models
  80. # The "masked-image" in this case will just be all 0.5 since the entire image is masked.
  81. image_conditioning = torch.ones(x.shape[0], 3, height, width, device=x.device) * 0.5
  82. image_conditioning = images_tensor_to_samples(image_conditioning, approximation_indexes.get(opts.sd_vae_encode_method))
  83. # Add the fake full 1s mask to the first dimension.
  84. image_conditioning = torch.nn.functional.pad(image_conditioning, (0, 0, 0, 0, 1, 0), value=1.0)
  85. image_conditioning = image_conditioning.to(x.dtype)
  86. return image_conditioning
  87. elif sd_model.model.conditioning_key == "crossattn-adm": # UnCLIP models
  88. return x.new_zeros(x.shape[0], 2*sd_model.noise_augmentor.time_embed.dim, dtype=x.dtype, device=x.device)
  89. else:
  90. if sd_model.is_sdxl_inpaint:
  91. # The "masked-image" in this case will just be all 0.5 since the entire image is masked.
  92. image_conditioning = torch.ones(x.shape[0], 3, height, width, device=x.device) * 0.5
  93. image_conditioning = images_tensor_to_samples(image_conditioning,
  94. approximation_indexes.get(opts.sd_vae_encode_method))
  95. # Add the fake full 1s mask to the first dimension.
  96. image_conditioning = torch.nn.functional.pad(image_conditioning, (0, 0, 0, 0, 1, 0), value=1.0)
  97. image_conditioning = image_conditioning.to(x.dtype)
  98. return image_conditioning
  99. # Dummy zero conditioning if we're not using inpainting or unclip models.
  100. # Still takes up a bit of memory, but no encoder call.
  101. # Pretty sure we can just make this a 1x1 image since its not going to be used besides its batch size.
  102. return x.new_zeros(x.shape[0], 5, 1, 1, dtype=x.dtype, device=x.device)
  103. @dataclass(repr=False)
  104. class StableDiffusionProcessing:
  105. sd_model: object = None
  106. outpath_samples: str = None
  107. outpath_grids: str = None
  108. prompt: str = ""
  109. prompt_for_display: str = None
  110. negative_prompt: str = ""
  111. styles: list[str] = None
  112. seed: int = -1
  113. subseed: int = -1
  114. subseed_strength: float = 0
  115. seed_resize_from_h: int = -1
  116. seed_resize_from_w: int = -1
  117. seed_enable_extras: bool = True
  118. sampler_name: str = None
  119. scheduler: str = None
  120. batch_size: int = 1
  121. n_iter: int = 1
  122. steps: int = 50
  123. cfg_scale: float = 7.0
  124. width: int = 512
  125. height: int = 512
  126. restore_faces: bool = None
  127. tiling: bool = None
  128. do_not_save_samples: bool = False
  129. do_not_save_grid: bool = False
  130. extra_generation_params: dict[str, Any] = None
  131. overlay_images: list = None
  132. eta: float = None
  133. do_not_reload_embeddings: bool = False
  134. denoising_strength: float = None
  135. ddim_discretize: str = None
  136. s_min_uncond: float = None
  137. s_churn: float = None
  138. s_tmax: float = None
  139. s_tmin: float = None
  140. s_noise: float = None
  141. override_settings: dict[str, Any] = None
  142. override_settings_restore_afterwards: bool = True
  143. sampler_index: int = None
  144. refiner_checkpoint: str = None
  145. refiner_switch_at: float = None
  146. token_merging_ratio = 0
  147. token_merging_ratio_hr = 0
  148. disable_extra_networks: bool = False
  149. firstpass_image: Image = None
  150. scripts_value: scripts.ScriptRunner = field(default=None, init=False)
  151. script_args_value: list = field(default=None, init=False)
  152. scripts_setup_complete: bool = field(default=False, init=False)
  153. cached_uc = [None, None]
  154. cached_c = [None, None]
  155. comments: dict = None
  156. sampler: sd_samplers_common.Sampler | None = field(default=None, init=False)
  157. is_using_inpainting_conditioning: bool = field(default=False, init=False)
  158. paste_to: tuple | None = field(default=None, init=False)
  159. is_hr_pass: bool = field(default=False, init=False)
  160. c: tuple = field(default=None, init=False)
  161. uc: tuple = field(default=None, init=False)
  162. rng: rng.ImageRNG | None = field(default=None, init=False)
  163. step_multiplier: int = field(default=1, init=False)
  164. color_corrections: list = field(default=None, init=False)
  165. all_prompts: list = field(default=None, init=False)
  166. all_negative_prompts: list = field(default=None, init=False)
  167. all_seeds: list = field(default=None, init=False)
  168. all_subseeds: list = field(default=None, init=False)
  169. iteration: int = field(default=0, init=False)
  170. main_prompt: str = field(default=None, init=False)
  171. main_negative_prompt: str = field(default=None, init=False)
  172. prompts: list = field(default=None, init=False)
  173. negative_prompts: list = field(default=None, init=False)
  174. seeds: list = field(default=None, init=False)
  175. subseeds: list = field(default=None, init=False)
  176. extra_network_data: dict = field(default=None, init=False)
  177. user: str = field(default=None, init=False)
  178. sd_model_name: str = field(default=None, init=False)
  179. sd_model_hash: str = field(default=None, init=False)
  180. sd_vae_name: str = field(default=None, init=False)
  181. sd_vae_hash: str = field(default=None, init=False)
  182. is_api: bool = field(default=False, init=False)
  183. def __post_init__(self):
  184. if self.sampler_index is not None:
  185. print("sampler_index argument for StableDiffusionProcessing does not do anything; use sampler_name", file=sys.stderr)
  186. self.comments = {}
  187. if self.styles is None:
  188. self.styles = []
  189. self.sampler_noise_scheduler_override = None
  190. self.extra_generation_params = self.extra_generation_params or {}
  191. self.override_settings = self.override_settings or {}
  192. self.script_args = self.script_args or {}
  193. self.refiner_checkpoint_info = None
  194. if not self.seed_enable_extras:
  195. self.subseed = -1
  196. self.subseed_strength = 0
  197. self.seed_resize_from_h = 0
  198. self.seed_resize_from_w = 0
  199. self.cached_uc = StableDiffusionProcessing.cached_uc
  200. self.cached_c = StableDiffusionProcessing.cached_c
  201. def fill_fields_from_opts(self):
  202. self.s_min_uncond = self.s_min_uncond if self.s_min_uncond is not None else opts.s_min_uncond
  203. self.s_churn = self.s_churn if self.s_churn is not None else opts.s_churn
  204. self.s_tmin = self.s_tmin if self.s_tmin is not None else opts.s_tmin
  205. self.s_tmax = (self.s_tmax if self.s_tmax is not None else opts.s_tmax) or float('inf')
  206. self.s_noise = self.s_noise if self.s_noise is not None else opts.s_noise
  207. @property
  208. def sd_model(self):
  209. return shared.sd_model
  210. @sd_model.setter
  211. def sd_model(self, value):
  212. pass
  213. @property
  214. def scripts(self):
  215. return self.scripts_value
  216. @scripts.setter
  217. def scripts(self, value):
  218. self.scripts_value = value
  219. if self.scripts_value and self.script_args_value and not self.scripts_setup_complete:
  220. self.setup_scripts()
  221. @property
  222. def script_args(self):
  223. return self.script_args_value
  224. @script_args.setter
  225. def script_args(self, value):
  226. self.script_args_value = value
  227. if self.scripts_value and self.script_args_value and not self.scripts_setup_complete:
  228. self.setup_scripts()
  229. def setup_scripts(self):
  230. self.scripts_setup_complete = True
  231. self.scripts.setup_scrips(self, is_ui=not self.is_api)
  232. def comment(self, text):
  233. self.comments[text] = 1
  234. def txt2img_image_conditioning(self, x, width=None, height=None):
  235. self.is_using_inpainting_conditioning = self.sd_model.model.conditioning_key in {'hybrid', 'concat'}
  236. return txt2img_image_conditioning(self.sd_model, x, width or self.width, height or self.height)
  237. def depth2img_image_conditioning(self, source_image):
  238. # Use the AddMiDaS helper to Format our source image to suit the MiDaS model
  239. transformer = AddMiDaS(model_type="dpt_hybrid")
  240. transformed = transformer({"jpg": rearrange(source_image[0], "c h w -> h w c")})
  241. midas_in = torch.from_numpy(transformed["midas_in"][None, ...]).to(device=shared.device)
  242. midas_in = repeat(midas_in, "1 ... -> n ...", n=self.batch_size)
  243. conditioning_image = images_tensor_to_samples(source_image*0.5+0.5, approximation_indexes.get(opts.sd_vae_encode_method))
  244. conditioning = torch.nn.functional.interpolate(
  245. self.sd_model.depth_model(midas_in),
  246. size=conditioning_image.shape[2:],
  247. mode="bicubic",
  248. align_corners=False,
  249. )
  250. (depth_min, depth_max) = torch.aminmax(conditioning)
  251. conditioning = 2. * (conditioning - depth_min) / (depth_max - depth_min) - 1.
  252. return conditioning
  253. def edit_image_conditioning(self, source_image):
  254. conditioning_image = shared.sd_model.encode_first_stage(source_image).mode()
  255. return conditioning_image
  256. def unclip_image_conditioning(self, source_image):
  257. c_adm = self.sd_model.embedder(source_image)
  258. if self.sd_model.noise_augmentor is not None:
  259. noise_level = 0 # TODO: Allow other noise levels?
  260. 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]))
  261. c_adm = torch.cat((c_adm, noise_level_emb), 1)
  262. return c_adm
  263. def inpainting_image_conditioning(self, source_image, latent_image, image_mask=None, round_image_mask=True):
  264. self.is_using_inpainting_conditioning = True
  265. # Handle the different mask inputs
  266. if image_mask is not None:
  267. if torch.is_tensor(image_mask):
  268. conditioning_mask = image_mask
  269. else:
  270. conditioning_mask = np.array(image_mask.convert("L"))
  271. conditioning_mask = conditioning_mask.astype(np.float32) / 255.0
  272. conditioning_mask = torch.from_numpy(conditioning_mask[None, None])
  273. if round_image_mask:
  274. # Caller is requesting a discretized mask as input, so we round to either 1.0 or 0.0
  275. conditioning_mask = torch.round(conditioning_mask)
  276. else:
  277. conditioning_mask = source_image.new_ones(1, 1, *source_image.shape[-2:])
  278. # Create another latent image, this time with a masked version of the original input.
  279. # Smoothly interpolate between the masked and unmasked latent conditioning image using a parameter.
  280. conditioning_mask = conditioning_mask.to(device=source_image.device, dtype=source_image.dtype)
  281. conditioning_image = torch.lerp(
  282. source_image,
  283. source_image * (1.0 - conditioning_mask),
  284. getattr(self, "inpainting_mask_weight", shared.opts.inpainting_mask_weight)
  285. )
  286. # Encode the new masked image using first stage of network.
  287. conditioning_image = self.sd_model.get_first_stage_encoding(self.sd_model.encode_first_stage(conditioning_image))
  288. # Create the concatenated conditioning tensor to be fed to `c_concat`
  289. conditioning_mask = torch.nn.functional.interpolate(conditioning_mask, size=latent_image.shape[-2:])
  290. conditioning_mask = conditioning_mask.expand(conditioning_image.shape[0], -1, -1, -1)
  291. image_conditioning = torch.cat([conditioning_mask, conditioning_image], dim=1)
  292. image_conditioning = image_conditioning.to(shared.device).type(self.sd_model.dtype)
  293. return image_conditioning
  294. def img2img_image_conditioning(self, source_image, latent_image, image_mask=None, round_image_mask=True):
  295. source_image = devices.cond_cast_float(source_image)
  296. # HACK: Using introspection as the Depth2Image model doesn't appear to uniquely
  297. # identify itself with a field common to all models. The conditioning_key is also hybrid.
  298. if isinstance(self.sd_model, LatentDepth2ImageDiffusion):
  299. return self.depth2img_image_conditioning(source_image)
  300. if self.sd_model.cond_stage_key == "edit":
  301. return self.edit_image_conditioning(source_image)
  302. if self.sampler.conditioning_key in {'hybrid', 'concat'}:
  303. return self.inpainting_image_conditioning(source_image, latent_image, image_mask=image_mask, round_image_mask=round_image_mask)
  304. if self.sampler.conditioning_key == "crossattn-adm":
  305. return self.unclip_image_conditioning(source_image)
  306. if self.sampler.model_wrap.inner_model.is_sdxl_inpaint:
  307. return self.inpainting_image_conditioning(source_image, latent_image, image_mask=image_mask)
  308. # Dummy zero conditioning if we're not using inpainting or depth model.
  309. return latent_image.new_zeros(latent_image.shape[0], 5, 1, 1)
  310. def init(self, all_prompts, all_seeds, all_subseeds):
  311. pass
  312. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  313. raise NotImplementedError()
  314. def close(self):
  315. self.sampler = None
  316. self.c = None
  317. self.uc = None
  318. if not opts.persistent_cond_cache:
  319. StableDiffusionProcessing.cached_c = [None, None]
  320. StableDiffusionProcessing.cached_uc = [None, None]
  321. def get_token_merging_ratio(self, for_hr=False):
  322. if for_hr:
  323. return self.token_merging_ratio_hr or opts.token_merging_ratio_hr or self.token_merging_ratio or opts.token_merging_ratio
  324. return self.token_merging_ratio or opts.token_merging_ratio
  325. def setup_prompts(self):
  326. if isinstance(self.prompt,list):
  327. self.all_prompts = self.prompt
  328. elif isinstance(self.negative_prompt, list):
  329. self.all_prompts = [self.prompt] * len(self.negative_prompt)
  330. else:
  331. self.all_prompts = self.batch_size * self.n_iter * [self.prompt]
  332. if isinstance(self.negative_prompt, list):
  333. self.all_negative_prompts = self.negative_prompt
  334. else:
  335. self.all_negative_prompts = [self.negative_prompt] * len(self.all_prompts)
  336. if len(self.all_prompts) != len(self.all_negative_prompts):
  337. raise RuntimeError(f"Received a different number of prompts ({len(self.all_prompts)}) and negative prompts ({len(self.all_negative_prompts)})")
  338. self.all_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_prompts]
  339. self.all_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_negative_prompts]
  340. self.main_prompt = self.all_prompts[0]
  341. self.main_negative_prompt = self.all_negative_prompts[0]
  342. def cached_params(self, required_prompts, steps, extra_network_data, hires_steps=None, use_old_scheduling=False):
  343. """Returns parameters that invalidate the cond cache if changed"""
  344. return (
  345. required_prompts,
  346. steps,
  347. hires_steps,
  348. use_old_scheduling,
  349. opts.CLIP_stop_at_last_layers,
  350. shared.sd_model.sd_checkpoint_info,
  351. extra_network_data,
  352. opts.sdxl_crop_left,
  353. opts.sdxl_crop_top,
  354. self.width,
  355. self.height,
  356. opts.fp8_storage,
  357. opts.cache_fp16_weight,
  358. opts.emphasis,
  359. )
  360. def apply_generation_params_list(self, generation_params_states):
  361. """add and apply generation_params_states to self.extra_generation_params"""
  362. for key, value in generation_params_states.items():
  363. if key in self.extra_generation_params and isinstance(current_value := self.extra_generation_params[key], util.GenerationParametersList):
  364. self.extra_generation_params[key] = current_value + value
  365. else:
  366. self.extra_generation_params[key] = value
  367. def clear_marked_generation_params(self):
  368. """clears any generation parameters that are with the attribute to_be_clear_before_batch = True"""
  369. for key, value in list(self.extra_generation_params.items()):
  370. if getattr(value, 'to_be_clear_before_batch', False):
  371. self.extra_generation_params.pop(key)
  372. def get_conds_with_caching(self, function, required_prompts, steps, caches, extra_network_data, hires_steps=None):
  373. """
  374. Returns the result of calling function(shared.sd_model, required_prompts, steps)
  375. using a cache to store the result if the same arguments have been used before.
  376. cache is an array containing two elements. The first element is a tuple
  377. representing the previously used arguments, or None if no arguments
  378. have been used before. The second element is where the previously
  379. computed result is stored.
  380. caches is a list with items described above.
  381. """
  382. if shared.opts.use_old_scheduling:
  383. old_schedules = prompt_parser.get_learned_conditioning_prompt_schedules(required_prompts, steps, hires_steps, False)
  384. new_schedules = prompt_parser.get_learned_conditioning_prompt_schedules(required_prompts, steps, hires_steps, True)
  385. if old_schedules != new_schedules:
  386. self.extra_generation_params["Old prompt editing timelines"] = True
  387. cached_params = self.cached_params(required_prompts, steps, extra_network_data, hires_steps, shared.opts.use_old_scheduling)
  388. for cache in caches:
  389. if cache[0] is not None and cached_params == cache[0]:
  390. if len(cache) == 3:
  391. generation_params_states, cached_cached_params = cache[2]
  392. if cached_params == cached_cached_params:
  393. self.apply_generation_params_list(generation_params_states)
  394. return cache[1]
  395. cache = caches[0]
  396. with devices.autocast():
  397. cache[1] = function(shared.sd_model, required_prompts, steps, hires_steps, shared.opts.use_old_scheduling)
  398. generation_params_states = model_hijack.extract_generation_params_states()
  399. self.apply_generation_params_list(generation_params_states)
  400. if len(cache) == 2:
  401. cache.append((generation_params_states, cached_params))
  402. else:
  403. cache[2] = (generation_params_states, cached_params)
  404. cache[0] = cached_params
  405. return cache[1]
  406. def setup_conds(self):
  407. prompts = prompt_parser.SdConditioning(self.prompts, width=self.width, height=self.height)
  408. negative_prompts = prompt_parser.SdConditioning(self.negative_prompts, width=self.width, height=self.height, is_negative_prompt=True)
  409. sampler_config = sd_samplers.find_sampler_config(self.sampler_name)
  410. total_steps = sampler_config.total_steps(self.steps) if sampler_config else self.steps
  411. self.step_multiplier = total_steps // self.steps
  412. self.firstpass_steps = total_steps
  413. self.uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, negative_prompts, total_steps, [self.cached_uc], self.extra_network_data)
  414. self.c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, prompts, total_steps, [self.cached_c], self.extra_network_data)
  415. self.extra_generation_params.update(model_hijack.extra_generation_params)
  416. def get_conds(self):
  417. return self.c, self.uc
  418. def parse_extra_network_prompts(self):
  419. self.prompts, self.extra_network_data = extra_networks.parse_prompts(self.prompts)
  420. def save_samples(self) -> bool:
  421. """Returns whether generated images need to be written to disk"""
  422. return opts.samples_save and not self.do_not_save_samples and (opts.save_incomplete_images or not state.interrupted and not state.skipped)
  423. class Processed:
  424. 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=""):
  425. self.images = images_list
  426. self.prompt = p.prompt
  427. self.negative_prompt = p.negative_prompt
  428. self.seed = seed
  429. self.subseed = subseed
  430. self.subseed_strength = p.subseed_strength
  431. self.info = info
  432. self.comments = "".join(f"{comment}\n" for comment in p.comments)
  433. self.width = p.width
  434. self.height = p.height
  435. self.sampler_name = p.sampler_name
  436. self.cfg_scale = p.cfg_scale
  437. self.image_cfg_scale = getattr(p, 'image_cfg_scale', None)
  438. self.steps = p.steps
  439. self.batch_size = p.batch_size
  440. self.restore_faces = p.restore_faces
  441. self.face_restoration_model = opts.face_restoration_model if p.restore_faces else None
  442. self.sd_model_name = p.sd_model_name
  443. self.sd_model_hash = p.sd_model_hash
  444. self.sd_vae_name = p.sd_vae_name
  445. self.sd_vae_hash = p.sd_vae_hash
  446. self.seed_resize_from_w = p.seed_resize_from_w
  447. self.seed_resize_from_h = p.seed_resize_from_h
  448. self.denoising_strength = getattr(p, 'denoising_strength', None)
  449. self.extra_generation_params = p.extra_generation_params
  450. self.index_of_first_image = index_of_first_image
  451. self.styles = p.styles
  452. self.job_timestamp = state.job_timestamp
  453. self.clip_skip = opts.CLIP_stop_at_last_layers
  454. self.token_merging_ratio = p.token_merging_ratio
  455. self.token_merging_ratio_hr = p.token_merging_ratio_hr
  456. self.eta = p.eta
  457. self.ddim_discretize = p.ddim_discretize
  458. self.s_churn = p.s_churn
  459. self.s_tmin = p.s_tmin
  460. self.s_tmax = p.s_tmax
  461. self.s_noise = p.s_noise
  462. self.s_min_uncond = p.s_min_uncond
  463. self.sampler_noise_scheduler_override = p.sampler_noise_scheduler_override
  464. self.prompt = self.prompt if not isinstance(self.prompt, list) else self.prompt[0]
  465. self.negative_prompt = self.negative_prompt if not isinstance(self.negative_prompt, list) else self.negative_prompt[0]
  466. self.seed = int(self.seed if not isinstance(self.seed, list) else self.seed[0]) if self.seed is not None else -1
  467. self.subseed = int(self.subseed if not isinstance(self.subseed, list) else self.subseed[0]) if self.subseed is not None else -1
  468. self.is_using_inpainting_conditioning = p.is_using_inpainting_conditioning
  469. self.all_prompts = all_prompts or p.all_prompts or [self.prompt]
  470. self.all_negative_prompts = all_negative_prompts or p.all_negative_prompts or [self.negative_prompt]
  471. self.all_seeds = all_seeds or p.all_seeds or [self.seed]
  472. self.all_subseeds = all_subseeds or p.all_subseeds or [self.subseed]
  473. self.infotexts = infotexts or [info] * len(images_list)
  474. self.version = program_version()
  475. def js(self):
  476. obj = {
  477. "prompt": self.all_prompts[0],
  478. "all_prompts": self.all_prompts,
  479. "negative_prompt": self.all_negative_prompts[0],
  480. "all_negative_prompts": self.all_negative_prompts,
  481. "seed": self.seed,
  482. "all_seeds": self.all_seeds,
  483. "subseed": self.subseed,
  484. "all_subseeds": self.all_subseeds,
  485. "subseed_strength": self.subseed_strength,
  486. "width": self.width,
  487. "height": self.height,
  488. "sampler_name": self.sampler_name,
  489. "cfg_scale": self.cfg_scale,
  490. "steps": self.steps,
  491. "batch_size": self.batch_size,
  492. "restore_faces": self.restore_faces,
  493. "face_restoration_model": self.face_restoration_model,
  494. "sd_model_name": self.sd_model_name,
  495. "sd_model_hash": self.sd_model_hash,
  496. "sd_vae_name": self.sd_vae_name,
  497. "sd_vae_hash": self.sd_vae_hash,
  498. "seed_resize_from_w": self.seed_resize_from_w,
  499. "seed_resize_from_h": self.seed_resize_from_h,
  500. "denoising_strength": self.denoising_strength,
  501. "extra_generation_params": self.extra_generation_params,
  502. "index_of_first_image": self.index_of_first_image,
  503. "infotexts": self.infotexts,
  504. "styles": self.styles,
  505. "job_timestamp": self.job_timestamp,
  506. "clip_skip": self.clip_skip,
  507. "is_using_inpainting_conditioning": self.is_using_inpainting_conditioning,
  508. "version": self.version,
  509. }
  510. return json.dumps(obj, default=lambda o: None)
  511. def infotext(self, p: StableDiffusionProcessing, index):
  512. 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)
  513. def get_token_merging_ratio(self, for_hr=False):
  514. return self.token_merging_ratio_hr if for_hr else self.token_merging_ratio
  515. def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, seed_resize_from_h=0, seed_resize_from_w=0, p=None):
  516. g = rng.ImageRNG(shape, seeds, subseeds=subseeds, subseed_strength=subseed_strength, seed_resize_from_h=seed_resize_from_h, seed_resize_from_w=seed_resize_from_w)
  517. return g.next()
  518. class DecodedSamples(list):
  519. already_decoded = True
  520. def decode_latent_batch(model, batch, target_device=None, check_for_nans=False):
  521. samples = DecodedSamples()
  522. if check_for_nans:
  523. devices.test_for_nans(batch, "unet")
  524. for i in range(batch.shape[0]):
  525. sample = decode_first_stage(model, batch[i:i + 1])[0]
  526. if check_for_nans:
  527. try:
  528. devices.test_for_nans(sample, "vae")
  529. except devices.NansException as e:
  530. if shared.opts.auto_vae_precision_bfloat16:
  531. autofix_dtype = torch.bfloat16
  532. autofix_dtype_text = "bfloat16"
  533. autofix_dtype_setting = "Automatically convert VAE to bfloat16"
  534. autofix_dtype_comment = ""
  535. elif shared.opts.auto_vae_precision:
  536. autofix_dtype = torch.float32
  537. autofix_dtype_text = "32-bit float"
  538. autofix_dtype_setting = "Automatically revert VAE to 32-bit floats"
  539. autofix_dtype_comment = "\nTo always start with 32-bit VAE, use --no-half-vae commandline flag."
  540. else:
  541. raise e
  542. if devices.dtype_vae == autofix_dtype:
  543. raise e
  544. errors.print_error_explanation(
  545. "A tensor with all NaNs was produced in VAE.\n"
  546. f"Web UI will now convert VAE into {autofix_dtype_text} and retry.\n"
  547. f"To disable this behavior, disable the '{autofix_dtype_setting}' setting.{autofix_dtype_comment}"
  548. )
  549. devices.dtype_vae = autofix_dtype
  550. model.first_stage_model.to(devices.dtype_vae)
  551. batch = batch.to(devices.dtype_vae)
  552. sample = decode_first_stage(model, batch[i:i + 1])[0]
  553. if target_device is not None:
  554. sample = sample.to(target_device)
  555. samples.append(sample)
  556. return samples
  557. def get_fixed_seed(seed):
  558. if seed == '' or seed is None:
  559. seed = -1
  560. elif isinstance(seed, str):
  561. try:
  562. seed = int(seed)
  563. except Exception:
  564. seed = -1
  565. if seed == -1:
  566. return int(random.randrange(4294967294))
  567. return seed
  568. def fix_seed(p):
  569. p.seed = get_fixed_seed(p.seed)
  570. p.subseed = get_fixed_seed(p.subseed)
  571. def program_version():
  572. import launch
  573. res = launch.git_tag()
  574. if res == "<none>":
  575. res = None
  576. return res
  577. def create_infotext(p, all_prompts, all_seeds, all_subseeds, comments=None, iteration=0, position_in_batch=0, use_main_prompt=False, index=None, all_negative_prompts=None):
  578. """
  579. this function is used to generate the infotext that is stored in the generated images, it's contains the parameters that are required to generate the imagee
  580. Args:
  581. p: StableDiffusionProcessing
  582. all_prompts: list[str]
  583. all_seeds: list[int]
  584. all_subseeds: list[int]
  585. comments: list[str]
  586. iteration: int
  587. position_in_batch: int
  588. use_main_prompt: bool
  589. index: int
  590. all_negative_prompts: list[str]
  591. Returns: str
  592. Extra generation params
  593. p.extra_generation_params dictionary allows for additional parameters to be added to the infotext
  594. this can be use by the base webui or extensions.
  595. To add a new entry, add a new key value pair, the dictionary key will be used as the key of the parameter in the infotext
  596. the value generation_params can be defined as:
  597. - str | None
  598. - List[str|None]
  599. - callable func(**kwargs) -> str | None
  600. When defined as a string, it will be used as without extra processing; this is this most common use case.
  601. Defining as a list allows for parameter that changes across images in the job, for example, the 'Seed' parameter.
  602. The list should have the same length as the total number of images in the entire job.
  603. Defining as a callable function allows parameter cannot be generated earlier or when extra logic is required.
  604. For example 'Hires prompt', due to reasons the hr_prompt might be changed by process in the pipeline or extensions
  605. and may vary across different images, defining as a static string or list would not work.
  606. The function takes locals() as **kwargs, as such will have access to variables like 'p' and 'index'.
  607. the base signature of the function should be:
  608. func(**kwargs) -> str | None
  609. optionally it can have additional arguments that will be used in the function:
  610. func(p, index, **kwargs) -> str | None
  611. note: for better future compatibility even though this function will have access to all variables in the locals(),
  612. it is recommended to only use the arguments present in the function signature of create_infotext.
  613. For actual implementation examples, see StableDiffusionProcessingTxt2Img.init > get_hr_prompt.
  614. """
  615. if use_main_prompt:
  616. index = 0
  617. elif index is None:
  618. index = position_in_batch + iteration * p.batch_size
  619. if all_negative_prompts is None:
  620. all_negative_prompts = p.all_negative_prompts
  621. clip_skip = getattr(p, 'clip_skip', opts.CLIP_stop_at_last_layers)
  622. enable_hr = getattr(p, 'enable_hr', False)
  623. token_merging_ratio = p.get_token_merging_ratio()
  624. token_merging_ratio_hr = p.get_token_merging_ratio(for_hr=True)
  625. prompt_text = p.main_prompt if use_main_prompt else all_prompts[index]
  626. negative_prompt = p.main_negative_prompt if use_main_prompt else all_negative_prompts[index]
  627. uses_ensd = opts.eta_noise_seed_delta != 0
  628. if uses_ensd:
  629. uses_ensd = sd_samplers_common.is_sampler_using_eta_noise_seed_delta(p)
  630. generation_params = {
  631. "Steps": p.steps,
  632. "Sampler": p.sampler_name,
  633. "Schedule type": p.scheduler,
  634. "CFG scale": p.cfg_scale,
  635. "Image CFG scale": getattr(p, 'image_cfg_scale', None),
  636. "Seed": p.all_seeds[0] if use_main_prompt else all_seeds[index],
  637. "Face restoration": opts.face_restoration_model if p.restore_faces else None,
  638. "Size": f"{p.width}x{p.height}",
  639. "Model hash": p.sd_model_hash if opts.add_model_hash_to_info else None,
  640. "Model": p.sd_model_name if opts.add_model_name_to_info else None,
  641. "FP8 weight": opts.fp8_storage if devices.fp8 else None,
  642. "Cache FP16 weight for LoRA": opts.cache_fp16_weight if devices.fp8 else None,
  643. "VAE hash": p.sd_vae_hash if opts.add_vae_hash_to_info else None,
  644. "VAE": p.sd_vae_name if opts.add_vae_name_to_info else None,
  645. "Variation seed": (None if p.subseed_strength == 0 else (p.all_subseeds[0] if use_main_prompt else all_subseeds[index])),
  646. "Variation seed strength": (None if p.subseed_strength == 0 else p.subseed_strength),
  647. "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}"),
  648. "Denoising strength": p.extra_generation_params.get("Denoising strength"),
  649. "Conditional mask weight": getattr(p, "inpainting_mask_weight", shared.opts.inpainting_mask_weight) if p.is_using_inpainting_conditioning else None,
  650. "Clip skip": None if clip_skip <= 1 else clip_skip,
  651. "ENSD": opts.eta_noise_seed_delta if uses_ensd else None,
  652. "Token merging ratio": None if token_merging_ratio == 0 else token_merging_ratio,
  653. "Token merging ratio hr": None if not enable_hr or token_merging_ratio_hr == 0 else token_merging_ratio_hr,
  654. "Init image hash": getattr(p, 'init_img_hash', None),
  655. "RNG": opts.randn_source if opts.randn_source != "GPU" else None,
  656. "Tiling": "True" if p.tiling else None,
  657. **p.extra_generation_params,
  658. "Version": program_version() if opts.add_version_to_infotext else None,
  659. "User": p.user if opts.add_user_name_to_info else None,
  660. }
  661. for key, value in generation_params.items():
  662. try:
  663. if callable(value):
  664. generation_params[key] = value(**locals())
  665. elif isinstance(value, list):
  666. generation_params[key] = value[index]
  667. except Exception:
  668. errors.report(f'Error creating infotext for key "{key}"', exc_info=True)
  669. generation_params[key] = None
  670. generation_params_text = ", ".join([k if k == v else f'{k}: {infotext_utils.quote(v)}' for k, v in generation_params.items() if v is not None])
  671. negative_prompt_text = f"\nNegative prompt: {negative_prompt}" if negative_prompt else ""
  672. return f"{prompt_text}{negative_prompt_text}\n{generation_params_text}".strip()
  673. def process_images(p: StableDiffusionProcessing) -> Processed:
  674. if p.scripts is not None:
  675. p.scripts.before_process(p)
  676. stored_opts = {k: opts.data[k] if k in opts.data else opts.get_default(k) for k in p.override_settings.keys() if k in opts.data}
  677. try:
  678. # if no checkpoint override or the override checkpoint can't be found, remove override entry and load opts checkpoint
  679. # and if after running refiner, the refiner model is not unloaded - webui swaps back to main model here, if model over is present it will be reloaded afterwards
  680. if sd_models.checkpoint_aliases.get(p.override_settings.get('sd_model_checkpoint')) is None:
  681. p.override_settings.pop('sd_model_checkpoint', None)
  682. sd_models.reload_model_weights()
  683. for k, v in p.override_settings.items():
  684. opts.set(k, v, is_api=True, run_callbacks=False)
  685. if k == 'sd_model_checkpoint':
  686. sd_models.reload_model_weights()
  687. if k == 'sd_vae':
  688. sd_vae.reload_vae_weights()
  689. sd_models.apply_token_merging(p.sd_model, p.get_token_merging_ratio())
  690. # backwards compatibility, fix sampler and scheduler if invalid
  691. sd_samplers.fix_p_invalid_sampler_and_scheduler(p)
  692. with profiling.Profiler():
  693. res = process_images_inner(p)
  694. finally:
  695. sd_models.apply_token_merging(p.sd_model, 0)
  696. # restore opts to original state
  697. if p.override_settings_restore_afterwards:
  698. for k, v in stored_opts.items():
  699. setattr(opts, k, v)
  700. if k == 'sd_vae':
  701. sd_vae.reload_vae_weights()
  702. return res
  703. def process_images_inner(p: StableDiffusionProcessing) -> Processed:
  704. """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"""
  705. if isinstance(p.prompt, list):
  706. assert(len(p.prompt) > 0)
  707. else:
  708. assert p.prompt is not None
  709. devices.torch_gc()
  710. seed = get_fixed_seed(p.seed)
  711. subseed = get_fixed_seed(p.subseed)
  712. if p.restore_faces is None:
  713. p.restore_faces = opts.face_restoration
  714. if p.tiling is None:
  715. p.tiling = opts.tiling
  716. if p.refiner_checkpoint not in (None, "", "None", "none"):
  717. p.refiner_checkpoint_info = sd_models.get_closet_checkpoint_match(p.refiner_checkpoint)
  718. if p.refiner_checkpoint_info is None:
  719. raise Exception(f'Could not find checkpoint with name {p.refiner_checkpoint}')
  720. if hasattr(shared.sd_model, 'fix_dimensions'):
  721. p.width, p.height = shared.sd_model.fix_dimensions(p.width, p.height)
  722. p.sd_model_name = shared.sd_model.sd_checkpoint_info.name_for_extra
  723. p.sd_model_hash = shared.sd_model.sd_model_hash
  724. p.sd_vae_name = sd_vae.get_loaded_vae_name()
  725. p.sd_vae_hash = sd_vae.get_loaded_vae_hash()
  726. modules.sd_hijack.model_hijack.apply_circular(p.tiling)
  727. modules.sd_hijack.model_hijack.clear_comments()
  728. p.fill_fields_from_opts()
  729. p.setup_prompts()
  730. if isinstance(seed, list):
  731. p.all_seeds = seed
  732. else:
  733. p.all_seeds = [int(seed) + (x if p.subseed_strength == 0 else 0) for x in range(len(p.all_prompts))]
  734. if isinstance(subseed, list):
  735. p.all_subseeds = subseed
  736. else:
  737. p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))]
  738. if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
  739. model_hijack.embedding_db.load_textual_inversion_embeddings()
  740. if p.scripts is not None:
  741. p.scripts.process(p)
  742. infotexts = []
  743. output_images = []
  744. with torch.no_grad(), p.sd_model.ema_scope():
  745. with devices.autocast():
  746. p.init(p.all_prompts, p.all_seeds, p.all_subseeds)
  747. # for OSX, loading the model during sampling changes the generated picture, so it is loaded here
  748. if shared.opts.live_previews_enable and opts.show_progress_type == "Approx NN":
  749. sd_vae_approx.model()
  750. sd_unet.apply_unet()
  751. if state.job_count == -1:
  752. state.job_count = p.n_iter
  753. for n in range(p.n_iter):
  754. p.iteration = n
  755. if state.skipped:
  756. state.skipped = False
  757. if state.interrupted or state.stopping_generation:
  758. break
  759. p.clear_marked_generation_params() # clean up some generation params are tagged to be cleared before batch
  760. sd_models.reload_model_weights() # model can be changed for example by refiner
  761. p.prompts = p.all_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  762. p.negative_prompts = p.all_negative_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  763. p.seeds = p.all_seeds[n * p.batch_size:(n + 1) * p.batch_size]
  764. p.subseeds = p.all_subseeds[n * p.batch_size:(n + 1) * p.batch_size]
  765. latent_channels = getattr(shared.sd_model, 'latent_channels', opt_C)
  766. p.rng = rng.ImageRNG((latent_channels, p.height // opt_f, p.width // opt_f), p.seeds, subseeds=p.subseeds, subseed_strength=p.subseed_strength, seed_resize_from_h=p.seed_resize_from_h, seed_resize_from_w=p.seed_resize_from_w)
  767. if p.scripts is not None:
  768. p.scripts.before_process_batch(p, batch_number=n, prompts=p.prompts, seeds=p.seeds, subseeds=p.subseeds)
  769. if len(p.prompts) == 0:
  770. break
  771. p.parse_extra_network_prompts()
  772. if not p.disable_extra_networks:
  773. with devices.autocast():
  774. extra_networks.activate(p, p.extra_network_data)
  775. if p.scripts is not None:
  776. p.scripts.process_batch(p, batch_number=n, prompts=p.prompts, seeds=p.seeds, subseeds=p.subseeds)
  777. p.setup_conds()
  778. # params.txt should be saved after scripts.process_batch, since the
  779. # infotext could be modified by that callback
  780. # Example: a wildcard processed by process_batch sets an extra model
  781. # strength, which is saved as "Model Strength: 1.0" in the infotext
  782. if n == 0 and not cmd_opts.no_prompt_history:
  783. with open(os.path.join(paths.data_path, "params.txt"), "w", encoding="utf8") as file:
  784. processed = Processed(p, [])
  785. file.write(processed.infotext(p, 0))
  786. for comment in model_hijack.comments:
  787. p.comment(comment)
  788. if p.n_iter > 1:
  789. shared.state.job = f"Batch {n+1} out of {p.n_iter}"
  790. sd_models.apply_alpha_schedule_override(p.sd_model, p)
  791. with devices.without_autocast() if devices.unet_needs_upcast else devices.autocast():
  792. 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)
  793. if p.scripts is not None:
  794. ps = scripts.PostSampleArgs(samples_ddim)
  795. p.scripts.post_sample(p, ps)
  796. samples_ddim = ps.samples
  797. if getattr(samples_ddim, 'already_decoded', False):
  798. x_samples_ddim = samples_ddim
  799. else:
  800. devices.test_for_nans(samples_ddim, "unet")
  801. if opts.sd_vae_decode_method != 'Full':
  802. p.extra_generation_params['VAE Decoder'] = opts.sd_vae_decode_method
  803. x_samples_ddim = decode_latent_batch(p.sd_model, samples_ddim, target_device=devices.cpu, check_for_nans=True)
  804. x_samples_ddim = torch.stack(x_samples_ddim).float()
  805. x_samples_ddim = torch.clamp((x_samples_ddim + 1.0) / 2.0, min=0.0, max=1.0)
  806. del samples_ddim
  807. if lowvram.is_enabled(shared.sd_model):
  808. lowvram.send_everything_to_cpu()
  809. devices.torch_gc()
  810. state.nextjob()
  811. if p.scripts is not None:
  812. p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n)
  813. p.prompts = p.all_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  814. p.negative_prompts = p.all_negative_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  815. batch_params = scripts.PostprocessBatchListArgs(list(x_samples_ddim))
  816. p.scripts.postprocess_batch_list(p, batch_params, batch_number=n)
  817. x_samples_ddim = batch_params.images
  818. def infotext(index=0, use_main_prompt=False):
  819. return create_infotext(p, p.prompts, p.seeds, p.subseeds, use_main_prompt=use_main_prompt, index=index, all_negative_prompts=p.negative_prompts)
  820. save_samples = p.save_samples()
  821. for i, x_sample in enumerate(x_samples_ddim):
  822. p.batch_index = i
  823. x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
  824. x_sample = x_sample.astype(np.uint8)
  825. if p.restore_faces:
  826. if save_samples and opts.save_images_before_face_restoration:
  827. images.save_image(Image.fromarray(x_sample), p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-before-face-restoration")
  828. devices.torch_gc()
  829. x_sample = modules.face_restoration.restore_faces(x_sample)
  830. devices.torch_gc()
  831. image = Image.fromarray(x_sample)
  832. if p.scripts is not None:
  833. pp = scripts.PostprocessImageArgs(image)
  834. p.scripts.postprocess_image(p, pp)
  835. image = pp.image
  836. mask_for_overlay = getattr(p, "mask_for_overlay", None)
  837. if not shared.opts.overlay_inpaint:
  838. overlay_image = None
  839. elif getattr(p, "overlay_images", None) is not None and i < len(p.overlay_images):
  840. overlay_image = p.overlay_images[i]
  841. else:
  842. overlay_image = None
  843. if p.scripts is not None:
  844. ppmo = scripts.PostProcessMaskOverlayArgs(i, mask_for_overlay, overlay_image)
  845. p.scripts.postprocess_maskoverlay(p, ppmo)
  846. mask_for_overlay, overlay_image = ppmo.mask_for_overlay, ppmo.overlay_image
  847. if p.color_corrections is not None and i < len(p.color_corrections):
  848. if save_samples and opts.save_images_before_color_correction:
  849. image_without_cc, _ = apply_overlay(image, p.paste_to, overlay_image)
  850. images.save_image(image_without_cc, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-before-color-correction")
  851. image = apply_color_correction(p.color_corrections[i], image)
  852. # If the intention is to show the output from the model
  853. # that is being composited over the original image,
  854. # we need to keep the original image around
  855. # and use it in the composite step.
  856. image, original_denoised_image = apply_overlay(image, p.paste_to, overlay_image)
  857. if p.scripts is not None:
  858. pp = scripts.PostprocessImageArgs(image)
  859. p.scripts.postprocess_image_after_composite(p, pp)
  860. image = pp.image
  861. if save_samples:
  862. images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p)
  863. text = infotext(i)
  864. infotexts.append(text)
  865. if opts.enable_pnginfo:
  866. image.info["parameters"] = text
  867. output_images.append(image)
  868. if mask_for_overlay is not None:
  869. if opts.return_mask or opts.save_mask:
  870. image_mask = mask_for_overlay.convert('RGB')
  871. if save_samples and opts.save_mask:
  872. images.save_image(image_mask, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-mask")
  873. if opts.return_mask:
  874. output_images.append(image_mask)
  875. if opts.return_mask_composite or opts.save_mask_composite:
  876. image_mask_composite = Image.composite(original_denoised_image.convert('RGBA').convert('RGBa'), Image.new('RGBa', image.size), images.resize_image(2, mask_for_overlay, image.width, image.height).convert('L')).convert('RGBA')
  877. if save_samples and opts.save_mask_composite:
  878. images.save_image(image_mask_composite, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-mask-composite")
  879. if opts.return_mask_composite:
  880. output_images.append(image_mask_composite)
  881. del x_samples_ddim
  882. devices.torch_gc()
  883. if not infotexts:
  884. infotexts.append(Processed(p, []).infotext(p, 0))
  885. p.color_corrections = None
  886. index_of_first_image = 0
  887. unwanted_grid_because_of_img_count = len(output_images) < 2 and opts.grid_only_if_multiple
  888. if (opts.return_grid or opts.grid_save) and not p.do_not_save_grid and not unwanted_grid_because_of_img_count:
  889. grid = images.image_grid(output_images, p.batch_size)
  890. if opts.return_grid:
  891. text = infotext(use_main_prompt=True)
  892. infotexts.insert(0, text)
  893. if opts.enable_pnginfo:
  894. grid.info["parameters"] = text
  895. output_images.insert(0, grid)
  896. index_of_first_image = 1
  897. if opts.grid_save:
  898. images.save_image(grid, p.outpath_grids, "grid", p.all_seeds[0], p.all_prompts[0], opts.grid_format, info=infotext(use_main_prompt=True), short_filename=not opts.grid_extended_filename, p=p, grid=True)
  899. if not p.disable_extra_networks and p.extra_network_data:
  900. extra_networks.deactivate(p, p.extra_network_data)
  901. devices.torch_gc()
  902. res = Processed(
  903. p,
  904. images_list=output_images,
  905. seed=p.all_seeds[0],
  906. info=infotexts[0],
  907. subseed=p.all_subseeds[0],
  908. index_of_first_image=index_of_first_image,
  909. infotexts=infotexts,
  910. )
  911. if p.scripts is not None:
  912. p.scripts.postprocess(p, res)
  913. return res
  914. def old_hires_fix_first_pass_dimensions(width, height):
  915. """old algorithm for auto-calculating first pass size"""
  916. desired_pixel_count = 512 * 512
  917. actual_pixel_count = width * height
  918. scale = math.sqrt(desired_pixel_count / actual_pixel_count)
  919. width = math.ceil(scale * width / 64) * 64
  920. height = math.ceil(scale * height / 64) * 64
  921. return width, height
  922. @dataclass(repr=False)
  923. class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
  924. enable_hr: bool = False
  925. denoising_strength: float = 0.75
  926. firstphase_width: int = 0
  927. firstphase_height: int = 0
  928. hr_scale: float = 2.0
  929. hr_upscaler: str = None
  930. hr_second_pass_steps: int = 0
  931. hr_resize_x: int = 0
  932. hr_resize_y: int = 0
  933. hr_checkpoint_name: str = None
  934. hr_sampler_name: str = None
  935. hr_scheduler: str = None
  936. hr_prompt: str = ''
  937. hr_negative_prompt: str = ''
  938. force_task_id: str = None
  939. cached_hr_uc = [None, None]
  940. cached_hr_c = [None, None]
  941. hr_checkpoint_info: dict = field(default=None, init=False)
  942. hr_upscale_to_x: int = field(default=0, init=False)
  943. hr_upscale_to_y: int = field(default=0, init=False)
  944. truncate_x: int = field(default=0, init=False)
  945. truncate_y: int = field(default=0, init=False)
  946. applied_old_hires_behavior_to: tuple = field(default=None, init=False)
  947. latent_scale_mode: dict = field(default=None, init=False)
  948. hr_c: tuple | None = field(default=None, init=False)
  949. hr_uc: tuple | None = field(default=None, init=False)
  950. all_hr_prompts: list = field(default=None, init=False)
  951. all_hr_negative_prompts: list = field(default=None, init=False)
  952. hr_prompts: list = field(default=None, init=False)
  953. hr_negative_prompts: list = field(default=None, init=False)
  954. hr_extra_network_data: list = field(default=None, init=False)
  955. def __post_init__(self):
  956. super().__post_init__()
  957. if self.firstphase_width != 0 or self.firstphase_height != 0:
  958. self.hr_upscale_to_x = self.width
  959. self.hr_upscale_to_y = self.height
  960. self.width = self.firstphase_width
  961. self.height = self.firstphase_height
  962. self.cached_hr_uc = StableDiffusionProcessingTxt2Img.cached_hr_uc
  963. self.cached_hr_c = StableDiffusionProcessingTxt2Img.cached_hr_c
  964. def calculate_target_resolution(self):
  965. if opts.use_old_hires_fix_width_height and self.applied_old_hires_behavior_to != (self.width, self.height):
  966. self.hr_resize_x = self.width
  967. self.hr_resize_y = self.height
  968. self.hr_upscale_to_x = self.width
  969. self.hr_upscale_to_y = self.height
  970. self.width, self.height = old_hires_fix_first_pass_dimensions(self.width, self.height)
  971. self.applied_old_hires_behavior_to = (self.width, self.height)
  972. if self.hr_resize_x == 0 and self.hr_resize_y == 0:
  973. self.extra_generation_params["Hires upscale"] = self.hr_scale
  974. self.hr_upscale_to_x = int(self.width * self.hr_scale)
  975. self.hr_upscale_to_y = int(self.height * self.hr_scale)
  976. else:
  977. self.extra_generation_params["Hires resize"] = f"{self.hr_resize_x}x{self.hr_resize_y}"
  978. if self.hr_resize_y == 0:
  979. self.hr_upscale_to_x = self.hr_resize_x
  980. self.hr_upscale_to_y = self.hr_resize_x * self.height // self.width
  981. elif self.hr_resize_x == 0:
  982. self.hr_upscale_to_x = self.hr_resize_y * self.width // self.height
  983. self.hr_upscale_to_y = self.hr_resize_y
  984. else:
  985. target_w = self.hr_resize_x
  986. target_h = self.hr_resize_y
  987. src_ratio = self.width / self.height
  988. dst_ratio = self.hr_resize_x / self.hr_resize_y
  989. if src_ratio < dst_ratio:
  990. self.hr_upscale_to_x = self.hr_resize_x
  991. self.hr_upscale_to_y = self.hr_resize_x * self.height // self.width
  992. else:
  993. self.hr_upscale_to_x = self.hr_resize_y * self.width // self.height
  994. self.hr_upscale_to_y = self.hr_resize_y
  995. self.truncate_x = (self.hr_upscale_to_x - target_w) // opt_f
  996. self.truncate_y = (self.hr_upscale_to_y - target_h) // opt_f
  997. def init(self, all_prompts, all_seeds, all_subseeds):
  998. if self.enable_hr:
  999. self.extra_generation_params["Denoising strength"] = self.denoising_strength
  1000. if self.hr_checkpoint_name and self.hr_checkpoint_name != 'Use same checkpoint':
  1001. self.hr_checkpoint_info = sd_models.get_closet_checkpoint_match(self.hr_checkpoint_name)
  1002. if self.hr_checkpoint_info is None:
  1003. raise Exception(f'Could not find checkpoint with name {self.hr_checkpoint_name}')
  1004. if shared.sd_model.sd_checkpoint_info == self.hr_checkpoint_info:
  1005. self.hr_checkpoint_info = None
  1006. else:
  1007. self.extra_generation_params["Hires checkpoint"] = self.hr_checkpoint_info.short_title
  1008. if self.hr_sampler_name is not None and self.hr_sampler_name != self.sampler_name:
  1009. self.extra_generation_params["Hires sampler"] = self.hr_sampler_name
  1010. def get_hr_prompt(p, index, prompt_text, **kwargs):
  1011. hr_prompt = p.all_hr_prompts[index]
  1012. return hr_prompt if hr_prompt != prompt_text else None
  1013. def get_hr_negative_prompt(p, index, negative_prompt, **kwargs):
  1014. hr_negative_prompt = p.all_hr_negative_prompts[index]
  1015. return hr_negative_prompt if hr_negative_prompt != negative_prompt else None
  1016. self.extra_generation_params["Hires prompt"] = get_hr_prompt
  1017. self.extra_generation_params["Hires negative prompt"] = get_hr_negative_prompt
  1018. self.extra_generation_params["Hires schedule type"] = None # to be set in sd_samplers_kdiffusion.py
  1019. if self.hr_scheduler is None:
  1020. self.hr_scheduler = self.scheduler
  1021. self.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")
  1022. if self.enable_hr and self.latent_scale_mode is None:
  1023. if not any(x.name == self.hr_upscaler for x in shared.sd_upscalers):
  1024. raise Exception(f"could not find upscaler named {self.hr_upscaler}")
  1025. self.calculate_target_resolution()
  1026. if not state.processing_has_refined_job_count:
  1027. if state.job_count == -1:
  1028. state.job_count = self.n_iter
  1029. if getattr(self, 'txt2img_upscale', False):
  1030. total_steps = (self.hr_second_pass_steps or self.steps) * state.job_count
  1031. else:
  1032. total_steps = (self.steps + (self.hr_second_pass_steps or self.steps)) * state.job_count
  1033. shared.total_tqdm.updateTotal(total_steps)
  1034. state.job_count = state.job_count * 2
  1035. state.processing_has_refined_job_count = True
  1036. if self.hr_second_pass_steps:
  1037. self.extra_generation_params["Hires steps"] = self.hr_second_pass_steps
  1038. if self.hr_upscaler is not None:
  1039. self.extra_generation_params["Hires upscaler"] = self.hr_upscaler
  1040. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  1041. self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
  1042. if self.firstpass_image is not None and self.enable_hr:
  1043. # here we don't need to generate image, we just take self.firstpass_image and prepare it for hires fix
  1044. if self.latent_scale_mode is None:
  1045. image = np.array(self.firstpass_image).astype(np.float32) / 255.0 * 2.0 - 1.0
  1046. image = np.moveaxis(image, 2, 0)
  1047. samples = None
  1048. decoded_samples = torch.asarray(np.expand_dims(image, 0))
  1049. else:
  1050. image = np.array(self.firstpass_image).astype(np.float32) / 255.0
  1051. image = np.moveaxis(image, 2, 0)
  1052. image = torch.from_numpy(np.expand_dims(image, axis=0))
  1053. image = image.to(shared.device, dtype=devices.dtype_vae)
  1054. if opts.sd_vae_encode_method != 'Full':
  1055. self.extra_generation_params['VAE Encoder'] = opts.sd_vae_encode_method
  1056. samples = images_tensor_to_samples(image, approximation_indexes.get(opts.sd_vae_encode_method), self.sd_model)
  1057. decoded_samples = None
  1058. devices.torch_gc()
  1059. else:
  1060. # here we generate an image normally
  1061. x = self.rng.next()
  1062. if self.scripts is not None:
  1063. self.scripts.process_before_every_sampling(
  1064. p=self,
  1065. x=x,
  1066. noise=x,
  1067. c=conditioning,
  1068. uc=unconditional_conditioning
  1069. )
  1070. samples = self.sampler.sample(self, x, conditioning, unconditional_conditioning, image_conditioning=self.txt2img_image_conditioning(x))
  1071. del x
  1072. if not self.enable_hr:
  1073. return samples
  1074. devices.torch_gc()
  1075. if self.latent_scale_mode is None:
  1076. decoded_samples = torch.stack(decode_latent_batch(self.sd_model, samples, target_device=devices.cpu, check_for_nans=True)).to(dtype=torch.float32)
  1077. else:
  1078. decoded_samples = None
  1079. with sd_models.SkipWritingToConfig():
  1080. sd_models.reload_model_weights(info=self.hr_checkpoint_info)
  1081. return self.sample_hr_pass(samples, decoded_samples, seeds, subseeds, subseed_strength, prompts)
  1082. def sample_hr_pass(self, samples, decoded_samples, seeds, subseeds, subseed_strength, prompts):
  1083. if shared.state.interrupted:
  1084. return samples
  1085. self.is_hr_pass = True
  1086. target_width = self.hr_upscale_to_x
  1087. target_height = self.hr_upscale_to_y
  1088. def save_intermediate(image, index):
  1089. """saves image before applying hires fix, if enabled in options; takes as an argument either an image or batch with latent space images"""
  1090. if not self.save_samples() or not opts.save_images_before_highres_fix:
  1091. return
  1092. if not isinstance(image, Image.Image):
  1093. image = sd_samplers.sample_to_image(image, index, approximation=0)
  1094. info = create_infotext(self, self.all_prompts, self.all_seeds, self.all_subseeds, [], iteration=self.iteration, position_in_batch=index)
  1095. images.save_image(image, self.outpath_samples, "", seeds[index], prompts[index], opts.samples_format, info=info, p=self, suffix="-before-highres-fix")
  1096. img2img_sampler_name = self.hr_sampler_name or self.sampler_name
  1097. self.sampler = sd_samplers.create_sampler(img2img_sampler_name, self.sd_model)
  1098. if self.latent_scale_mode is not None:
  1099. for i in range(samples.shape[0]):
  1100. save_intermediate(samples, i)
  1101. samples = torch.nn.functional.interpolate(samples, size=(target_height // opt_f, target_width // opt_f), mode=self.latent_scale_mode["mode"], antialias=self.latent_scale_mode["antialias"])
  1102. # Avoid making the inpainting conditioning unless necessary as
  1103. # this does need some extra compute to decode / encode the image again.
  1104. if getattr(self, "inpainting_mask_weight", shared.opts.inpainting_mask_weight) < 1.0:
  1105. image_conditioning = self.img2img_image_conditioning(decode_first_stage(self.sd_model, samples), samples)
  1106. else:
  1107. image_conditioning = self.txt2img_image_conditioning(samples)
  1108. else:
  1109. lowres_samples = torch.clamp((decoded_samples + 1.0) / 2.0, min=0.0, max=1.0)
  1110. batch_images = []
  1111. for i, x_sample in enumerate(lowres_samples):
  1112. x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
  1113. x_sample = x_sample.astype(np.uint8)
  1114. image = Image.fromarray(x_sample)
  1115. save_intermediate(image, i)
  1116. image = images.resize_image(0, image, target_width, target_height, upscaler_name=self.hr_upscaler)
  1117. image = np.array(image).astype(np.float32) / 255.0
  1118. image = np.moveaxis(image, 2, 0)
  1119. batch_images.append(image)
  1120. decoded_samples = torch.from_numpy(np.array(batch_images))
  1121. decoded_samples = decoded_samples.to(shared.device, dtype=devices.dtype_vae)
  1122. if opts.sd_vae_encode_method != 'Full':
  1123. self.extra_generation_params['VAE Encoder'] = opts.sd_vae_encode_method
  1124. samples = images_tensor_to_samples(decoded_samples, approximation_indexes.get(opts.sd_vae_encode_method))
  1125. image_conditioning = self.img2img_image_conditioning(decoded_samples, samples)
  1126. shared.state.nextjob()
  1127. 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]
  1128. self.rng = rng.ImageRNG(samples.shape[1:], self.seeds, subseeds=self.subseeds, subseed_strength=self.subseed_strength, seed_resize_from_h=self.seed_resize_from_h, seed_resize_from_w=self.seed_resize_from_w)
  1129. noise = self.rng.next()
  1130. # GC now before running the next img2img to prevent running out of memory
  1131. devices.torch_gc()
  1132. if not self.disable_extra_networks:
  1133. with devices.autocast():
  1134. extra_networks.activate(self, self.hr_extra_network_data)
  1135. with devices.autocast():
  1136. self.calculate_hr_conds()
  1137. sd_models.apply_token_merging(self.sd_model, self.get_token_merging_ratio(for_hr=True))
  1138. if self.scripts is not None:
  1139. self.scripts.before_hr(self)
  1140. self.scripts.process_before_every_sampling(
  1141. p=self,
  1142. x=samples,
  1143. noise=noise,
  1144. c=self.hr_c,
  1145. uc=self.hr_uc,
  1146. )
  1147. 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)
  1148. sd_models.apply_token_merging(self.sd_model, self.get_token_merging_ratio())
  1149. self.sampler = None
  1150. devices.torch_gc()
  1151. decoded_samples = decode_latent_batch(self.sd_model, samples, target_device=devices.cpu, check_for_nans=True)
  1152. self.is_hr_pass = False
  1153. return decoded_samples
  1154. def close(self):
  1155. super().close()
  1156. self.hr_c = None
  1157. self.hr_uc = None
  1158. if not opts.persistent_cond_cache:
  1159. StableDiffusionProcessingTxt2Img.cached_hr_uc = [None, None]
  1160. StableDiffusionProcessingTxt2Img.cached_hr_c = [None, None]
  1161. def setup_prompts(self):
  1162. super().setup_prompts()
  1163. if not self.enable_hr:
  1164. return
  1165. if self.hr_prompt == '':
  1166. self.hr_prompt = self.prompt
  1167. if self.hr_negative_prompt == '':
  1168. self.hr_negative_prompt = self.negative_prompt
  1169. if isinstance(self.hr_prompt, list):
  1170. self.all_hr_prompts = self.hr_prompt
  1171. else:
  1172. self.all_hr_prompts = self.batch_size * self.n_iter * [self.hr_prompt]
  1173. if isinstance(self.hr_negative_prompt, list):
  1174. self.all_hr_negative_prompts = self.hr_negative_prompt
  1175. else:
  1176. self.all_hr_negative_prompts = self.batch_size * self.n_iter * [self.hr_negative_prompt]
  1177. self.all_hr_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_hr_prompts]
  1178. self.all_hr_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_hr_negative_prompts]
  1179. def calculate_hr_conds(self):
  1180. if self.hr_c is not None:
  1181. return
  1182. hr_prompts = prompt_parser.SdConditioning(self.hr_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y)
  1183. hr_negative_prompts = prompt_parser.SdConditioning(self.hr_negative_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y, is_negative_prompt=True)
  1184. sampler_config = sd_samplers.find_sampler_config(self.hr_sampler_name or self.sampler_name)
  1185. steps = self.hr_second_pass_steps or self.steps
  1186. total_steps = sampler_config.total_steps(steps) if sampler_config else steps
  1187. self.hr_uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, hr_negative_prompts, self.firstpass_steps, [self.cached_hr_uc, self.cached_uc], self.hr_extra_network_data, total_steps)
  1188. self.hr_c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, hr_prompts, self.firstpass_steps, [self.cached_hr_c, self.cached_c], self.hr_extra_network_data, total_steps)
  1189. self.extra_generation_params.update(model_hijack.extra_generation_params)
  1190. def setup_conds(self):
  1191. if self.is_hr_pass:
  1192. # if we are in hr pass right now, the call is being made from the refiner, and we don't need to setup firstpass cons or switch model
  1193. self.hr_c = None
  1194. self.calculate_hr_conds()
  1195. return
  1196. super().setup_conds()
  1197. self.hr_uc = None
  1198. self.hr_c = None
  1199. if self.enable_hr and self.hr_checkpoint_info is None:
  1200. if shared.opts.hires_fix_use_firstpass_conds:
  1201. self.calculate_hr_conds()
  1202. elif lowvram.is_enabled(shared.sd_model) and shared.sd_model.sd_checkpoint_info == sd_models.select_checkpoint(): # if in lowvram mode, we need to calculate conds right away, before the cond NN is unloaded
  1203. with devices.autocast():
  1204. extra_networks.activate(self, self.hr_extra_network_data)
  1205. self.calculate_hr_conds()
  1206. with devices.autocast():
  1207. extra_networks.activate(self, self.extra_network_data)
  1208. def get_conds(self):
  1209. if self.is_hr_pass:
  1210. return self.hr_c, self.hr_uc
  1211. return super().get_conds()
  1212. def parse_extra_network_prompts(self):
  1213. res = super().parse_extra_network_prompts()
  1214. if self.enable_hr:
  1215. self.hr_prompts = self.all_hr_prompts[self.iteration * self.batch_size:(self.iteration + 1) * self.batch_size]
  1216. self.hr_negative_prompts = self.all_hr_negative_prompts[self.iteration * self.batch_size:(self.iteration + 1) * self.batch_size]
  1217. self.hr_prompts, self.hr_extra_network_data = extra_networks.parse_prompts(self.hr_prompts)
  1218. return res
  1219. @dataclass(repr=False)
  1220. class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
  1221. init_images: list = None
  1222. resize_mode: int = 0
  1223. denoising_strength: float = 0.75
  1224. image_cfg_scale: float = None
  1225. mask: Any = None
  1226. mask_blur_x: int = 4
  1227. mask_blur_y: int = 4
  1228. mask_blur: int = None
  1229. mask_round: bool = True
  1230. inpainting_fill: int = 0
  1231. inpaint_full_res: bool = True
  1232. inpaint_full_res_padding: int = 0
  1233. inpainting_mask_invert: int = 0
  1234. initial_noise_multiplier: float = None
  1235. latent_mask: Image = None
  1236. force_task_id: str = None
  1237. image_mask: Any = field(default=None, init=False)
  1238. nmask: torch.Tensor = field(default=None, init=False)
  1239. image_conditioning: torch.Tensor = field(default=None, init=False)
  1240. init_img_hash: str = field(default=None, init=False)
  1241. mask_for_overlay: Image = field(default=None, init=False)
  1242. init_latent: torch.Tensor = field(default=None, init=False)
  1243. def __post_init__(self):
  1244. super().__post_init__()
  1245. self.image_mask = self.mask
  1246. self.mask = None
  1247. self.initial_noise_multiplier = opts.initial_noise_multiplier if self.initial_noise_multiplier is None else self.initial_noise_multiplier
  1248. @property
  1249. def mask_blur(self):
  1250. if self.mask_blur_x == self.mask_blur_y:
  1251. return self.mask_blur_x
  1252. return None
  1253. @mask_blur.setter
  1254. def mask_blur(self, value):
  1255. if isinstance(value, int):
  1256. self.mask_blur_x = value
  1257. self.mask_blur_y = value
  1258. def init(self, all_prompts, all_seeds, all_subseeds):
  1259. self.extra_generation_params["Denoising strength"] = self.denoising_strength
  1260. self.image_cfg_scale: float = self.image_cfg_scale if shared.sd_model.cond_stage_key == "edit" else None
  1261. self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
  1262. crop_region = None
  1263. image_mask = self.image_mask
  1264. if image_mask is not None:
  1265. # image_mask is passed in as RGBA by Gradio to support alpha masks,
  1266. # but we still want to support binary masks.
  1267. image_mask = create_binary_mask(image_mask, round=self.mask_round)
  1268. if self.inpainting_mask_invert:
  1269. image_mask = ImageOps.invert(image_mask)
  1270. self.extra_generation_params["Mask mode"] = "Inpaint not masked"
  1271. if self.mask_blur_x > 0:
  1272. np_mask = np.array(image_mask)
  1273. kernel_size = 2 * int(2.5 * self.mask_blur_x + 0.5) + 1
  1274. np_mask = cv2.GaussianBlur(np_mask, (kernel_size, 1), self.mask_blur_x)
  1275. image_mask = Image.fromarray(np_mask)
  1276. if self.mask_blur_y > 0:
  1277. np_mask = np.array(image_mask)
  1278. kernel_size = 2 * int(2.5 * self.mask_blur_y + 0.5) + 1
  1279. np_mask = cv2.GaussianBlur(np_mask, (1, kernel_size), self.mask_blur_y)
  1280. image_mask = Image.fromarray(np_mask)
  1281. if self.mask_blur_x > 0 or self.mask_blur_y > 0:
  1282. self.extra_generation_params["Mask blur"] = self.mask_blur
  1283. if self.inpaint_full_res:
  1284. self.mask_for_overlay = image_mask
  1285. mask = image_mask.convert('L')
  1286. crop_region = masking.get_crop_region_v2(mask, self.inpaint_full_res_padding)
  1287. if crop_region:
  1288. crop_region = masking.expand_crop_region(crop_region, self.width, self.height, mask.width, mask.height)
  1289. x1, y1, x2, y2 = crop_region
  1290. mask = mask.crop(crop_region)
  1291. image_mask = images.resize_image(2, mask, self.width, self.height)
  1292. self.paste_to = (x1, y1, x2-x1, y2-y1)
  1293. self.extra_generation_params["Inpaint area"] = "Only masked"
  1294. self.extra_generation_params["Masked area padding"] = self.inpaint_full_res_padding
  1295. else:
  1296. crop_region = None
  1297. image_mask = None
  1298. self.mask_for_overlay = None
  1299. self.inpaint_full_res = False
  1300. massage = 'Unable to perform "Inpaint Only mask" because mask is blank, switch to img2img mode.'
  1301. model_hijack.comments.append(massage)
  1302. logging.info(massage)
  1303. else:
  1304. image_mask = images.resize_image(self.resize_mode, image_mask, self.width, self.height)
  1305. np_mask = np.array(image_mask)
  1306. np_mask = np.clip((np_mask.astype(np.float32)) * 2, 0, 255).astype(np.uint8)
  1307. self.mask_for_overlay = Image.fromarray(np_mask)
  1308. self.overlay_images = []
  1309. latent_mask = self.latent_mask if self.latent_mask is not None else image_mask
  1310. add_color_corrections = opts.img2img_color_correction and self.color_corrections is None
  1311. if add_color_corrections:
  1312. self.color_corrections = []
  1313. imgs = []
  1314. for img in self.init_images:
  1315. # Save init image
  1316. if opts.save_init_img:
  1317. self.init_img_hash = hashlib.md5(img.tobytes()).hexdigest()
  1318. images.save_image(img, path=opts.outdir_init_images, basename=None, forced_filename=self.init_img_hash, save_to_dirs=False, existing_info=img.info)
  1319. image = images.flatten(img, opts.img2img_background_color)
  1320. if crop_region is None and self.resize_mode != 3:
  1321. image = images.resize_image(self.resize_mode, image, self.width, self.height)
  1322. if image_mask is not None:
  1323. if self.mask_for_overlay.size != (image.width, image.height):
  1324. self.mask_for_overlay = images.resize_image(self.resize_mode, self.mask_for_overlay, image.width, image.height)
  1325. image_masked = Image.new('RGBa', (image.width, image.height))
  1326. image_masked.paste(image.convert("RGBA").convert("RGBa"), mask=ImageOps.invert(self.mask_for_overlay.convert('L')))
  1327. self.overlay_images.append(image_masked.convert('RGBA'))
  1328. # crop_region is not None if we are doing inpaint full res
  1329. if crop_region is not None:
  1330. image = image.crop(crop_region)
  1331. image = images.resize_image(2, image, self.width, self.height)
  1332. if image_mask is not None:
  1333. if self.inpainting_fill != 1:
  1334. image = masking.fill(image, latent_mask)
  1335. if self.inpainting_fill == 0:
  1336. self.extra_generation_params["Masked content"] = 'fill'
  1337. if add_color_corrections:
  1338. self.color_corrections.append(setup_color_correction(image))
  1339. image = np.array(image).astype(np.float32) / 255.0
  1340. image = np.moveaxis(image, 2, 0)
  1341. imgs.append(image)
  1342. if len(imgs) == 1:
  1343. batch_images = np.expand_dims(imgs[0], axis=0).repeat(self.batch_size, axis=0)
  1344. if self.overlay_images is not None:
  1345. self.overlay_images = self.overlay_images * self.batch_size
  1346. if self.color_corrections is not None and len(self.color_corrections) == 1:
  1347. self.color_corrections = self.color_corrections * self.batch_size
  1348. elif len(imgs) <= self.batch_size:
  1349. self.batch_size = len(imgs)
  1350. batch_images = np.array(imgs)
  1351. else:
  1352. raise RuntimeError(f"bad number of images passed: {len(imgs)}; expecting {self.batch_size} or less")
  1353. image = torch.from_numpy(batch_images)
  1354. image = image.to(shared.device, dtype=devices.dtype_vae)
  1355. if opts.sd_vae_encode_method != 'Full':
  1356. self.extra_generation_params['VAE Encoder'] = opts.sd_vae_encode_method
  1357. self.init_latent = images_tensor_to_samples(image, approximation_indexes.get(opts.sd_vae_encode_method), self.sd_model)
  1358. devices.torch_gc()
  1359. if self.resize_mode == 3:
  1360. self.init_latent = torch.nn.functional.interpolate(self.init_latent, size=(self.height // opt_f, self.width // opt_f), mode="bilinear")
  1361. if image_mask is not None:
  1362. init_mask = latent_mask
  1363. latmask = init_mask.convert('RGB').resize((self.init_latent.shape[3], self.init_latent.shape[2]))
  1364. latmask = np.moveaxis(np.array(latmask, dtype=np.float32), 2, 0) / 255
  1365. latmask = latmask[0]
  1366. if self.mask_round:
  1367. latmask = np.around(latmask)
  1368. latmask = np.tile(latmask[None], (self.init_latent.shape[1], 1, 1))
  1369. self.mask = torch.asarray(1.0 - latmask).to(shared.device).type(devices.dtype)
  1370. self.nmask = torch.asarray(latmask).to(shared.device).type(devices.dtype)
  1371. # this needs to be fixed to be done in sample() using actual seeds for batches
  1372. if self.inpainting_fill == 2:
  1373. 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
  1374. self.extra_generation_params["Masked content"] = 'latent noise'
  1375. elif self.inpainting_fill == 3:
  1376. self.init_latent = self.init_latent * self.mask
  1377. self.extra_generation_params["Masked content"] = 'latent nothing'
  1378. self.image_conditioning = self.img2img_image_conditioning(image * 2 - 1, self.init_latent, image_mask, self.mask_round)
  1379. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  1380. x = self.rng.next()
  1381. if self.initial_noise_multiplier != 1.0:
  1382. self.extra_generation_params["Noise multiplier"] = self.initial_noise_multiplier
  1383. x *= self.initial_noise_multiplier
  1384. if self.scripts is not None:
  1385. self.scripts.process_before_every_sampling(
  1386. p=self,
  1387. x=self.init_latent,
  1388. noise=x,
  1389. c=conditioning,
  1390. uc=unconditional_conditioning
  1391. )
  1392. samples = self.sampler.sample_img2img(self, self.init_latent, x, conditioning, unconditional_conditioning, image_conditioning=self.image_conditioning)
  1393. if self.mask is not None:
  1394. blended_samples = samples * self.nmask + self.init_latent * self.mask
  1395. if self.scripts is not None:
  1396. mba = scripts.MaskBlendArgs(samples, self.nmask, self.init_latent, self.mask, blended_samples)
  1397. self.scripts.on_mask_blend(self, mba)
  1398. blended_samples = mba.blended_latent
  1399. samples = blended_samples
  1400. del x
  1401. devices.torch_gc()
  1402. return samples
  1403. def get_token_merging_ratio(self, for_hr=False):
  1404. 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