AUTOMATIC1111/stable-diffusion-webui

Feature Request: txt2img advanced toggle for outputing every sampling step

SeverianVoid opened this issue · 16 comments

Wondering if you would be able to add a toggle in the advanced tab of the txt2img generator that would cause it to output the image at each sampling step. I noticed that when using certain sampling methods mostly euler_a and dpm2_a they can change the image quite dramatically between sampling steps.

Right now I am just manually incrementing the sampling number and regenerating the image for each sampling step. Which seems like a huge waste since for each next step I am having to reprocess all of the preceding step.

I don't have an advanced tab.

You make a very good point, I have far to many versions installed at this point I am losing track of them. A toggle in the settings panel would be nice to be able to output the image at each step. Maybe next to the Save Image Grids toggle.

As explained here you can use a script for that.

For example if you want each image for steps 10, 15, 20, 25 and 30 on samplers euler_a, dpm2_a and DDIM :

steps = [10,15,20,25,30]
sampler_index = [0,5,6]

def cell(x, y, p=p):
	p.steps = x
	p.sampler_index = y
	return process_images(p).images[0]

images = [draw_xy_grid(
	xs = steps,
	ys = sampler_index,
	x_label = lambda x: f'Steps = {x}',
	y_label = lambda y: f'Sampler = {samplers[y].name}',
	cell = cell
)]

save_image(images[0], 'test/example', 'example')
display(images)

Well, what he's asking theoretically is possible via script but it would be a lot more difficult than drawing a grid. He wants to save images during sampling.

SeverianVoid: how do you see this feature? Will you have it on at most times or just occasionally experiment with it? A lot of images saved will be garbage. Would if be ok for example to save them as 1.png, 2.png ... 99.png in some directory?

It does indeed generate a whole lot of images since I was manually saving out each step 1, 2, 3, 4, 5 up to 100 and then steps of 5 after that since generation was starting to take so long 105, 110, up to the 250 max. In the end I used each image as a frame in a video so you could see the generation process as the different samplers converged on an image or converged for a bit and then wander off again. But seems like a huge waste to generate 99 steps to get image 99 and then regenerate all 99 again +1 to get image 100.

An example of just how much difference can be between individual steps with no other changes to generation
https://drive.google.com/file/d/1aVC9Schgf1ygdYVxXiR-W_8QDuLc9-Zn/

All identical prompt and seed the only change is the sampling method
K_LMS: https://youtube.com/shorts/OQmJUKqk8ZQ
DPM2_A: https://youtube.com/shorts/6UskP8iUnp0
EULAR_A: https://youtube.com/shorts/Z93_fprh7s4

you can see that eular_a and dpm2_a both have a much more sporadic image generation with larger differences between individual steps. I found that K_LMS and basically everything else eular, ddim, heun, dpm2, plms converge on the same image eventually. But I was quite surprised at just how much difference exists between individual steps with the dpm2_a and eular_a sampling methods. Also interesting that unlike the other sampling methods those two also don't seem to eventually settle on a final image with no further changes happening, instead settling eventually for a bit before drifting off again.

I tended to generate batches of 12 images at a time before finding one I thought looked interesting to explore further and then proceeded to generate all the steps using that one seed. Saving them out to a folder sequentially is perfect since I was then importing them into ImageJ as sequential sets to save out as videos.

But seems like a huge waste to generate 99 steps to get image 99 and then regenerate all 99 again +1 to get image 100.

All right there seems to be a misunderstanding here. Setting steps to N and then saving (N-1)-th image will give you a different result from setting steps to (N-1) and then saving (N-1)-th image. You were doing a different thing, to do what you were doing, the only way is to properly go all the way discard all previous images for every value of steps.

Huh, so if I understand you correctly if I set it to 100 steps and had it spit out the image at each step as it did 100 steps to the final image the intermediate steps from that process would be different images than settings steps to 1 saving that, then setting 2 and generating that, then 3, and so on?

Euler Ancestral 20 steps:
explorer_0qvifQMC39

Euler Ancestral 10 steps:
explorer_Cx9swdSrhm

Huh that's kind of unexpected and not at all how I thought sampling steps worked. Would explain how it generated such radical changes between single step values...

So in theory what I am trying to do could be accomplished using the scripting section somehow, I haven't quite been able to figure out how to combine the two examples to get it to work but

steps = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,55,60,65,70,75,80,85,90,95,100]

# needs to loop over the steps so I know this parts important somehow but I don't know what the cell thing does

def cell(x, p=p):
	p.steps = x
	return process_images(p).images[0]

# I dont need it to draw the grid so I would remove this but then I dont know what to do with the cell part that had to be defined before which is used here I just want to save out the automated generation of step images

images = [draw_xy_grid(
	xs = steps,
	x_label = lambda x: f'Steps = {x}',
	y_label = lambda y: f'CFG = {y}',
	cell = cell
)]
processed = process_images(p)
display(processed.images, processed.seed, processed.info)
for step in range(10): # alternatively: for steps in [1,2,3,5,10,100]
	p.steps = step+1
	
	processed = process_images(p)
	
	# save_image() automatially adds a number to filename
	save_image(processed.images[0], 'directory_with_images', 'file', no_prompt=True)

explorer_i5sw3aNG9f

Don't forget to choose seed in UI or it will be different every time.

My next set, these were so much easier to make with the scripting to automate the generation!

KLMS https://youtube.com/shorts/q_iamVciIe4
DPM2_A https://youtube.com/shorts/pD1A5a2oaPY
EULAR_A https://youtube.com/shorts/d9o_4cJ7-78

I managed to figure out how to modify the script a little so I got all the images I wanted out as well as the extra generation info in the names of the files so I dont forget, works wonderfully though with out the pausing in between images when I was making them manually my gpu is a lot more unhappy.

foldername='Steplapse/projectnumber/samplingmethod'

for step in range(100):
	p.steps = step+1	
	processed = process_images(p)	
	# save_image() automatially adds a number to filename
	save_image(processed.images[0], foldername, 'file', p.seed, p.prompt, info=processed.info, no_prompt=False)
	
for step in range(105,250,5):
	p.steps = step
	processed = process_images(p)	
	# save_image() automatially adds a number to filename
	save_image(processed.images[0], foldername, 'file', p.seed, p.prompt, info=processed.info, no_prompt=False)	

for step in range(260,400,10):
	p.steps = step
	processed = process_images(p)	
	# save_image() automatially adds a number to filename
	save_image(processed.images[0], foldername, 'file', p.seed, p.prompt, info=processed.info, no_prompt=False)	
for step in list(range(100)) + list(range(105,250,5)) + range(260,400,10):
    ...

As explained here you can use a script for that.

When I follow that link it just takes me to the main page; the specific anchor does not seem to exist. (I'm basically just interested in automating repetitive things so I don't have to keep entering stuff into the UI to try variations on something I like.)

As explained here you can use a script for that.

When I follow that link it just takes me to the main page; the specific anchor does not seem to exist. (I'm basically just interested in automating repetitive things so I don't have to keep entering stuff into the UI to try variations on something I like.)

The documentation was moved in the wiki : https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Custom-Scripts