mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 09:14:35 +02:00
add operations to metadata
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user