Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: txt2img advanced toggle for outputing every sampling step #41

Closed
SeverianVoid opened this issue Sep 1, 2022 · 16 comments

Comments

@SeverianVoid
Copy link

SeverianVoid commented Sep 1, 2022

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.

@AUTOMATIC1111
Copy link
Owner

I don't have an advanced tab.

@SeverianVoid
Copy link
Author

SeverianVoid commented Sep 1, 2022

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.

@orionaskatu
Copy link
Contributor

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)

@AUTOMATIC1111
Copy link
Owner

AUTOMATIC1111 commented Sep 1, 2022

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.

@AUTOMATIC1111
Copy link
Owner

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?

@SeverianVoid
Copy link
Author

SeverianVoid commented Sep 1, 2022

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.

@AUTOMATIC1111
Copy link
Owner

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.

@SeverianVoid
Copy link
Author

SeverianVoid commented Sep 1, 2022

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?

@AUTOMATIC1111
Copy link
Owner

Euler Ancestral 20 steps:
explorer_0qvifQMC39

Euler Ancestral 10 steps:
explorer_Cx9swdSrhm

@SeverianVoid
Copy link
Author

SeverianVoid commented Sep 1, 2022

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...

@SeverianVoid
Copy link
Author

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)

@AUTOMATIC1111
Copy link
Owner

AUTOMATIC1111 commented Sep 2, 2022

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.

@SeverianVoid
Copy link
Author

SeverianVoid commented Sep 2, 2022

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)	

@AUTOMATIC1111
Copy link
Owner

for step in list(range(100)) + list(range(105,250,5)) + range(260,400,10):
    ...

@michael-ts
Copy link

michael-ts commented Sep 21, 2022

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.)

@orionaskatu
Copy link
Contributor

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

Sashimimochi pushed a commit to Sashimimochi/stable-diffusion-webui that referenced this issue Apr 7, 2023
Franek313 pushed a commit to Franek313/stable-diffusion-webui that referenced this issue Feb 17, 2024
Forge use totally different mechanism to handle lora/lycoris models
I think it is good to remove the back compact things so "lyco" alias can be used by legacy lycoris extensions. (some other extension may rely on it)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants