Skip to content

Commit

Permalink
Add "Desired min SSIM threshold" and let SSIM give up when no progress
Browse files Browse the repository at this point in the history
  • Loading branch information
yownas committed Mar 14, 2023
1 parent 84d8ee7 commit 1aaace6
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 16 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ So, interpolating between the noise from two seeds will not only look cool as a

`SSIM minimum substep`: Smallest "step" SSIM is allowed to take. Sometimes animations can't me smoothed out, no matter how small steps you take. It is better to let the script give up and have a single skip than force it and get an animation that flickers.

`Desired min SSIM threshold (% of threshold)`: Try to make new images "at least" this good. By default SSIM will give up a newly generated image is worse then the gap it is trying to fill. This will allow you to set "Steps" to something as low as 1 and not have SSIM give up just because the image halfway through was bad.

# Output

The images and video (if selected) will show up in the `outputs\txt2-images\travels` folder. With a separate numbered folder for each travel you've made.
Expand Down
41 changes: 25 additions & 16 deletions scripts/seed_travel.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ def ui(self, is_img2img):
ratestr = gr.Slider(label='Rate strength', value=3, minimum=0.0, maximum=10.0, step=0.1)
allowdefsampler = gr.Checkbox(label='Allow the default Euler a Sampling method. (Does not produce good results)', value=False)
substep_min = gr.Number(label='SSIM minimum substep', value=0.0001)
ssim_diff_min = gr.Slider(label='Desired min SSIM threshold (% of threshold)', value=75, minimum=0, maximum=100, step=1)

return [rnd_seed, seed_count, dest_seed, steps, rate, ratestr, loopback, save_video, video_fps, show_images, compare_paths,
allowdefsampler, bump_seed, lead_inout, upscale_meth, upscale_ratio, use_cache, ssim_diff, ssim_ccrop, substep_min]
allowdefsampler, bump_seed, lead_inout, upscale_meth, upscale_ratio, use_cache, ssim_diff, ssim_ccrop, substep_min, ssim_diff_min]

def get_next_sequence_number(path):
from pathlib import Path
Expand All @@ -76,7 +77,7 @@ def get_next_sequence_number(path):
return result + 1

def run(self, p, rnd_seed, seed_count, dest_seed, steps, rate, ratestr, loopback, save_video, video_fps, show_images, compare_paths,
allowdefsampler, bump_seed, lead_inout, upscale_meth, upscale_ratio, use_cache, ssim_diff, ssim_ccrop, substep_min):
allowdefsampler, bump_seed, lead_inout, upscale_meth, upscale_ratio, use_cache, ssim_diff, ssim_ccrop, substep_min, ssim_diff_min):
initial_info = None
images = []
lead_inout=int(lead_inout)
Expand Down Expand Up @@ -269,7 +270,9 @@ def run(self, p, rnd_seed, seed_count, dest_seed, steps, rate, ratestr, loopback

check = True
skip_count = 0
not_better = 0
skip_ssim_min = 1.0
min_step = 1.0

done = 0
while(check):
Expand All @@ -285,7 +288,7 @@ def run(self, p, rnd_seed, seed_count, dest_seed, steps, rate, ratestr, loopback

seed_a, subseed_a, subseed_strength_a = step_keys[i]
seed_b, subseed_b, subseed_strength_b = step_keys[i+1]
if subseed_strength_b == 0:
if subseed_strength_b == 0: # If next image is the start of a new seed...
subseed_strength_b = 1

if d < ssim_diff and abs(subseed_strength_b - subseed_strength_a) > substep_min:
Expand All @@ -296,14 +299,12 @@ def run(self, p, rnd_seed, seed_count, dest_seed, steps, rate, ratestr, loopback
check = True

new_strength = (subseed_strength_a + subseed_strength_b)/2.0

#new_strength = (subseed_strength_a + subseed_strength_b)/2.0
#key = (from_seed, to_seed, new_strength)

key = (seed_a, subseed_a, new_strength)

p.seed, p.subseed, p.subseed_strength = key

if min_step > (subseed_strength_b - subseed_strength_a)/2.0:
min_step = (subseed_strength_b - subseed_strength_a)/2.0

# DEBUG
print(f"Process: {key} of {seeds}")
proc = process_images(p)
Expand All @@ -313,14 +314,23 @@ def run(self, p, rnd_seed, seed_count, dest_seed, steps, rate, ratestr, loopback

# upscale - copied from https://github.com/Kahsolt/stable-diffusion-webui-prompt-travel
if upscale_meth != 'None' and upscale_ratio != 1.0 and upscale_ratio != 0.0:
image = [resize_image(0, proc.images[0], tgt_w, tgt_h, upscaler_name=upscale_meth)]
image = resize_image(0, proc.images[0], tgt_w, tgt_h, upscaler_name=upscale_meth)
else:
image = proc.images[0]

# Check if this was an improvment
c = transform(image.convert('RGB')).unsqueeze(0)
d2 = ssim(a, c)

if d2 > min(d, ssim_diff*ssim_diff_min/100.0):
# Image is improvment or at least better than desired min ssim_diff
step_images.insert(i+1, image)
step_keys.insert(i+1, key)
else:
image = [proc.images[0]]
print(f"Failed to find improvment: {d2} < {d} ({d-d2}) Giving up.")
not_better += 1
done = i + 1

#images = images[0:i] + [image] + images[i:]
# TODO use cache?
step_images.insert(i+1, image[0])
step_keys.insert(i+1, key)
break;
else:
# DEBUG
Expand All @@ -335,8 +345,7 @@ def run(self, p, rnd_seed, seed_count, dest_seed, steps, rate, ratestr, loopback
done = i
# DEBUG
print("SSIM done!")
if skip_count > 0:
print(f"Minimum step limits reached: {skip_count} Worst: {skip_ssim_min}")
print(f"Stats: Skip count: {skip_count} Worst: {skip_ssim_min} No improvment: {not_better} Min. step: {min_step}")

if save_video:
frames = [np.asarray(step_images[0])] * lead_inout + [np.asarray(t) for t in step_images] + [np.asarray(step_images[-1])] * lead_inout
Expand Down

0 comments on commit 1aaace6

Please sign in to comment.