processing.py 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541
  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, generation_parameters_copypaste, extra_networks, sd_vae_approx, scripts, sd_samplers_common, sd_unet, errors, rng
  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 apply_overlay(image, paste_loc, index, overlays):
  53. if overlays is None or index >= len(overlays):
  54. return image
  55. overlay = overlays[index]
  56. if paste_loc is not None:
  57. x, y, w, h = paste_loc
  58. base_image = Image.new('RGBA', (overlay.width, overlay.height))
  59. image = images.resize_image(1, image, w, h)
  60. base_image.paste(image, (x, y))
  61. image = base_image
  62. image = image.convert('RGBA')
  63. image.alpha_composite(overlay)
  64. image = image.convert('RGB')
  65. return image
  66. def create_binary_mask(image):
  67. if image.mode == 'RGBA' and image.getextrema()[-1] != (255, 255):
  68. image = image.split()[-1].convert("L").point(lambda x: 255 if x > 128 else 0)
  69. else:
  70. image = image.convert('L')
  71. return image
  72. def txt2img_image_conditioning(sd_model, x, width, height):
  73. if sd_model.model.conditioning_key in {'hybrid', 'concat'}: # Inpainting models
  74. # The "masked-image" in this case will just be all 0.5 since the entire image is masked.
  75. image_conditioning = torch.ones(x.shape[0], 3, height, width, device=x.device) * 0.5
  76. image_conditioning = images_tensor_to_samples(image_conditioning, approximation_indexes.get(opts.sd_vae_encode_method))
  77. # Add the fake full 1s mask to the first dimension.
  78. image_conditioning = torch.nn.functional.pad(image_conditioning, (0, 0, 0, 0, 1, 0), value=1.0)
  79. image_conditioning = image_conditioning.to(x.dtype)
  80. return image_conditioning
  81. elif sd_model.model.conditioning_key == "crossattn-adm": # UnCLIP models
  82. return x.new_zeros(x.shape[0], 2*sd_model.noise_augmentor.time_embed.dim, dtype=x.dtype, device=x.device)
  83. else:
  84. # Dummy zero conditioning if we're not using inpainting or unclip models.
  85. # Still takes up a bit of memory, but no encoder call.
  86. # Pretty sure we can just make this a 1x1 image since its not going to be used besides its batch size.
  87. return x.new_zeros(x.shape[0], 5, 1, 1, dtype=x.dtype, device=x.device)
  88. @dataclass(repr=False)
  89. class StableDiffusionProcessing:
  90. sd_model: object = None
  91. outpath_samples: str = None
  92. outpath_grids: str = None
  93. prompt: str = ""
  94. prompt_for_display: str = None
  95. negative_prompt: str = ""
  96. styles: list[str] = None
  97. seed: int = -1
  98. subseed: int = -1
  99. subseed_strength: float = 0
  100. seed_resize_from_h: int = -1
  101. seed_resize_from_w: int = -1
  102. seed_enable_extras: bool = True
  103. sampler_name: str = None
  104. batch_size: int = 1
  105. n_iter: int = 1
  106. steps: int = 50
  107. cfg_scale: float = 7.0
  108. width: int = 512
  109. height: int = 512
  110. restore_faces: bool = None
  111. tiling: bool = None
  112. do_not_save_samples: bool = False
  113. do_not_save_grid: bool = False
  114. extra_generation_params: dict[str, Any] = None
  115. overlay_images: list = None
  116. eta: float = None
  117. do_not_reload_embeddings: bool = False
  118. denoising_strength: float = None
  119. ddim_discretize: str = None
  120. s_min_uncond: float = None
  121. s_churn: float = None
  122. s_tmax: float = None
  123. s_tmin: float = None
  124. s_noise: float = None
  125. override_settings: dict[str, Any] = None
  126. override_settings_restore_afterwards: bool = True
  127. sampler_index: int = None
  128. refiner_checkpoint: str = None
  129. refiner_switch_at: float = None
  130. token_merging_ratio = 0
  131. token_merging_ratio_hr = 0
  132. disable_extra_networks: bool = False
  133. scripts_value: scripts.ScriptRunner = field(default=None, init=False)
  134. script_args_value: list = field(default=None, init=False)
  135. scripts_setup_complete: bool = field(default=False, init=False)
  136. cached_uc = [None, None]
  137. cached_c = [None, None]
  138. comments: dict = None
  139. sampler: sd_samplers_common.Sampler | None = field(default=None, init=False)
  140. is_using_inpainting_conditioning: bool = field(default=False, init=False)
  141. paste_to: tuple | None = field(default=None, init=False)
  142. is_hr_pass: bool = field(default=False, init=False)
  143. c: tuple = field(default=None, init=False)
  144. uc: tuple = field(default=None, init=False)
  145. rng: rng.ImageRNG | None = field(default=None, init=False)
  146. step_multiplier: int = field(default=1, init=False)
  147. color_corrections: list = field(default=None, init=False)
  148. all_prompts: list = field(default=None, init=False)
  149. all_negative_prompts: list = field(default=None, init=False)
  150. all_seeds: list = field(default=None, init=False)
  151. all_subseeds: list = field(default=None, init=False)
  152. iteration: int = field(default=0, init=False)
  153. main_prompt: str = field(default=None, init=False)
  154. main_negative_prompt: str = field(default=None, init=False)
  155. prompts: list = field(default=None, init=False)
  156. negative_prompts: list = field(default=None, init=False)
  157. seeds: list = field(default=None, init=False)
  158. subseeds: list = field(default=None, init=False)
  159. extra_network_data: dict = field(default=None, init=False)
  160. user: str = field(default=None, init=False)
  161. sd_model_name: str = field(default=None, init=False)
  162. sd_model_hash: str = field(default=None, init=False)
  163. sd_vae_name: str = field(default=None, init=False)
  164. sd_vae_hash: str = field(default=None, init=False)
  165. is_api: bool = field(default=False, init=False)
  166. def __post_init__(self):
  167. if self.sampler_index is not None:
  168. print("sampler_index argument for StableDiffusionProcessing does not do anything; use sampler_name", file=sys.stderr)
  169. self.comments = {}
  170. if self.styles is None:
  171. self.styles = []
  172. self.sampler_noise_scheduler_override = None
  173. self.s_min_uncond = self.s_min_uncond if self.s_min_uncond is not None else opts.s_min_uncond
  174. self.s_churn = self.s_churn if self.s_churn is not None else opts.s_churn
  175. self.s_tmin = self.s_tmin if self.s_tmin is not None else opts.s_tmin
  176. self.s_tmax = (self.s_tmax if self.s_tmax is not None else opts.s_tmax) or float('inf')
  177. self.s_noise = self.s_noise if self.s_noise is not None else opts.s_noise
  178. self.extra_generation_params = self.extra_generation_params or {}
  179. self.override_settings = self.override_settings or {}
  180. self.script_args = self.script_args or {}
  181. self.refiner_checkpoint_info = None
  182. if not self.seed_enable_extras:
  183. self.subseed = -1
  184. self.subseed_strength = 0
  185. self.seed_resize_from_h = 0
  186. self.seed_resize_from_w = 0
  187. self.cached_uc = StableDiffusionProcessing.cached_uc
  188. self.cached_c = StableDiffusionProcessing.cached_c
  189. @property
  190. def sd_model(self):
  191. return shared.sd_model
  192. @sd_model.setter
  193. def sd_model(self, value):
  194. pass
  195. @property
  196. def scripts(self):
  197. return self.scripts_value
  198. @scripts.setter
  199. def scripts(self, value):
  200. self.scripts_value = value
  201. if self.scripts_value and self.script_args_value and not self.scripts_setup_complete:
  202. self.setup_scripts()
  203. @property
  204. def script_args(self):
  205. return self.script_args_value
  206. @script_args.setter
  207. def script_args(self, value):
  208. self.script_args_value = value
  209. if self.scripts_value and self.script_args_value and not self.scripts_setup_complete:
  210. self.setup_scripts()
  211. def setup_scripts(self):
  212. self.scripts_setup_complete = True
  213. self.scripts.setup_scrips(self, is_ui=not self.is_api)
  214. def comment(self, text):
  215. self.comments[text] = 1
  216. def txt2img_image_conditioning(self, x, width=None, height=None):
  217. self.is_using_inpainting_conditioning = self.sd_model.model.conditioning_key in {'hybrid', 'concat'}
  218. return txt2img_image_conditioning(self.sd_model, x, width or self.width, height or self.height)
  219. def depth2img_image_conditioning(self, source_image):
  220. # Use the AddMiDaS helper to Format our source image to suit the MiDaS model
  221. transformer = AddMiDaS(model_type="dpt_hybrid")
  222. transformed = transformer({"jpg": rearrange(source_image[0], "c h w -> h w c")})
  223. midas_in = torch.from_numpy(transformed["midas_in"][None, ...]).to(device=shared.device)
  224. midas_in = repeat(midas_in, "1 ... -> n ...", n=self.batch_size)
  225. conditioning_image = images_tensor_to_samples(source_image*0.5+0.5, approximation_indexes.get(opts.sd_vae_encode_method))
  226. conditioning = torch.nn.functional.interpolate(
  227. self.sd_model.depth_model(midas_in),
  228. size=conditioning_image.shape[2:],
  229. mode="bicubic",
  230. align_corners=False,
  231. )
  232. (depth_min, depth_max) = torch.aminmax(conditioning)
  233. conditioning = 2. * (conditioning - depth_min) / (depth_max - depth_min) - 1.
  234. return conditioning
  235. def edit_image_conditioning(self, source_image):
  236. conditioning_image = images_tensor_to_samples(source_image*0.5+0.5, approximation_indexes.get(opts.sd_vae_encode_method))
  237. return conditioning_image
  238. def unclip_image_conditioning(self, source_image):
  239. c_adm = self.sd_model.embedder(source_image)
  240. if self.sd_model.noise_augmentor is not None:
  241. noise_level = 0 # TODO: Allow other noise levels?
  242. 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]))
  243. c_adm = torch.cat((c_adm, noise_level_emb), 1)
  244. return c_adm
  245. def inpainting_image_conditioning(self, source_image, latent_image, image_mask=None):
  246. self.is_using_inpainting_conditioning = True
  247. # Handle the different mask inputs
  248. if image_mask is not None:
  249. if torch.is_tensor(image_mask):
  250. conditioning_mask = image_mask
  251. else:
  252. conditioning_mask = np.array(image_mask.convert("L"))
  253. conditioning_mask = conditioning_mask.astype(np.float32) / 255.0
  254. conditioning_mask = torch.from_numpy(conditioning_mask[None, None])
  255. # Inpainting model uses a discretized mask as input, so we round to either 1.0 or 0.0
  256. conditioning_mask = torch.round(conditioning_mask)
  257. else:
  258. conditioning_mask = source_image.new_ones(1, 1, *source_image.shape[-2:])
  259. # Create another latent image, this time with a masked version of the original input.
  260. # Smoothly interpolate between the masked and unmasked latent conditioning image using a parameter.
  261. conditioning_mask = conditioning_mask.to(device=source_image.device, dtype=source_image.dtype)
  262. conditioning_image = torch.lerp(
  263. source_image,
  264. source_image * (1.0 - conditioning_mask),
  265. getattr(self, "inpainting_mask_weight", shared.opts.inpainting_mask_weight)
  266. )
  267. # Encode the new masked image using first stage of network.
  268. conditioning_image = self.sd_model.get_first_stage_encoding(self.sd_model.encode_first_stage(conditioning_image))
  269. # Create the concatenated conditioning tensor to be fed to `c_concat`
  270. conditioning_mask = torch.nn.functional.interpolate(conditioning_mask, size=latent_image.shape[-2:])
  271. conditioning_mask = conditioning_mask.expand(conditioning_image.shape[0], -1, -1, -1)
  272. image_conditioning = torch.cat([conditioning_mask, conditioning_image], dim=1)
  273. image_conditioning = image_conditioning.to(shared.device).type(self.sd_model.dtype)
  274. return image_conditioning
  275. def img2img_image_conditioning(self, source_image, latent_image, image_mask=None):
  276. source_image = devices.cond_cast_float(source_image)
  277. # HACK: Using introspection as the Depth2Image model doesn't appear to uniquely
  278. # identify itself with a field common to all models. The conditioning_key is also hybrid.
  279. if isinstance(self.sd_model, LatentDepth2ImageDiffusion):
  280. return self.depth2img_image_conditioning(source_image)
  281. if self.sd_model.cond_stage_key == "edit":
  282. return self.edit_image_conditioning(source_image)
  283. if self.sampler.conditioning_key in {'hybrid', 'concat'}:
  284. return self.inpainting_image_conditioning(source_image, latent_image, image_mask=image_mask)
  285. if self.sampler.conditioning_key == "crossattn-adm":
  286. return self.unclip_image_conditioning(source_image)
  287. # Dummy zero conditioning if we're not using inpainting or depth model.
  288. return latent_image.new_zeros(latent_image.shape[0], 5, 1, 1)
  289. def init(self, all_prompts, all_seeds, all_subseeds):
  290. pass
  291. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  292. raise NotImplementedError()
  293. def close(self):
  294. self.sampler = None
  295. self.c = None
  296. self.uc = None
  297. if not opts.persistent_cond_cache:
  298. StableDiffusionProcessing.cached_c = [None, None]
  299. StableDiffusionProcessing.cached_uc = [None, None]
  300. def get_token_merging_ratio(self, for_hr=False):
  301. if for_hr:
  302. return self.token_merging_ratio_hr or opts.token_merging_ratio_hr or self.token_merging_ratio or opts.token_merging_ratio
  303. return self.token_merging_ratio or opts.token_merging_ratio
  304. def setup_prompts(self):
  305. if isinstance(self.prompt,list):
  306. self.all_prompts = self.prompt
  307. elif isinstance(self.negative_prompt, list):
  308. self.all_prompts = [self.prompt] * len(self.negative_prompt)
  309. else:
  310. self.all_prompts = self.batch_size * self.n_iter * [self.prompt]
  311. if isinstance(self.negative_prompt, list):
  312. self.all_negative_prompts = self.negative_prompt
  313. else:
  314. self.all_negative_prompts = [self.negative_prompt] * len(self.all_prompts)
  315. if len(self.all_prompts) != len(self.all_negative_prompts):
  316. raise RuntimeError(f"Received a different number of prompts ({len(self.all_prompts)}) and negative prompts ({len(self.all_negative_prompts)})")
  317. self.all_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_prompts]
  318. self.all_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_negative_prompts]
  319. self.main_prompt = self.all_prompts[0]
  320. self.main_negative_prompt = self.all_negative_prompts[0]
  321. def cached_params(self, required_prompts, steps, extra_network_data, hires_steps=None, use_old_scheduling=False):
  322. """Returns parameters that invalidate the cond cache if changed"""
  323. return (
  324. required_prompts,
  325. steps,
  326. hires_steps,
  327. use_old_scheduling,
  328. opts.CLIP_stop_at_last_layers,
  329. shared.sd_model.sd_checkpoint_info,
  330. extra_network_data,
  331. opts.sdxl_crop_left,
  332. opts.sdxl_crop_top,
  333. self.width,
  334. self.height,
  335. )
  336. def get_conds_with_caching(self, function, required_prompts, steps, caches, extra_network_data, hires_steps=None):
  337. """
  338. Returns the result of calling function(shared.sd_model, required_prompts, steps)
  339. using a cache to store the result if the same arguments have been used before.
  340. cache is an array containing two elements. The first element is a tuple
  341. representing the previously used arguments, or None if no arguments
  342. have been used before. The second element is where the previously
  343. computed result is stored.
  344. caches is a list with items described above.
  345. """
  346. if shared.opts.use_old_scheduling:
  347. old_schedules = prompt_parser.get_learned_conditioning_prompt_schedules(required_prompts, steps, hires_steps, False)
  348. new_schedules = prompt_parser.get_learned_conditioning_prompt_schedules(required_prompts, steps, hires_steps, True)
  349. if old_schedules != new_schedules:
  350. self.extra_generation_params["Old prompt editing timelines"] = True
  351. cached_params = self.cached_params(required_prompts, steps, extra_network_data, hires_steps, shared.opts.use_old_scheduling)
  352. for cache in caches:
  353. if cache[0] is not None and cached_params == cache[0]:
  354. return cache[1]
  355. cache = caches[0]
  356. with devices.autocast():
  357. cache[1] = function(shared.sd_model, required_prompts, steps, hires_steps, shared.opts.use_old_scheduling)
  358. cache[0] = cached_params
  359. return cache[1]
  360. def setup_conds(self):
  361. prompts = prompt_parser.SdConditioning(self.prompts, width=self.width, height=self.height)
  362. negative_prompts = prompt_parser.SdConditioning(self.negative_prompts, width=self.width, height=self.height, is_negative_prompt=True)
  363. sampler_config = sd_samplers.find_sampler_config(self.sampler_name)
  364. total_steps = sampler_config.total_steps(self.steps) if sampler_config else self.steps
  365. self.step_multiplier = total_steps // self.steps
  366. self.firstpass_steps = total_steps
  367. self.uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, negative_prompts, total_steps, [self.cached_uc], self.extra_network_data)
  368. self.c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, prompts, total_steps, [self.cached_c], self.extra_network_data)
  369. def get_conds(self):
  370. return self.c, self.uc
  371. def parse_extra_network_prompts(self):
  372. self.prompts, self.extra_network_data = extra_networks.parse_prompts(self.prompts)
  373. def save_samples(self) -> bool:
  374. """Returns whether generated images need to be written to disk"""
  375. return opts.samples_save and not self.do_not_save_samples and (opts.save_incomplete_images or not state.interrupted and not state.skipped)
  376. class Processed:
  377. 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=""):
  378. self.images = images_list
  379. self.prompt = p.prompt
  380. self.negative_prompt = p.negative_prompt
  381. self.seed = seed
  382. self.subseed = subseed
  383. self.subseed_strength = p.subseed_strength
  384. self.info = info
  385. self.comments = "".join(f"{comment}\n" for comment in p.comments)
  386. self.width = p.width
  387. self.height = p.height
  388. self.sampler_name = p.sampler_name
  389. self.cfg_scale = p.cfg_scale
  390. self.image_cfg_scale = getattr(p, 'image_cfg_scale', None)
  391. self.steps = p.steps
  392. self.batch_size = p.batch_size
  393. self.restore_faces = p.restore_faces
  394. self.face_restoration_model = opts.face_restoration_model if p.restore_faces else None
  395. self.sd_model_name = p.sd_model_name
  396. self.sd_model_hash = p.sd_model_hash
  397. self.sd_vae_name = p.sd_vae_name
  398. self.sd_vae_hash = p.sd_vae_hash
  399. self.seed_resize_from_w = p.seed_resize_from_w
  400. self.seed_resize_from_h = p.seed_resize_from_h
  401. self.denoising_strength = getattr(p, 'denoising_strength', None)
  402. self.extra_generation_params = p.extra_generation_params
  403. self.index_of_first_image = index_of_first_image
  404. self.styles = p.styles
  405. self.job_timestamp = state.job_timestamp
  406. self.clip_skip = opts.CLIP_stop_at_last_layers
  407. self.token_merging_ratio = p.token_merging_ratio
  408. self.token_merging_ratio_hr = p.token_merging_ratio_hr
  409. self.eta = p.eta
  410. self.ddim_discretize = p.ddim_discretize
  411. self.s_churn = p.s_churn
  412. self.s_tmin = p.s_tmin
  413. self.s_tmax = p.s_tmax
  414. self.s_noise = p.s_noise
  415. self.s_min_uncond = p.s_min_uncond
  416. self.sampler_noise_scheduler_override = p.sampler_noise_scheduler_override
  417. self.prompt = self.prompt if not isinstance(self.prompt, list) else self.prompt[0]
  418. self.negative_prompt = self.negative_prompt if not isinstance(self.negative_prompt, list) else self.negative_prompt[0]
  419. self.seed = int(self.seed if not isinstance(self.seed, list) else self.seed[0]) if self.seed is not None else -1
  420. self.subseed = int(self.subseed if not isinstance(self.subseed, list) else self.subseed[0]) if self.subseed is not None else -1
  421. self.is_using_inpainting_conditioning = p.is_using_inpainting_conditioning
  422. self.all_prompts = all_prompts or p.all_prompts or [self.prompt]
  423. self.all_negative_prompts = all_negative_prompts or p.all_negative_prompts or [self.negative_prompt]
  424. self.all_seeds = all_seeds or p.all_seeds or [self.seed]
  425. self.all_subseeds = all_subseeds or p.all_subseeds or [self.subseed]
  426. self.infotexts = infotexts or [info]
  427. self.version = program_version()
  428. def js(self):
  429. obj = {
  430. "prompt": self.all_prompts[0],
  431. "all_prompts": self.all_prompts,
  432. "negative_prompt": self.all_negative_prompts[0],
  433. "all_negative_prompts": self.all_negative_prompts,
  434. "seed": self.seed,
  435. "all_seeds": self.all_seeds,
  436. "subseed": self.subseed,
  437. "all_subseeds": self.all_subseeds,
  438. "subseed_strength": self.subseed_strength,
  439. "width": self.width,
  440. "height": self.height,
  441. "sampler_name": self.sampler_name,
  442. "cfg_scale": self.cfg_scale,
  443. "steps": self.steps,
  444. "batch_size": self.batch_size,
  445. "restore_faces": self.restore_faces,
  446. "face_restoration_model": self.face_restoration_model,
  447. "sd_model_name": self.sd_model_name,
  448. "sd_model_hash": self.sd_model_hash,
  449. "sd_vae_name": self.sd_vae_name,
  450. "sd_vae_hash": self.sd_vae_hash,
  451. "seed_resize_from_w": self.seed_resize_from_w,
  452. "seed_resize_from_h": self.seed_resize_from_h,
  453. "denoising_strength": self.denoising_strength,
  454. "extra_generation_params": self.extra_generation_params,
  455. "index_of_first_image": self.index_of_first_image,
  456. "infotexts": self.infotexts,
  457. "styles": self.styles,
  458. "job_timestamp": self.job_timestamp,
  459. "clip_skip": self.clip_skip,
  460. "is_using_inpainting_conditioning": self.is_using_inpainting_conditioning,
  461. "version": self.version,
  462. }
  463. return json.dumps(obj)
  464. def infotext(self, p: StableDiffusionProcessing, index):
  465. 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)
  466. def get_token_merging_ratio(self, for_hr=False):
  467. return self.token_merging_ratio_hr if for_hr else self.token_merging_ratio
  468. def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, seed_resize_from_h=0, seed_resize_from_w=0, p=None):
  469. 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)
  470. return g.next()
  471. class DecodedSamples(list):
  472. already_decoded = True
  473. def decode_latent_batch(model, batch, target_device=None, check_for_nans=False):
  474. samples = DecodedSamples()
  475. for i in range(batch.shape[0]):
  476. sample = decode_first_stage(model, batch[i:i + 1])[0]
  477. if check_for_nans:
  478. try:
  479. devices.test_for_nans(sample, "vae")
  480. except devices.NansException as e:
  481. if devices.dtype_vae == torch.float32 or not shared.opts.auto_vae_precision:
  482. raise e
  483. errors.print_error_explanation(
  484. "A tensor with all NaNs was produced in VAE.\n"
  485. "Web UI will now convert VAE into 32-bit float and retry.\n"
  486. "To disable this behavior, disable the 'Automatically revert VAE to 32-bit floats' setting.\n"
  487. "To always start with 32-bit VAE, use --no-half-vae commandline flag."
  488. )
  489. devices.dtype_vae = torch.float32
  490. model.first_stage_model.to(devices.dtype_vae)
  491. batch = batch.to(devices.dtype_vae)
  492. sample = decode_first_stage(model, batch[i:i + 1])[0]
  493. if target_device is not None:
  494. sample = sample.to(target_device)
  495. samples.append(sample)
  496. return samples
  497. def get_fixed_seed(seed):
  498. if seed == '' or seed is None:
  499. seed = -1
  500. elif isinstance(seed, str):
  501. try:
  502. seed = int(seed)
  503. except Exception:
  504. seed = -1
  505. if seed == -1:
  506. return int(random.randrange(4294967294))
  507. return seed
  508. def fix_seed(p):
  509. p.seed = get_fixed_seed(p.seed)
  510. p.subseed = get_fixed_seed(p.subseed)
  511. def program_version():
  512. import launch
  513. res = launch.git_tag()
  514. if res == "<none>":
  515. res = None
  516. return res
  517. 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):
  518. if index is None:
  519. index = position_in_batch + iteration * p.batch_size
  520. if all_negative_prompts is None:
  521. all_negative_prompts = p.all_negative_prompts
  522. clip_skip = getattr(p, 'clip_skip', opts.CLIP_stop_at_last_layers)
  523. enable_hr = getattr(p, 'enable_hr', False)
  524. token_merging_ratio = p.get_token_merging_ratio()
  525. token_merging_ratio_hr = p.get_token_merging_ratio(for_hr=True)
  526. uses_ensd = opts.eta_noise_seed_delta != 0
  527. if uses_ensd:
  528. uses_ensd = sd_samplers_common.is_sampler_using_eta_noise_seed_delta(p)
  529. generation_params = {
  530. "Steps": p.steps,
  531. "Sampler": p.sampler_name,
  532. "CFG scale": p.cfg_scale,
  533. "Image CFG scale": getattr(p, 'image_cfg_scale', None),
  534. "Seed": p.all_seeds[0] if use_main_prompt else all_seeds[index],
  535. "Face restoration": opts.face_restoration_model if p.restore_faces else None,
  536. "Size": f"{p.width}x{p.height}",
  537. "Model hash": p.sd_model_hash if opts.add_model_hash_to_info else None,
  538. "Model": p.sd_model_name if opts.add_model_name_to_info else None,
  539. "VAE hash": p.sd_vae_hash if opts.add_model_hash_to_info else None,
  540. "VAE": p.sd_vae_name if opts.add_model_name_to_info else None,
  541. "Variation seed": (None if p.subseed_strength == 0 else (p.all_subseeds[0] if use_main_prompt else all_subseeds[index])),
  542. "Variation seed strength": (None if p.subseed_strength == 0 else p.subseed_strength),
  543. "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}"),
  544. "Denoising strength": getattr(p, 'denoising_strength', None),
  545. "Conditional mask weight": getattr(p, "inpainting_mask_weight", shared.opts.inpainting_mask_weight) if p.is_using_inpainting_conditioning else None,
  546. "Clip skip": None if clip_skip <= 1 else clip_skip,
  547. "ENSD": opts.eta_noise_seed_delta if uses_ensd else None,
  548. "Token merging ratio": None if token_merging_ratio == 0 else token_merging_ratio,
  549. "Token merging ratio hr": None if not enable_hr or token_merging_ratio_hr == 0 else token_merging_ratio_hr,
  550. "Init image hash": getattr(p, 'init_img_hash', None),
  551. "RNG": opts.randn_source if opts.randn_source != "GPU" else None,
  552. "NGMS": None if p.s_min_uncond == 0 else p.s_min_uncond,
  553. "Tiling": "True" if p.tiling else None,
  554. **p.extra_generation_params,
  555. "Version": program_version() if opts.add_version_to_infotext else None,
  556. "User": p.user if opts.add_user_name_to_info else None,
  557. }
  558. 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])
  559. prompt_text = p.main_prompt if use_main_prompt else all_prompts[index]
  560. negative_prompt_text = f"\nNegative prompt: {p.main_negative_prompt if use_main_prompt else all_negative_prompts[index]}" if all_negative_prompts[index] else ""
  561. return f"{prompt_text}{negative_prompt_text}\n{generation_params_text}".strip()
  562. def process_images(p: StableDiffusionProcessing) -> Processed:
  563. if p.scripts is not None:
  564. p.scripts.before_process(p)
  565. stored_opts = {k: opts.data[k] for k in p.override_settings.keys() if k in opts.data}
  566. try:
  567. # if no checkpoint override or the override checkpoint can't be found, remove override entry and load opts checkpoint
  568. # 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
  569. if sd_models.checkpoint_aliases.get(p.override_settings.get('sd_model_checkpoint')) is None:
  570. p.override_settings.pop('sd_model_checkpoint', None)
  571. sd_models.reload_model_weights()
  572. for k, v in p.override_settings.items():
  573. opts.set(k, v, is_api=True, run_callbacks=False)
  574. if k == 'sd_model_checkpoint':
  575. sd_models.reload_model_weights()
  576. if k == 'sd_vae':
  577. sd_vae.reload_vae_weights()
  578. sd_models.apply_token_merging(p.sd_model, p.get_token_merging_ratio())
  579. res = process_images_inner(p)
  580. finally:
  581. sd_models.apply_token_merging(p.sd_model, 0)
  582. # restore opts to original state
  583. if p.override_settings_restore_afterwards:
  584. for k, v in stored_opts.items():
  585. setattr(opts, k, v)
  586. if k == 'sd_vae':
  587. sd_vae.reload_vae_weights()
  588. return res
  589. def process_images_inner(p: StableDiffusionProcessing) -> Processed:
  590. """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"""
  591. if isinstance(p.prompt, list):
  592. assert(len(p.prompt) > 0)
  593. else:
  594. assert p.prompt is not None
  595. devices.torch_gc()
  596. seed = get_fixed_seed(p.seed)
  597. subseed = get_fixed_seed(p.subseed)
  598. if p.restore_faces is None:
  599. p.restore_faces = opts.face_restoration
  600. if p.tiling is None:
  601. p.tiling = opts.tiling
  602. if p.refiner_checkpoint not in (None, "", "None", "none"):
  603. p.refiner_checkpoint_info = sd_models.get_closet_checkpoint_match(p.refiner_checkpoint)
  604. if p.refiner_checkpoint_info is None:
  605. raise Exception(f'Could not find checkpoint with name {p.refiner_checkpoint}')
  606. p.sd_model_name = shared.sd_model.sd_checkpoint_info.name_for_extra
  607. p.sd_model_hash = shared.sd_model.sd_model_hash
  608. p.sd_vae_name = sd_vae.get_loaded_vae_name()
  609. p.sd_vae_hash = sd_vae.get_loaded_vae_hash()
  610. modules.sd_hijack.model_hijack.apply_circular(p.tiling)
  611. modules.sd_hijack.model_hijack.clear_comments()
  612. p.setup_prompts()
  613. if isinstance(seed, list):
  614. p.all_seeds = seed
  615. else:
  616. p.all_seeds = [int(seed) + (x if p.subseed_strength == 0 else 0) for x in range(len(p.all_prompts))]
  617. if isinstance(subseed, list):
  618. p.all_subseeds = subseed
  619. else:
  620. p.all_subseeds = [int(subseed) + x for x in range(len(p.all_prompts))]
  621. if os.path.exists(cmd_opts.embeddings_dir) and not p.do_not_reload_embeddings:
  622. model_hijack.embedding_db.load_textual_inversion_embeddings()
  623. if p.scripts is not None:
  624. p.scripts.process(p)
  625. infotexts = []
  626. output_images = []
  627. with torch.no_grad(), p.sd_model.ema_scope():
  628. with devices.autocast():
  629. p.init(p.all_prompts, p.all_seeds, p.all_subseeds)
  630. # for OSX, loading the model during sampling changes the generated picture, so it is loaded here
  631. if shared.opts.live_previews_enable and opts.show_progress_type == "Approx NN":
  632. sd_vae_approx.model()
  633. sd_unet.apply_unet()
  634. if state.job_count == -1:
  635. state.job_count = p.n_iter
  636. for n in range(p.n_iter):
  637. p.iteration = n
  638. if state.skipped:
  639. state.skipped = False
  640. if state.interrupted:
  641. break
  642. sd_models.reload_model_weights() # model can be changed for example by refiner
  643. p.prompts = p.all_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  644. p.negative_prompts = p.all_negative_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  645. p.seeds = p.all_seeds[n * p.batch_size:(n + 1) * p.batch_size]
  646. p.subseeds = p.all_subseeds[n * p.batch_size:(n + 1) * p.batch_size]
  647. p.rng = rng.ImageRNG((opt_C, 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)
  648. if p.scripts is not None:
  649. p.scripts.before_process_batch(p, batch_number=n, prompts=p.prompts, seeds=p.seeds, subseeds=p.subseeds)
  650. if len(p.prompts) == 0:
  651. break
  652. p.parse_extra_network_prompts()
  653. if not p.disable_extra_networks:
  654. with devices.autocast():
  655. extra_networks.activate(p, p.extra_network_data)
  656. if p.scripts is not None:
  657. p.scripts.process_batch(p, batch_number=n, prompts=p.prompts, seeds=p.seeds, subseeds=p.subseeds)
  658. # params.txt should be saved after scripts.process_batch, since the
  659. # infotext could be modified by that callback
  660. # Example: a wildcard processed by process_batch sets an extra model
  661. # strength, which is saved as "Model Strength: 1.0" in the infotext
  662. if n == 0:
  663. with open(os.path.join(paths.data_path, "params.txt"), "w", encoding="utf8") as file:
  664. processed = Processed(p, [])
  665. file.write(processed.infotext(p, 0))
  666. p.setup_conds()
  667. for comment in model_hijack.comments:
  668. p.comment(comment)
  669. p.extra_generation_params.update(model_hijack.extra_generation_params)
  670. if p.n_iter > 1:
  671. shared.state.job = f"Batch {n+1} out of {p.n_iter}"
  672. with devices.without_autocast() if devices.unet_needs_upcast else devices.autocast():
  673. 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)
  674. if getattr(samples_ddim, 'already_decoded', False):
  675. x_samples_ddim = samples_ddim
  676. else:
  677. if opts.sd_vae_decode_method != 'Full':
  678. p.extra_generation_params['VAE Decoder'] = opts.sd_vae_decode_method
  679. x_samples_ddim = decode_latent_batch(p.sd_model, samples_ddim, target_device=devices.cpu, check_for_nans=True)
  680. x_samples_ddim = torch.stack(x_samples_ddim).float()
  681. x_samples_ddim = torch.clamp((x_samples_ddim + 1.0) / 2.0, min=0.0, max=1.0)
  682. del samples_ddim
  683. if lowvram.is_enabled(shared.sd_model):
  684. lowvram.send_everything_to_cpu()
  685. devices.torch_gc()
  686. if p.scripts is not None:
  687. p.scripts.postprocess_batch(p, x_samples_ddim, batch_number=n)
  688. p.prompts = p.all_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  689. p.negative_prompts = p.all_negative_prompts[n * p.batch_size:(n + 1) * p.batch_size]
  690. batch_params = scripts.PostprocessBatchListArgs(list(x_samples_ddim))
  691. p.scripts.postprocess_batch_list(p, batch_params, batch_number=n)
  692. x_samples_ddim = batch_params.images
  693. def infotext(index=0, use_main_prompt=False):
  694. return create_infotext(p, p.prompts, p.seeds, p.subseeds, use_main_prompt=use_main_prompt, index=index, all_negative_prompts=p.negative_prompts)
  695. save_samples = p.save_samples()
  696. for i, x_sample in enumerate(x_samples_ddim):
  697. p.batch_index = i
  698. x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
  699. x_sample = x_sample.astype(np.uint8)
  700. if p.restore_faces:
  701. if save_samples and opts.save_images_before_face_restoration:
  702. 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")
  703. devices.torch_gc()
  704. x_sample = modules.face_restoration.restore_faces(x_sample)
  705. devices.torch_gc()
  706. image = Image.fromarray(x_sample)
  707. if p.scripts is not None:
  708. pp = scripts.PostprocessImageArgs(image)
  709. p.scripts.postprocess_image(p, pp)
  710. image = pp.image
  711. if p.color_corrections is not None and i < len(p.color_corrections):
  712. if save_samples and opts.save_images_before_color_correction:
  713. image_without_cc = apply_overlay(image, p.paste_to, i, p.overlay_images)
  714. 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")
  715. image = apply_color_correction(p.color_corrections[i], image)
  716. image = apply_overlay(image, p.paste_to, i, p.overlay_images)
  717. if save_samples:
  718. images.save_image(image, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p)
  719. text = infotext(i)
  720. infotexts.append(text)
  721. if opts.enable_pnginfo:
  722. image.info["parameters"] = text
  723. output_images.append(image)
  724. if save_samples and 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]):
  725. image_mask = p.mask_for_overlay.convert('RGB')
  726. 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')
  727. if opts.save_mask:
  728. images.save_image(image_mask, p.outpath_samples, "", p.seeds[i], p.prompts[i], opts.samples_format, info=infotext(i), p=p, suffix="-mask")
  729. if opts.save_mask_composite:
  730. 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")
  731. if opts.return_mask:
  732. output_images.append(image_mask)
  733. if opts.return_mask_composite:
  734. output_images.append(image_mask_composite)
  735. del x_samples_ddim
  736. devices.torch_gc()
  737. state.nextjob()
  738. p.color_corrections = None
  739. index_of_first_image = 0
  740. unwanted_grid_because_of_img_count = len(output_images) < 2 and opts.grid_only_if_multiple
  741. if (opts.return_grid or opts.grid_save) and not p.do_not_save_grid and not unwanted_grid_because_of_img_count:
  742. grid = images.image_grid(output_images, p.batch_size)
  743. if opts.return_grid:
  744. text = infotext(use_main_prompt=True)
  745. infotexts.insert(0, text)
  746. if opts.enable_pnginfo:
  747. grid.info["parameters"] = text
  748. output_images.insert(0, grid)
  749. index_of_first_image = 1
  750. if opts.grid_save:
  751. 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)
  752. if not p.disable_extra_networks and p.extra_network_data:
  753. extra_networks.deactivate(p, p.extra_network_data)
  754. devices.torch_gc()
  755. res = Processed(
  756. p,
  757. images_list=output_images,
  758. seed=p.all_seeds[0],
  759. info=infotexts[0],
  760. subseed=p.all_subseeds[0],
  761. index_of_first_image=index_of_first_image,
  762. infotexts=infotexts,
  763. )
  764. if p.scripts is not None:
  765. p.scripts.postprocess(p, res)
  766. return res
  767. def old_hires_fix_first_pass_dimensions(width, height):
  768. """old algorithm for auto-calculating first pass size"""
  769. desired_pixel_count = 512 * 512
  770. actual_pixel_count = width * height
  771. scale = math.sqrt(desired_pixel_count / actual_pixel_count)
  772. width = math.ceil(scale * width / 64) * 64
  773. height = math.ceil(scale * height / 64) * 64
  774. return width, height
  775. @dataclass(repr=False)
  776. class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
  777. enable_hr: bool = False
  778. denoising_strength: float = 0.75
  779. firstphase_width: int = 0
  780. firstphase_height: int = 0
  781. hr_scale: float = 2.0
  782. hr_upscaler: str = None
  783. hr_second_pass_steps: int = 0
  784. hr_resize_x: int = 0
  785. hr_resize_y: int = 0
  786. hr_checkpoint_name: str = None
  787. hr_sampler_name: str = None
  788. hr_prompt: str = ''
  789. hr_negative_prompt: str = ''
  790. cached_hr_uc = [None, None]
  791. cached_hr_c = [None, None]
  792. hr_checkpoint_info: dict = field(default=None, init=False)
  793. hr_upscale_to_x: int = field(default=0, init=False)
  794. hr_upscale_to_y: int = field(default=0, init=False)
  795. truncate_x: int = field(default=0, init=False)
  796. truncate_y: int = field(default=0, init=False)
  797. applied_old_hires_behavior_to: tuple = field(default=None, init=False)
  798. latent_scale_mode: dict = field(default=None, init=False)
  799. hr_c: tuple | None = field(default=None, init=False)
  800. hr_uc: tuple | None = field(default=None, init=False)
  801. all_hr_prompts: list = field(default=None, init=False)
  802. all_hr_negative_prompts: list = field(default=None, init=False)
  803. hr_prompts: list = field(default=None, init=False)
  804. hr_negative_prompts: list = field(default=None, init=False)
  805. hr_extra_network_data: list = field(default=None, init=False)
  806. def __post_init__(self):
  807. super().__post_init__()
  808. if self.firstphase_width != 0 or self.firstphase_height != 0:
  809. self.hr_upscale_to_x = self.width
  810. self.hr_upscale_to_y = self.height
  811. self.width = self.firstphase_width
  812. self.height = self.firstphase_height
  813. self.cached_hr_uc = StableDiffusionProcessingTxt2Img.cached_hr_uc
  814. self.cached_hr_c = StableDiffusionProcessingTxt2Img.cached_hr_c
  815. def calculate_target_resolution(self):
  816. if opts.use_old_hires_fix_width_height and self.applied_old_hires_behavior_to != (self.width, self.height):
  817. self.hr_resize_x = self.width
  818. self.hr_resize_y = self.height
  819. self.hr_upscale_to_x = self.width
  820. self.hr_upscale_to_y = self.height
  821. self.width, self.height = old_hires_fix_first_pass_dimensions(self.width, self.height)
  822. self.applied_old_hires_behavior_to = (self.width, self.height)
  823. if self.hr_resize_x == 0 and self.hr_resize_y == 0:
  824. self.extra_generation_params["Hires upscale"] = self.hr_scale
  825. self.hr_upscale_to_x = int(self.width * self.hr_scale)
  826. self.hr_upscale_to_y = int(self.height * self.hr_scale)
  827. else:
  828. self.extra_generation_params["Hires resize"] = f"{self.hr_resize_x}x{self.hr_resize_y}"
  829. if self.hr_resize_y == 0:
  830. self.hr_upscale_to_x = self.hr_resize_x
  831. self.hr_upscale_to_y = self.hr_resize_x * self.height // self.width
  832. elif self.hr_resize_x == 0:
  833. self.hr_upscale_to_x = self.hr_resize_y * self.width // self.height
  834. self.hr_upscale_to_y = self.hr_resize_y
  835. else:
  836. target_w = self.hr_resize_x
  837. target_h = self.hr_resize_y
  838. src_ratio = self.width / self.height
  839. dst_ratio = self.hr_resize_x / self.hr_resize_y
  840. if src_ratio < dst_ratio:
  841. self.hr_upscale_to_x = self.hr_resize_x
  842. self.hr_upscale_to_y = self.hr_resize_x * self.height // self.width
  843. else:
  844. self.hr_upscale_to_x = self.hr_resize_y * self.width // self.height
  845. self.hr_upscale_to_y = self.hr_resize_y
  846. self.truncate_x = (self.hr_upscale_to_x - target_w) // opt_f
  847. self.truncate_y = (self.hr_upscale_to_y - target_h) // opt_f
  848. def init(self, all_prompts, all_seeds, all_subseeds):
  849. if self.enable_hr:
  850. if self.hr_checkpoint_name:
  851. self.hr_checkpoint_info = sd_models.get_closet_checkpoint_match(self.hr_checkpoint_name)
  852. if self.hr_checkpoint_info is None:
  853. raise Exception(f'Could not find checkpoint with name {self.hr_checkpoint_name}')
  854. self.extra_generation_params["Hires checkpoint"] = self.hr_checkpoint_info.short_title
  855. if self.hr_sampler_name is not None and self.hr_sampler_name != self.sampler_name:
  856. self.extra_generation_params["Hires sampler"] = self.hr_sampler_name
  857. if tuple(self.hr_prompt) != tuple(self.prompt):
  858. self.extra_generation_params["Hires prompt"] = self.hr_prompt
  859. if tuple(self.hr_negative_prompt) != tuple(self.negative_prompt):
  860. self.extra_generation_params["Hires negative prompt"] = self.hr_negative_prompt
  861. 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")
  862. if self.enable_hr and self.latent_scale_mode is None:
  863. if not any(x.name == self.hr_upscaler for x in shared.sd_upscalers):
  864. raise Exception(f"could not find upscaler named {self.hr_upscaler}")
  865. self.calculate_target_resolution()
  866. if not state.processing_has_refined_job_count:
  867. if state.job_count == -1:
  868. state.job_count = self.n_iter
  869. shared.total_tqdm.updateTotal((self.steps + (self.hr_second_pass_steps or self.steps)) * state.job_count)
  870. state.job_count = state.job_count * 2
  871. state.processing_has_refined_job_count = True
  872. if self.hr_second_pass_steps:
  873. self.extra_generation_params["Hires steps"] = self.hr_second_pass_steps
  874. if self.hr_upscaler is not None:
  875. self.extra_generation_params["Hires upscaler"] = self.hr_upscaler
  876. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  877. self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
  878. x = self.rng.next()
  879. samples = self.sampler.sample(self, x, conditioning, unconditional_conditioning, image_conditioning=self.txt2img_image_conditioning(x))
  880. del x
  881. if not self.enable_hr:
  882. return samples
  883. if self.latent_scale_mode is None:
  884. decoded_samples = torch.stack(decode_latent_batch(self.sd_model, samples, target_device=devices.cpu, check_for_nans=True)).to(dtype=torch.float32)
  885. else:
  886. decoded_samples = None
  887. with sd_models.SkipWritingToConfig():
  888. sd_models.reload_model_weights(info=self.hr_checkpoint_info)
  889. devices.torch_gc()
  890. return self.sample_hr_pass(samples, decoded_samples, seeds, subseeds, subseed_strength, prompts)
  891. def sample_hr_pass(self, samples, decoded_samples, seeds, subseeds, subseed_strength, prompts):
  892. if shared.state.interrupted:
  893. return samples
  894. self.is_hr_pass = True
  895. target_width = self.hr_upscale_to_x
  896. target_height = self.hr_upscale_to_y
  897. def save_intermediate(image, index):
  898. """saves image before applying hires fix, if enabled in options; takes as an argument either an image or batch with latent space images"""
  899. if not self.save_samples() or not opts.save_images_before_highres_fix:
  900. return
  901. if not isinstance(image, Image.Image):
  902. image = sd_samplers.sample_to_image(image, index, approximation=0)
  903. info = create_infotext(self, self.all_prompts, self.all_seeds, self.all_subseeds, [], iteration=self.iteration, position_in_batch=index)
  904. images.save_image(image, self.outpath_samples, "", seeds[index], prompts[index], opts.samples_format, info=info, p=self, suffix="-before-highres-fix")
  905. img2img_sampler_name = self.hr_sampler_name or self.sampler_name
  906. self.sampler = sd_samplers.create_sampler(img2img_sampler_name, self.sd_model)
  907. if self.latent_scale_mode is not None:
  908. for i in range(samples.shape[0]):
  909. save_intermediate(samples, i)
  910. 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"])
  911. # Avoid making the inpainting conditioning unless necessary as
  912. # this does need some extra compute to decode / encode the image again.
  913. if getattr(self, "inpainting_mask_weight", shared.opts.inpainting_mask_weight) < 1.0:
  914. image_conditioning = self.img2img_image_conditioning(decode_first_stage(self.sd_model, samples), samples)
  915. else:
  916. image_conditioning = self.txt2img_image_conditioning(samples)
  917. else:
  918. lowres_samples = torch.clamp((decoded_samples + 1.0) / 2.0, min=0.0, max=1.0)
  919. batch_images = []
  920. for i, x_sample in enumerate(lowres_samples):
  921. x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
  922. x_sample = x_sample.astype(np.uint8)
  923. image = Image.fromarray(x_sample)
  924. save_intermediate(image, i)
  925. image = images.resize_image(0, image, target_width, target_height, upscaler_name=self.hr_upscaler)
  926. image = np.array(image).astype(np.float32) / 255.0
  927. image = np.moveaxis(image, 2, 0)
  928. batch_images.append(image)
  929. decoded_samples = torch.from_numpy(np.array(batch_images))
  930. decoded_samples = decoded_samples.to(shared.device, dtype=devices.dtype_vae)
  931. if opts.sd_vae_encode_method != 'Full':
  932. self.extra_generation_params['VAE Encoder'] = opts.sd_vae_encode_method
  933. samples = images_tensor_to_samples(decoded_samples, approximation_indexes.get(opts.sd_vae_encode_method))
  934. image_conditioning = self.img2img_image_conditioning(decoded_samples, samples)
  935. shared.state.nextjob()
  936. 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]
  937. 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)
  938. noise = self.rng.next()
  939. # GC now before running the next img2img to prevent running out of memory
  940. devices.torch_gc()
  941. if not self.disable_extra_networks:
  942. with devices.autocast():
  943. extra_networks.activate(self, self.hr_extra_network_data)
  944. with devices.autocast():
  945. self.calculate_hr_conds()
  946. sd_models.apply_token_merging(self.sd_model, self.get_token_merging_ratio(for_hr=True))
  947. if self.scripts is not None:
  948. self.scripts.before_hr(self)
  949. 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)
  950. sd_models.apply_token_merging(self.sd_model, self.get_token_merging_ratio())
  951. self.sampler = None
  952. devices.torch_gc()
  953. decoded_samples = decode_latent_batch(self.sd_model, samples, target_device=devices.cpu, check_for_nans=True)
  954. self.is_hr_pass = False
  955. return decoded_samples
  956. def close(self):
  957. super().close()
  958. self.hr_c = None
  959. self.hr_uc = None
  960. if not opts.persistent_cond_cache:
  961. StableDiffusionProcessingTxt2Img.cached_hr_uc = [None, None]
  962. StableDiffusionProcessingTxt2Img.cached_hr_c = [None, None]
  963. def setup_prompts(self):
  964. super().setup_prompts()
  965. if not self.enable_hr:
  966. return
  967. if self.hr_prompt == '':
  968. self.hr_prompt = self.prompt
  969. if self.hr_negative_prompt == '':
  970. self.hr_negative_prompt = self.negative_prompt
  971. if isinstance(self.hr_prompt, list):
  972. self.all_hr_prompts = self.hr_prompt
  973. else:
  974. self.all_hr_prompts = self.batch_size * self.n_iter * [self.hr_prompt]
  975. if isinstance(self.hr_negative_prompt, list):
  976. self.all_hr_negative_prompts = self.hr_negative_prompt
  977. else:
  978. self.all_hr_negative_prompts = self.batch_size * self.n_iter * [self.hr_negative_prompt]
  979. self.all_hr_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_hr_prompts]
  980. self.all_hr_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_hr_negative_prompts]
  981. def calculate_hr_conds(self):
  982. if self.hr_c is not None:
  983. return
  984. hr_prompts = prompt_parser.SdConditioning(self.hr_prompts, width=self.hr_upscale_to_x, height=self.hr_upscale_to_y)
  985. 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)
  986. sampler_config = sd_samplers.find_sampler_config(self.hr_sampler_name or self.sampler_name)
  987. steps = self.hr_second_pass_steps or self.steps
  988. total_steps = sampler_config.total_steps(steps) if sampler_config else steps
  989. 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)
  990. 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)
  991. def setup_conds(self):
  992. if self.is_hr_pass:
  993. # 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
  994. self.hr_c = None
  995. self.calculate_hr_conds()
  996. return
  997. super().setup_conds()
  998. self.hr_uc = None
  999. self.hr_c = None
  1000. if self.enable_hr and self.hr_checkpoint_info is None:
  1001. if shared.opts.hires_fix_use_firstpass_conds:
  1002. self.calculate_hr_conds()
  1003. 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
  1004. with devices.autocast():
  1005. extra_networks.activate(self, self.hr_extra_network_data)
  1006. self.calculate_hr_conds()
  1007. with devices.autocast():
  1008. extra_networks.activate(self, self.extra_network_data)
  1009. def get_conds(self):
  1010. if self.is_hr_pass:
  1011. return self.hr_c, self.hr_uc
  1012. return super().get_conds()
  1013. def parse_extra_network_prompts(self):
  1014. res = super().parse_extra_network_prompts()
  1015. if self.enable_hr:
  1016. self.hr_prompts = self.all_hr_prompts[self.iteration * self.batch_size:(self.iteration + 1) * self.batch_size]
  1017. self.hr_negative_prompts = self.all_hr_negative_prompts[self.iteration * self.batch_size:(self.iteration + 1) * self.batch_size]
  1018. self.hr_prompts, self.hr_extra_network_data = extra_networks.parse_prompts(self.hr_prompts)
  1019. return res
  1020. @dataclass(repr=False)
  1021. class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
  1022. init_images: list = None
  1023. resize_mode: int = 0
  1024. denoising_strength: float = 0.75
  1025. image_cfg_scale: float = None
  1026. mask: Any = None
  1027. mask_blur_x: int = 4
  1028. mask_blur_y: int = 4
  1029. mask_blur: int = None
  1030. inpainting_fill: int = 0
  1031. inpaint_full_res: bool = True
  1032. inpaint_full_res_padding: int = 0
  1033. inpainting_mask_invert: int = 0
  1034. initial_noise_multiplier: float = None
  1035. latent_mask: Image = None
  1036. image_mask: Any = field(default=None, init=False)
  1037. nmask: torch.Tensor = field(default=None, init=False)
  1038. image_conditioning: torch.Tensor = field(default=None, init=False)
  1039. init_img_hash: str = field(default=None, init=False)
  1040. mask_for_overlay: Image = field(default=None, init=False)
  1041. init_latent: torch.Tensor = field(default=None, init=False)
  1042. def __post_init__(self):
  1043. super().__post_init__()
  1044. self.image_mask = self.mask
  1045. self.mask = None
  1046. self.initial_noise_multiplier = opts.initial_noise_multiplier if self.initial_noise_multiplier is None else self.initial_noise_multiplier
  1047. @property
  1048. def mask_blur(self):
  1049. if self.mask_blur_x == self.mask_blur_y:
  1050. return self.mask_blur_x
  1051. return None
  1052. @mask_blur.setter
  1053. def mask_blur(self, value):
  1054. if isinstance(value, int):
  1055. self.mask_blur_x = value
  1056. self.mask_blur_y = value
  1057. def init(self, all_prompts, all_seeds, all_subseeds):
  1058. self.image_cfg_scale: float = self.image_cfg_scale if shared.sd_model.cond_stage_key == "edit" else None
  1059. self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
  1060. crop_region = None
  1061. image_mask = self.image_mask
  1062. if image_mask is not None:
  1063. # image_mask is passed in as RGBA by Gradio to support alpha masks,
  1064. # but we still want to support binary masks.
  1065. image_mask = create_binary_mask(image_mask)
  1066. if self.inpainting_mask_invert:
  1067. image_mask = ImageOps.invert(image_mask)
  1068. if self.mask_blur_x > 0:
  1069. np_mask = np.array(image_mask)
  1070. kernel_size = 2 * int(2.5 * self.mask_blur_x + 0.5) + 1
  1071. np_mask = cv2.GaussianBlur(np_mask, (kernel_size, 1), self.mask_blur_x)
  1072. image_mask = Image.fromarray(np_mask)
  1073. if self.mask_blur_y > 0:
  1074. np_mask = np.array(image_mask)
  1075. kernel_size = 2 * int(2.5 * self.mask_blur_y + 0.5) + 1
  1076. np_mask = cv2.GaussianBlur(np_mask, (1, kernel_size), self.mask_blur_y)
  1077. image_mask = Image.fromarray(np_mask)
  1078. if self.inpaint_full_res:
  1079. self.mask_for_overlay = image_mask
  1080. mask = image_mask.convert('L')
  1081. crop_region = masking.get_crop_region(np.array(mask), self.inpaint_full_res_padding)
  1082. crop_region = masking.expand_crop_region(crop_region, self.width, self.height, mask.width, mask.height)
  1083. x1, y1, x2, y2 = crop_region
  1084. mask = mask.crop(crop_region)
  1085. image_mask = images.resize_image(2, mask, self.width, self.height)
  1086. self.paste_to = (x1, y1, x2-x1, y2-y1)
  1087. else:
  1088. image_mask = images.resize_image(self.resize_mode, image_mask, self.width, self.height)
  1089. np_mask = np.array(image_mask)
  1090. np_mask = np.clip((np_mask.astype(np.float32)) * 2, 0, 255).astype(np.uint8)
  1091. self.mask_for_overlay = Image.fromarray(np_mask)
  1092. self.overlay_images = []
  1093. latent_mask = self.latent_mask if self.latent_mask is not None else image_mask
  1094. add_color_corrections = opts.img2img_color_correction and self.color_corrections is None
  1095. if add_color_corrections:
  1096. self.color_corrections = []
  1097. imgs = []
  1098. for img in self.init_images:
  1099. # Save init image
  1100. if opts.save_init_img:
  1101. self.init_img_hash = hashlib.md5(img.tobytes()).hexdigest()
  1102. images.save_image(img, path=opts.outdir_init_images, basename=None, forced_filename=self.init_img_hash, save_to_dirs=False)
  1103. image = images.flatten(img, opts.img2img_background_color)
  1104. if crop_region is None and self.resize_mode != 3:
  1105. image = images.resize_image(self.resize_mode, image, self.width, self.height)
  1106. if image_mask is not None:
  1107. image_masked = Image.new('RGBa', (image.width, image.height))
  1108. image_masked.paste(image.convert("RGBA").convert("RGBa"), mask=ImageOps.invert(self.mask_for_overlay.convert('L')))
  1109. self.overlay_images.append(image_masked.convert('RGBA'))
  1110. # crop_region is not None if we are doing inpaint full res
  1111. if crop_region is not None:
  1112. image = image.crop(crop_region)
  1113. image = images.resize_image(2, image, self.width, self.height)
  1114. if image_mask is not None:
  1115. if self.inpainting_fill != 1:
  1116. image = masking.fill(image, latent_mask)
  1117. if add_color_corrections:
  1118. self.color_corrections.append(setup_color_correction(image))
  1119. image = np.array(image).astype(np.float32) / 255.0
  1120. image = np.moveaxis(image, 2, 0)
  1121. imgs.append(image)
  1122. if len(imgs) == 1:
  1123. batch_images = np.expand_dims(imgs[0], axis=0).repeat(self.batch_size, axis=0)
  1124. if self.overlay_images is not None:
  1125. self.overlay_images = self.overlay_images * self.batch_size
  1126. if self.color_corrections is not None and len(self.color_corrections) == 1:
  1127. self.color_corrections = self.color_corrections * self.batch_size
  1128. elif len(imgs) <= self.batch_size:
  1129. self.batch_size = len(imgs)
  1130. batch_images = np.array(imgs)
  1131. else:
  1132. raise RuntimeError(f"bad number of images passed: {len(imgs)}; expecting {self.batch_size} or less")
  1133. image = torch.from_numpy(batch_images)
  1134. image = image.to(shared.device, dtype=devices.dtype_vae)
  1135. if opts.sd_vae_encode_method != 'Full':
  1136. self.extra_generation_params['VAE Encoder'] = opts.sd_vae_encode_method
  1137. self.init_latent = images_tensor_to_samples(image, approximation_indexes.get(opts.sd_vae_encode_method), self.sd_model)
  1138. devices.torch_gc()
  1139. if self.resize_mode == 3:
  1140. self.init_latent = torch.nn.functional.interpolate(self.init_latent, size=(self.height // opt_f, self.width // opt_f), mode="bilinear")
  1141. if image_mask is not None:
  1142. init_mask = latent_mask
  1143. latmask = init_mask.convert('RGB').resize((self.init_latent.shape[3], self.init_latent.shape[2]))
  1144. latmask = np.moveaxis(np.array(latmask, dtype=np.float32), 2, 0) / 255
  1145. latmask = latmask[0]
  1146. latmask = np.around(latmask)
  1147. latmask = np.tile(latmask[None], (4, 1, 1))
  1148. self.mask = torch.asarray(1.0 - latmask).to(shared.device).type(self.sd_model.dtype)
  1149. self.nmask = torch.asarray(latmask).to(shared.device).type(self.sd_model.dtype)
  1150. # this needs to be fixed to be done in sample() using actual seeds for batches
  1151. if self.inpainting_fill == 2:
  1152. 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
  1153. elif self.inpainting_fill == 3:
  1154. self.init_latent = self.init_latent * self.mask
  1155. self.image_conditioning = self.img2img_image_conditioning(image * 2 - 1, self.init_latent, image_mask)
  1156. def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
  1157. x = self.rng.next()
  1158. if self.initial_noise_multiplier != 1.0:
  1159. self.extra_generation_params["Noise multiplier"] = self.initial_noise_multiplier
  1160. x *= self.initial_noise_multiplier
  1161. samples = self.sampler.sample_img2img(self, self.init_latent, x, conditioning, unconditional_conditioning, image_conditioning=self.image_conditioning)
  1162. if self.mask is not None:
  1163. samples = samples * self.nmask + self.init_latent * self.mask
  1164. del x
  1165. devices.torch_gc()
  1166. return samples
  1167. def get_token_merging_ratio(self, for_hr=False):
  1168. 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