add operations to metadata

This commit is contained in:
Vladimir Mandic
2023-07-25 12:28:13 -04:00
parent aa62f6d8d4
commit 6c02e6a2eb
6 changed files with 24 additions and 12 deletions
+2
View File
@@ -8,6 +8,7 @@
- extensions: fix couple of compatibility items
- firefox compatibility improvements
- minor image viewer improvements
- add backend and operation info to metadata
- original
- fix hires secondary sampler
this now fully obsoletes `fallback_sampler` and `force_latent_sampler`
@@ -21,6 +22,7 @@
- option to set vae upcast in settings
- enable fp16 vae decode when using optimized vae
this pretty much doubles performance of decode step (delay after generate is done)
- refiner: fix batch processing
- sd-xl: loading vae now applies to both base and refiner and saves a bit of vram
- vae: enable loading of pure-safetensors vae files without config
also enable *automatic* selection to work with diffusers
+1
View File
@@ -15,6 +15,7 @@ Stuff to be added, in no particular order...
- Add SD-XL Lora
- Add ControlNet
- Fix SD-XL Img2img/Inpaint
- Add SD and SD-XL Pix2Pix
- Add VAE direct load from safetensors
- Fix Kandinsky 2.2 model
- Fix DeepFloyd IF model
+2 -3
View File
@@ -5,7 +5,7 @@ from io import BytesIO
from typing import List, Dict, Any
from threading import Lock
from secrets import compare_digest
from fastapi import APIRouter, Depends, FastAPI
from fastapi import FastAPI, APIRouter, Depends
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.exceptions import HTTPException
from PIL import PngImagePlugin,Image
@@ -143,7 +143,7 @@ class Api:
self.add_api_route("/sdapi/v1/reload-checkpoint", self.reloadapi, methods=["POST"])
self.add_api_route("/sdapi/v1/scripts", self.get_scripts_list, methods=["GET"], response_model=models.ScriptsList)
self.add_api_route("/sdapi/v1/script-info", self.get_script_info, methods=["GET"], response_model=List[models.ScriptInfo])
self.app.add_api_route("/sdapi/v1/log", self.get_log_buffer, methods=["GET"], response_model=List) # bypass auth
self.add_api_route("/sdapi/v1/log", self.get_log_buffer, methods=["GET"], response_model=List) # bypass auth
self.default_script_arg_txt2img = []
self.default_script_arg_img2img = []
@@ -158,7 +158,6 @@ class Api:
return True
raise HTTPException(status_code=401, detail="Unauthorized", headers={"WWW-Authenticate": "Basic"})
def get_log_buffer(self, req: models.LogRequest = Depends()):
lines = shared.log.buffer[:req.lines] if req.lines > 0 else shared.log.buffer.copy()
if req.clear:
+1 -1
View File
@@ -585,7 +585,7 @@ def save_image(image, path, basename, seed=None, prompt=None, extension='jpg', i
params.filename = filename + extension
txt_fullfn = f"{filename}.txt" if shared.opts.save_txt and len(exifinfo) > 0 else None
save_queue.put((params.image, filename, extension, params, exifinfo, txt_fullfn))
save_queue.put((params.image, filename, extension, params, exifinfo, txt_fullfn)) # actual save is executed in a thread that polls data from queue
save_queue.join()
# atomically_save_image(params.image, filename, extension, params, exifinfo, txt_fullfn)
+14 -7
View File
@@ -381,7 +381,6 @@ def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, see
subnoise = None
if subseeds is not None:
subseed = 0 if i >= len(subseeds) else subseeds[i]
subnoise = devices.randn(subseed, noise_shape)
# randn results depend on device; gpu and cpu get different results for same seed;
@@ -403,16 +402,13 @@ def create_random_tensors(shape, seeds, subseeds=None, subseed_strength=0.0, see
ty = 0 if dy < 0 else dy
dx = max(-dx, 0)
dy = max(-dy, 0)
x[:, ty:ty+h, tx:tx+w] = noise[:, dy:dy+h, dx:dx+w]
noise = x
if sampler_noises is not None:
cnt = p.sampler.number_of_needed_noises(p)
if eta_noise_seed_delta > 0:
torch.manual_seed(seed + eta_noise_seed_delta)
for j in range(cnt):
sampler_noises[j].append(devices.randn_without_seed(tuple(noise_shape)))
@@ -450,8 +446,6 @@ def fix_seed(p):
def create_infotext(p: StableDiffusionProcessing, all_prompts, all_seeds, all_subseeds, comments=None, iteration=0, position_in_batch=0): # pylint: disable=unused-argument
index = position_in_batch + iteration * p.batch_size
generation_params = {
"Version": git_commit,
"Pipeline": 'Diffusers' if shared.backend == shared.Backend.DIFFUSERS else 'Original',
"Steps": p.steps,
"Seed": all_seeds[index],
"Sampler": p.sampler_name,
@@ -481,7 +475,10 @@ def create_infotext(p: StableDiffusionProcessing, all_prompts, all_seeds, all_su
"Denoise end": p.refiner_denoise_end if p.enable_hr else None,
# restore_faces
"Face restoration": shared.opts.face_restoration_model if p.restore_faces else None,
"Operations": ', '.join(p.ops),
# sdnext
"Version": git_commit,
"Pipeline": 'Diffusers' if shared.backend == shared.Backend.DIFFUSERS else 'Original',
"Operations": ', '.join(list(set(p.ops))),
}
token_merging_ratio = p.get_token_merging_ratio()
token_merging_ratio_hr = p.get_token_merging_ratio(for_hr=True) if p.enable_hr else None
@@ -726,6 +723,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
info=infotext(n, i)
p.restore_faces = orig
images.save_image(Image.fromarray(x_sample), path=p.outpath_samples, basename="", seed=seeds[i], prompt=prompts[i], extension=shared.opts.samples_format, info=info, p=p, suffix="-before-face-restoration")
p.ops.append('face')
x_sample = modules.face_restoration.restore_faces(x_sample)
image = Image.fromarray(x_sample)
if p.scripts is not None:
@@ -740,6 +738,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
p.color_corrections = orig
image_without_cc = apply_overlay(image, p.paste_to, i, p.overlay_images)
images.save_image(image_without_cc, path=p.outpath_samples, basename="", seed=seeds[i], prompt=prompts[i], extension=shared.opts.samples_format, info=info, p=p, suffix="-before-color-correction")
p.ops.append('color')
image = apply_color_correction(p.color_corrections[i], image)
image = apply_overlay(image, p.paste_to, i, p.overlay_images)
if shared.opts.samples_save and not p.do_not_save_samples:
@@ -840,7 +839,9 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
self.width = self.width or 512
self.height = self.height or 512
def init_hr(self):
if self.enable_hr:
self.ops.append('hires')
if shared.opts.use_old_hires_fix_width_height and self.applied_old_hires_behavior_to != (self.width, self.height):
self.hr_resize_x = self.width
self.hr_resize_y = self.height
@@ -908,6 +909,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
if shared.backend == shared.Backend.DIFFUSERS:
sd_models.set_diffuser_pipe(self.sd_model, sd_models.DiffusersTaskType.TEXT_2_IMAGE)
self.ops.append('txt2img')
self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
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")
if self.enable_hr and latent_scale_mode is None:
@@ -919,6 +921,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
if not self.enable_hr or shared.state.interrupted or shared.state.skipped:
return samples
self.is_hr_pass = True
self.init_hr()
target_width = self.hr_upscale_to_x
target_height = self.hr_upscale_to_y
@@ -1009,6 +1012,10 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing):
self.sampler_name = 'UniPC'
self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
if self.image_mask is not None:
self.ops.append('inpaint')
else:
self.ops.append('img2img')
crop_region = None
image_mask = self.image_mask
if image_mask is not None:
+4 -1
View File
@@ -104,10 +104,13 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro
cross_attention_kwargs['scale'] = lora_state['multiplier']
task_specific_kwargs={}
if sd_models.get_diffusers_task(shared.sd_model) == sd_models.DiffusersTaskType.TEXT_2_IMAGE:
p.ops.append('txt2img')
task_specific_kwargs = {"height": p.height, "width": p.width}
elif sd_models.get_diffusers_task(shared.sd_model) == sd_models.DiffusersTaskType.IMAGE_2_IMAGE:
p.ops.append('img2img')
task_specific_kwargs = {"image": p.init_images, "strength": p.denoising_strength}
elif sd_models.get_diffusers_task(shared.sd_model) == sd_models.DiffusersTaskType.INPAINTING:
p.ops.append('inpaint')
task_specific_kwargs = {"image": p.init_images, "mask_image": p.mask, "strength": p.denoising_strength}
# TODO diffusers use transformers for prompt parsing
@@ -167,7 +170,7 @@ def process_diffusers(p: StableDiffusionProcessing, seeds, prompts, negative_pro
if shared.opts.diffusers_move_refiner:
shared.sd_refiner.to(devices.device)
p.ops.append('refine')
for i in range(len(output.images)):
pipe_args = set_pipeline_args(
model=shared.sd_refiner,