Download scripts/advanced_loopback.py from dikdimon/new0808: direct link, hf CLI and curl.
- Browser
- Download file 13.3 kB
-
https://huggingface.co/dikdimon/new0808/resolve/refs%2Fpr%2F1/scripts/advanced_loopback.py
- Command line
-
hf download hf://dikdimon/new0808@refs/pr/1/scripts/advanced_loopback.py
-
curl -L -o advanced_loopback.py https://huggingface.co/dikdimon/new0808/resolve/refs%2Fpr%2F1/scripts/advanced_loopback.py
13.3 kB
| import numpy as np | |
| from tqdm import trange | |
| from PIL import Image, ImageEnhance | |
| import modules.scripts as scripts | |
| import gradio as gr | |
| from modules import processing, shared, sd_samplers, images | |
| from modules.processing import Processed | |
| from modules.sd_samplers import samplers | |
| from modules.shared import opts, cmd_opts, state | |
| from math import sin, pi | |
| class Script(scripts.Script): | |
| def title(self): | |
| return "Advanced loopback" | |
| def show(self, is_img2img): | |
| return is_img2img | |
| def ui(self, is_img2img): | |
| loops = gr.Number(minimum=1, step=1, label='Loops', value=4) | |
| use_first_image_colors = gr.Checkbox(label='Use first image colors (custom color correction) ', value=False) | |
| denoising_strength_change_factor = gr.Slider(minimum=0.9, maximum=1.1, step=0.01, label='Denoising strength change factor (overridden if proportional used)', value=1) | |
| zoom_level = gr.Slider(minimum=1, maximum=1.1, step=0.001, label='Zoom level', value=1) | |
| with gr.Row(): | |
| direction_x = gr.Slider(minimum=-0.1, maximum=0.1, step=0.01, label='Direction X', value=0) | |
| direction_y = gr.Slider(minimum=-0.1, maximum=0.1, step=0.01, label='Direction Y', value=0) | |
| with gr.Row(): | |
| denoising_strength_first_image = gr.Number(minimum=0, step=1, label='Denoising strength start ', value=0) | |
| denoising_strength_last_image = gr.Number(minimum=0, step=1, label='Denoising strength end ', value=4) | |
| denoising_strength_min = gr.Slider(minimum=0.1, maximum=1, step=0.01, label='Denoising strength proportional change starting value ', value=0.1) | |
| denoising_strength_max = gr.Slider(minimum=0.1, maximum=1, step=0.01, label='Denoising strength proportional change ending value (0.1 = disabled) ', value=0.1) | |
| cfg_scale_min = gr.Slider(minimum=0.1, maximum=30, step=0.1, label='CFG scale proportional change starting value ', value=0.1) | |
| cfg_scale_max = gr.Slider(minimum=0.1, maximum=30, step=0.1, label='CFG scale proportional change ending value (0.1 = disabled) ', value=0.1) | |
| saturation_per_image = gr.Slider(minimum=0.99, maximum=1.01, step=0.001, label='Saturation enhancement per image ', value=1) | |
| with gr.Row(): | |
| use_sine_variation_dns = gr.Checkbox(label='Use sine denoising strength variation (CFG will be scaled with it if the slider is > 0.1)', value=True) | |
| phase_diff_denoising = gr.Slider(minimum=0, maximum=1, step=0.05, label='Phase difference', value=0) | |
| amplify_sine_variation_denoise = gr.Slider(minimum=1, maximum=10, step=1, label='Denoising strength exponentiation ', value=1) | |
| with gr.Row(): | |
| use_sine_variation_zoom = gr.Checkbox(label='Use sine zoom variation', value=False) | |
| phase_diff_zoom = gr.Slider(minimum=0, maximum=1, step=0.05, label='Phase difference', value=0) | |
| amplify_sine_variation_zoom = gr.Slider(minimum=1, maximum=10, step=1, label='Zoom exponentiation ', value=1) | |
| with gr.Row(): | |
| use_multi_prompts = gr.Checkbox(label='Use multiple prompts', value=False) | |
| same_seed_per_prompt = gr.Checkbox(label='Same seed per prompt', value=False) | |
| same_seed_always = gr.Checkbox(label='Same seed for everything', value=False) | |
| same_init_image = gr.Checkbox(label='Original init image for everything', value=False) | |
| multi_prompts = gr.Textbox(label="Multiple prompts : 1 line positive, 1 line negative, leave a blank line for no negative", lines=2, max_lines=2000) | |
| return [ | |
| loops, | |
| denoising_strength_change_factor, | |
| zoom_level, | |
| direction_x, | |
| direction_y, | |
| denoising_strength_first_image, | |
| denoising_strength_last_image, | |
| denoising_strength_min, | |
| denoising_strength_max, | |
| cfg_scale_min, | |
| cfg_scale_max, | |
| saturation_per_image, | |
| use_first_image_colors, | |
| use_sine_variation_dns, | |
| use_sine_variation_zoom, | |
| phase_diff_zoom, | |
| use_multi_prompts, | |
| multi_prompts, | |
| amplify_sine_variation_zoom, | |
| same_seed_per_prompt, | |
| phase_diff_denoising, | |
| amplify_sine_variation_denoise, | |
| same_seed_always, | |
| same_init_image | |
| ] | |
| def zoom_into(self, img, zoom, direction_x, direction_y): | |
| neg = lambda x: 1 if x > 0 else -1 | |
| if abs(direction_x) > zoom-1 : direction_x = (zoom-1)*neg(direction_x)*0.999999999999999 #*0.999999999999999 to avoid a float rounding error that makes it higher than desired | |
| if abs(direction_y) > zoom-1 : direction_y = (zoom-1)*neg(direction_y)*0.999999999999999 | |
| w, h = img.size | |
| x = w/2+direction_x*w/4 | |
| y = h/2-direction_y*h/4 | |
| zoom2 = zoom * 2 | |
| img = img.crop((x - w / zoom2, y - h / zoom2, | |
| x + w / zoom2, y + h / zoom2)) | |
| return img.resize((w, h), Image.LANCZOS) | |
| def run(self, p, | |
| loops, | |
| denoising_strength_change_factor, | |
| zoom_level, | |
| direction_x, | |
| direction_y, | |
| denoising_strength_first_image, | |
| denoising_strength_last_image, | |
| denoising_strength_min, | |
| denoising_strength_max, | |
| cfg_scale_min, | |
| cfg_scale_max, | |
| saturation_per_image, | |
| use_first_image_colors, | |
| use_sine_variation_dns, | |
| use_sine_variation_zoom, | |
| phase_diff_zoom, | |
| use_multi_prompts, | |
| multi_prompts, | |
| amplify_sine_variation_zoom, | |
| same_seed_per_prompt, | |
| phase_diff_denoising, | |
| amplify_sine_variation_denoise, | |
| same_seed_always, | |
| same_init_image | |
| ): | |
| ppos = [] | |
| pneg = [] | |
| if use_multi_prompts : | |
| prompts_list = multi_prompts.splitlines() | |
| oddeven = lambda x: 1 if x%2==0 else 0 | |
| for x in range(len(prompts_list)) : | |
| if oddeven(x): | |
| ppos.append(prompts_list[x]) | |
| else: | |
| pneg.append(prompts_list[x]) | |
| if len(pneg) < len(ppos) : | |
| pneg.append("") | |
| def remap_range(value, minIn, MaxIn, minOut, maxOut): | |
| if value > MaxIn: value = MaxIn; | |
| if value < minIn: value = minIn; | |
| finalValue = ((value - minIn) / (MaxIn - minIn)) * (maxOut - minOut) + minOut; | |
| return finalValue; | |
| def get_sin_steps(i,amplify,phase_diff=0): | |
| i -= denoising_strength_first_image | |
| range = (denoising_strength_last_image - denoising_strength_first_image) | |
| x = i % (range) | |
| y = remap_range(x,0,range,0,1) | |
| y = y ** amplify | |
| z = sin((y+phase_diff/2)*pi) | |
| return z | |
| processing.fix_seed(p) | |
| batch_count = p.n_iter | |
| p.extra_generation_params = { | |
| "Denoising strength change factor": denoising_strength_change_factor, | |
| 'Denoising strength proportional change start image':denoising_strength_first_image, | |
| 'Denoising strength proportional change end image':denoising_strength_last_image, | |
| 'Denoising strength proportional change starting value':denoising_strength_min, | |
| 'Denoising strength proportional change ending value':denoising_strength_max, | |
| 'CFG min':cfg_scale_min, | |
| 'CFG max':cfg_scale_max, | |
| 'use first image colors': use_first_image_colors, | |
| 'Saturation enhancement per image':saturation_per_image, | |
| 'Zoom level':zoom_level, | |
| } | |
| p.batch_size = 1 | |
| p.n_iter = 1 | |
| output_images, info = None, None | |
| initial_seed = None | |
| initial_info = None | |
| grids = [] | |
| all_images = [] | |
| state.job_count = loops * batch_count | |
| original_image = p.init_images[0].copy() | |
| if opts.img2img_color_correction: | |
| p.color_corrections = [processing.setup_color_correction(p.init_images[0])] | |
| for n in range(batch_count): | |
| history = [] | |
| multi_prompts_index = 0 | |
| loops = round(loops) | |
| for i in range(loops): | |
| p.n_iter = 1 | |
| p.batch_size = 1 | |
| p.do_not_save_grid = True | |
| if use_multi_prompts : | |
| image_range = (denoising_strength_last_image - denoising_strength_first_image) | |
| il = i % (image_range) | |
| if i == 0: | |
| p.prompt = ppos[multi_prompts_index] | |
| p.negative_prompt = pneg[multi_prompts_index] | |
| print("Prompt :",p.prompt) | |
| print("Negative prompt :",p.negative_prompt) | |
| if il == 0 and i > 0: | |
| multi_prompts_index+=1 | |
| try: | |
| if same_seed_per_prompt: | |
| if not same_seed_always: | |
| p.subseed = p.subseed + 1 if p.subseed_strength > 0 else p.subseed | |
| p.seed = p.seed + 1 if p.subseed_strength == 0 else p.seed | |
| p.prompt = ppos[multi_prompts_index] | |
| p.negative_prompt = pneg[multi_prompts_index] | |
| except Exception as e: | |
| multi_prompts_index = 0 | |
| if same_seed_per_prompt: | |
| if not same_seed_always: | |
| p.subseed = p.subseed + 1 if p.subseed_strength > 0 else p.subseed | |
| p.seed = p.seed + 1 if p.subseed_strength == 0 else p.seed | |
| p.prompt = ppos[multi_prompts_index] | |
| p.negative_prompt = pneg[multi_prompts_index] | |
| # print("Prompt :",p.prompt) | |
| # print("Negative prompt :",p.negative_prompt) | |
| if use_first_image_colors: | |
| p.color_corrections = [processing.setup_color_correction(original_image)] | |
| state.job = f"Iteration {i + 1}/{loops}, batch {n + 1}/{batch_count}" | |
| if denoising_strength_max > 0.1 : | |
| if use_sine_variation_dns : | |
| ds = remap_range(get_sin_steps(i,amplify_sine_variation_denoise,phase_diff_denoising),0,1,denoising_strength_min,denoising_strength_max) | |
| else: | |
| ds = remap_range(i+1,denoising_strength_first_image,denoising_strength_last_image,denoising_strength_min,denoising_strength_max) | |
| p.denoising_strength = round(ds,3) | |
| print("Denoising strength : "+str(p.denoising_strength)) | |
| if cfg_scale_max > 0.1 : | |
| if use_sine_variation_dns : | |
| cfgs = remap_range(get_sin_steps(i,amplify_sine_variation_denoise,phase_diff_denoising),0,1,cfg_scale_min,cfg_scale_max) | |
| else: | |
| cfgs = remap_range(i+1,denoising_strength_first_image,denoising_strength_last_image,cfg_scale_min,cfg_scale_max) | |
| p.cfg_scale = round(cfgs,2) | |
| print("CFG scale : "+str(p.cfg_scale)) | |
| processed = processing.process_images(p) | |
| if zoom_level != 1: | |
| if use_sine_variation_zoom : | |
| if loops >= denoising_strength_first_image : | |
| z = remap_range(get_sin_steps(i,amplify_sine_variation_zoom,phase_diff_zoom),0,1,1,zoom_level) | |
| processed.images[0] = self.zoom_into(processed.images[0], z, direction_x, direction_y) | |
| print("Zoom level :",z) | |
| else: | |
| processed.images[0] = self.zoom_into(processed.images[0], zoom_level, direction_x, direction_y) | |
| if initial_seed is None: | |
| initial_seed = processed.seed | |
| initial_info = processed.info | |
| if not same_init_image : | |
| init_img = processed.images[0] | |
| else: | |
| init_img = original_image | |
| if saturation_per_image != 1 : | |
| init_img = ImageEnhance.Color(init_img).enhance(saturation_per_image) | |
| p.init_images = [init_img] | |
| if not same_seed_per_prompt: | |
| if not same_seed_always: | |
| p.subseed = p.subseed + 1 if p.subseed_strength > 0 else p.subseed | |
| p.seed = p.seed + 1 if p.subseed_strength == 0 else p.seed | |
| p.denoising_strength = min(max(p.denoising_strength * denoising_strength_change_factor, 0.1), 1) | |
| history.append(processed.images[0]) | |
| if state.interrupted: | |
| break | |
| grid = images.image_grid(history, rows=1) | |
| if opts.grid_save: | |
| images.save_image(grid, p.outpath_grids, "grid", initial_seed, p.prompt, opts.grid_format, info=info, short_filename=not opts.grid_extended_filename, grid=True, p=p) | |
| grids.append(grid) | |
| all_images += history | |
| if opts.return_grid: | |
| all_images = grids + all_images | |
| processed = Processed(p, all_images, initial_seed, initial_info) | |
| return processed | |