Skip to content

Commit

Permalink
Add save_intermediate_images script
Browse files Browse the repository at this point in the history
Combines a few different scripts in various GitHub issues with some
useful added features:

- This script is set to `scripts.AlwaysVisible`, meaning it can be run
  in combination with other scripts
- Intermediate images are saved using the same filename structure as the
  final images, in a subdirectory called "intermediates". The custom script
  in the wiki overwrites your intermediate images each time you generate
  new images
- Allows you to save every N images (defaults to 5)
- Allows you to save either denoised or noisy intermediate images

See AUTOMATIC1111#1026
See AUTOMATIC1111#2137
See AUTOMATIC1111#2094
See AUTOMATIC1111#2739
See AUTOMATIC1111#4709
  • Loading branch information
kevinschaul committed Dec 6, 2022
1 parent 44c46f0 commit db31726
Showing 1 changed file with 51 additions and 0 deletions.
51 changes: 51 additions & 0 deletions scripts/save_intermediate_images.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import os

from modules import scripts
from modules.processing import Processed, process_images, fix_seed
from modules.sd_samplers import KDiffusionSampler, sample_to_image
from modules.images import save_image

import gradio as gr

orig_callback_state = KDiffusionSampler.callback_state


class Script(scripts.Script):
def title(self):
return "Save intermediate images during the sampling process"

def show(self, is_img2img):
return scripts.AlwaysVisible

def ui(self, is_img2img):
is_active = gr.Checkbox(label="Save intermediate images", value=False)
intermediate_type = gr.Radio(label="Should the intermediate images by denoised or noisy?", choices=["Denoised", "Noisy"], value="Denoised")
every_n = gr.Number(label="Save every N images", value=5)
return [is_active, intermediate_type, every_n]

def run(self, p, is_active, intermediate_type, every_n):
fix_seed(p)
return Processed(p, images, p.seed)

def process(self, p, is_active, intermediate_type, every_n):
if is_active:
def callback_state(self, d):
"""
callback_state runs after each processing step
"""
current_step = d["i"]

if current_step % every_n == 0:
if intermediate_type == "Denoised":
image = sample_to_image(d["denoised"])
else:
image = sample_to_image(d["x"])

save_image(image, os.path.join(p.outpath_samples, "intermediates"), f"{current_step:02}", seed=p.seed, p=p)

return orig_callback_state(self, d)

setattr(KDiffusionSampler, "callback_state", callback_state)

def postprocess(self, p, processed, is_active, intermediate_type, every_n):
setattr(KDiffusionSampler, "callback_state", orig_callback_state)

1 comment on commit db31726

@Pun0110
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed import section...

import os

from modules import scripts
from modules.processing import Processed, process_images, fix_seed
from modules.sd_samplers_common import sample_to_image
from modules.sd_samplers_kdiffusion import KDiffusionSampler
from modules.images import save_image

import gradio as gr

orig_callback_state = KDiffusionSampler.callback_state


class Script(scripts.Script):
    def title(self):
        return "Save intermediate images during the sampling process"

    def show(self, is_img2img):
        return scripts.AlwaysVisible

    def ui(self, is_img2img):
        is_active = gr.Checkbox(label="Save intermediate images", value=False)
        intermediate_type = gr.Radio(label="Should the intermediate images by denoised or noisy?", choices=["Denoised", "Noisy"], value="Denoised")
        every_n = gr.Number(label="Save every N images", value=5)
        return [is_active, intermediate_type, every_n]

    def run(self, p, is_active, intermediate_type, every_n):
        fix_seed(p)
        return Processed(p, images, p.seed)

    def process(self, p, is_active, intermediate_type, every_n):
        if is_active:
            def callback_state(self, d):
                """
                callback_state runs after each processing step
                """
                current_step = d["i"]

                if current_step % every_n == 0:
                    if intermediate_type == "Denoised":
                        image = sample_to_image(d["denoised"])
                    else:
                        image = sample_to_image(d["x"])

                    save_image(image, os.path.join(p.outpath_samples, "intermediates"), f"{current_step:02}", seed=p.seed, p=p)

                return orig_callback_state(self, d)

            setattr(KDiffusionSampler, "callback_state", callback_state)

    def postprocess(self, p, processed, is_active, intermediate_type, every_n):
        setattr(KDiffusionSampler, "callback_state", orig_callback_state)

Please sign in to comment.