fix for batch_count and other small fixes, #16, #14

main
AlUlkesh 2023-01-18 22:26:39 +01:00
parent 95c58f667f
commit 7f8fda4e15
2 changed files with 132 additions and 104 deletions

View File

@ -22,6 +22,8 @@ Once the image generation begins, the intermediate images will start saving in a
Please be aware that _Image creation progress preview mode_ in the webui's settings affects how the intermediate images are created.
You can also make a video out of the intermediate images:
<p><img src="images/13655-sample.gif"/>
<p>GIF:<br>
<img src="images/13655-sample.gif"/>
<img src="images/13642-sample.gif"/>
<p>MP4, with interpolation:<br>
<video src='https://user-images.githubusercontent.com/99896447/213034519-7b6ed42f-39d5-4994-a8b7-c85ec92bda84.mp4' autoplay loop></video>

View File

@ -16,6 +16,74 @@ import gradio as gr; gr.__version__
orig_callback_state = KDiffusionSampler.callback_state
def make_video(p, ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug):
if ssii_is_active and ssii_video and not state.skipped and not state.interrupted:
logger = logging.getLogger(__name__)
# ffmpeg requires sequential numbers in filenames (that is exactly +1)
p.intermed_files.sort(key=lambda x: x[0])
prev_batch = None
for real_i, (batch_no, name_org, _) in enumerate(p.intermed_files):
if prev_batch != batch_no:
i = 0
num_seq = '{:03}'.format(i)
name_seq = re.sub(r'^\d+-(\d{3})', f'{name_org.split("-")[0]}-{num_seq}', name_org)
p.intermed_files[real_i] = (batch_no, name_org, name_seq)
path_name_org = os.path.join(p.intermed_outpath, name_org)
path_name_seq = os.path.join(p.intermed_outpath, name_seq)
os.replace(path_name_org, path_name_seq)
logger.debug(f"replace {path_name_org} / {path_name_seq}")
i = i + 1
prev_batch = batch_no
frames_per_image = i
for intermed_pattern in p.intermed_pattern.values():
img_file = intermed_pattern.replace("%%%", "%03d") + ".png"
vid_file = intermed_pattern.replace("%%%-", "") + "." + ssii_video_format
if hasattr(p, "enable_hr"):
if p.enable_hr and ssii_video_hires == "1":
img_file = img_file.replace("-p2-", "-p1-")
vid_file = vid_file.replace("-p2-", "-p1-")
path_img_file = os.path.join(p.intermed_outpath, img_file)
path_vid_file = os.path.join(p.intermed_outpath, vid_file)
if ssii_smooth:
pts = (round(ssii_seconds / frames_per_image, 5))
logger.debug(f"pts: {pts}")
if pts < 1:
pts = "1"
else:
pts = str(pts)
if ssii_video_format == "gif":
ff = FFmpeg(
inputs={path_img_file: "-benchmark -framerate 1"},
outputs={path_vid_file: f'-filter_complex "split[v1][v2]; [v1]palettegen=stats_mode=full [palette]; [v2][palette]paletteuse=dither=sierra2_4a [v3]; [v3]setpts={pts}*PTS [v4]; [v4]minterpolate=fps={int(ssii_video_fps)}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1"'}
)
else:
ff = FFmpeg(
inputs={path_img_file: "-benchmark -framerate 1"},
outputs={path_vid_file: f'-filter_complex "setpts={pts}*PTS [v4]; [v4]minterpolate=fps={int(ssii_video_fps)}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1"'}
)
else:
if ssii_video_format == "gif":
ff = FFmpeg(
inputs={path_img_file: f"-benchmark -framerate {int(ssii_video_fps)}"},
outputs={path_vid_file: '-filter_complex "split[v1][v2]; [v1]palettegen=stats_mode=full [palette]; [v2][palette]paletteuse=dither=sierra2_4a"'}
)
else:
ff = FFmpeg(
inputs={path_img_file: f"-benchmark -framerate {int(ssii_video_fps)}"},
outputs={path_vid_file: None}
)
ff.run()
# Back to original numbering
for (batch_no, name_org, name_seq) in reversed(p.intermed_files):
path_name_org = os.path.join(p.intermed_outpath, name_org)
path_name_seq = os.path.join(p.intermed_outpath, name_seq)
os.replace(path_name_seq, path_name_org)
logger.debug(f"replace {path_name_seq} / {path_name_org}")
return
class Script(scripts.Script):
def title(self):
return "Save intermediate images during the sampling process"
@ -90,7 +158,7 @@ class Script(scripts.Script):
return [ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug]
def save_image_only_get_name(image, path, basename, seed=None, prompt=None, extension='png', info=None, short_filename=False, no_prompt=False, grid=False, pnginfo_section_name='parameters', p=None, existing_info=None, forced_filename=None, suffix="", save_to_dirs=None):
#for description see modules.images.save_image, same code up saving of files
# for description see modules.images.save_image, same code up saving of files
namegen = FilenameGenerator(p, seed, prompt, image)
@ -176,7 +244,20 @@ class Script(scripts.Script):
logger.debug(f"Step: {current_step}")
logger.debug(f"hr: {hr}")
#Highres. fix requires 2 passes
if current_step == 0:
# Deal with batch_count > 1
if hasattr(p, 'intermed_batch_iter'):
if p.iteration > p.intermed_batch_iter:
p.intermed_batch_iter = p.iteration
# Reset per-batch_count-attributes
delattr(p, "intermed_final_pass")
delattr(p, "intermed_max_step")
# Make video for previous batch_count
make_video(p, ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug)
else:
p.intermed_batch_iter = p.iteration
# Highres. fix requires 2 passes
if not hasattr(p, 'intermed_final_pass'):
if hr:
p.intermed_first_pass = True
@ -185,7 +266,7 @@ class Script(scripts.Script):
p.intermed_first_pass = True
p.intermed_final_pass = True
#Check if pass 1 has finished
# Check if pass 1 has finished
if hasattr(p, 'intermed_max_step'):
if current_step >= p.intermed_max_step:
p.intermed_max_step = current_step
@ -196,7 +277,7 @@ class Script(scripts.Script):
else:
p.intermed_max_step = current_step
#ssii_stop_at_n must be a multiple of ssii_every_n
# ssii_stop_at_n must be a multiple of ssii_every_n
if not hasattr(p, 'intermed_ssii_stop_at_n'):
if ssii_stop_at_n % ssii_every_n == 0:
p.intermed_ssii_stop_at_n = ssii_stop_at_n
@ -205,6 +286,7 @@ class Script(scripts.Script):
if current_step % ssii_every_n == 0:
for index in range(0, p.batch_size):
# Live preview only works on first batch_pos
if ssii_intermediate_type == "According to Live preview subject setting" and index == 0:
image = state.current_image
elif ssii_intermediate_type == "Noisy":
@ -214,6 +296,7 @@ class Script(scripts.Script):
logger.debug(f"ssii_intermediate_type, ssii_every_n, ssii_stop_at_n: {ssii_intermediate_type}, {ssii_every_n}, {ssii_stop_at_n}")
logger.debug(f"Step: {current_step}")
logger.debug(f"batch_count, iteration, batch_size, batch_pos: {p.n_iter}, {p.iteration}, {p.batch_size}, {index}")
# Inits per seed
if current_step == 0 and p.intermed_first_pass:
@ -263,46 +346,52 @@ class Script(scripts.Script):
logger.debug(f"p.all_seeds: {p.all_seeds}")
logger.debug(f"p.cfg_scale: {p.cfg_scale}")
logger.debug(f"p.sampler_name: {p.sampler_name}")
logger.debug(f"p.batch_size: {p.batch_size}")
intermed_suffix = p.intermed_outpath_suffix.replace(str(int(p.seed)), str(int(p.all_seeds[index])), 1)
intermed_pattern = p.intermed_outpath_number[index] + "-%%%-" + intermed_suffix
if hr:
if p.intermed_final_pass:
intermed_pattern = intermed_pattern.replace("%%%", "%%%-p2")
else:
intermed_pattern = intermed_pattern.replace("%%%", "%%%-p1")
p.intermed_pattern[int(p.all_seeds[index])] = intermed_pattern
filename = intermed_pattern.replace("%%%", f"{current_step:03}")
#don't save first step
if current_step > 0:
#generate png-info
infotext = create_infotext(p, p.all_prompts, p.all_seeds, p.all_subseeds, comments=[], position_in_batch=index % p.batch_size, iteration=index // p.batch_size)
infotext = f'{infotext}, intermediate: {current_step:03d}'
if current_step == p.intermed_ssii_stop_at_n:
if (hr and p.intermed_final_pass) or not hr:
#early stop for this seed reached, prevent normal save, save as final image
p.do_not_save_samples = True
save_image(image, p.outpath_samples, "", p.all_seeds[index], p.prompt, opts.samples_format, info=infotext, p=p)
if index == p.batch_size - 1:
#early stop for final seed and final pass reached, interrupt further processing
state.interrupt()
# Don't continue with no image (can happen with live preview subject setting)
if image is None:
logger.debug("image is None")
else:
intermed_seed_index = p.iteration * p.batch_size + index
intermed_seed = int(p.all_seeds[intermed_seed_index])
logger.debug(f"intermed_seed_index, intermed_seed: {intermed_seed_index}, {intermed_seed}")
intermed_suffix = p.intermed_outpath_suffix.replace(str(int(p.seed)), str(intermed_seed), 1)
intermed_pattern = p.intermed_outpath_number[index] + "-%%%-" + intermed_suffix
if hr:
if p.intermed_final_pass:
intermed_pattern = intermed_pattern.replace("%%%", "%%%-p2")
else:
#save intermediate image
intermed_pattern = intermed_pattern.replace("%%%", "%%%-p1")
p.intermed_pattern[intermed_seed] = intermed_pattern
filename = intermed_pattern.replace("%%%", f"{current_step:03}")
# Don't save first step
if current_step > 0:
# generate png-info
infotext = create_infotext(p, p.all_prompts, p.all_seeds, p.all_subseeds, comments=[], position_in_batch=index % p.batch_size, iteration=index // p.batch_size)
infotext = f'{infotext}, intermediate: {current_step:03d}'
if current_step == p.intermed_ssii_stop_at_n:
if (hr and p.intermed_final_pass) or not hr:
# early stop for this seed reached, prevent normal save, save as final image
p.do_not_save_samples = True
save_image(image, p.outpath_samples, "", intermed_seed, p.prompt, opts.samples_format, info=infotext, p=p)
if index == p.batch_size - 1:
# early stop for final seed and final pass reached, interrupt further processing
state.interrupt()
else:
# save intermediate image
save_image(image, p.intermed_outpath, "", info=infotext, p=p, forced_filename=filename, save_to_dirs=False)
filename_clean = re.sub(r"[^\d-]", "%", filename)
logger.debug(f"filename: {filename_clean}")
if ssii_video and ((hr and p.intermed_first_pass and ssii_video_hires == "1") or (hr and p.intermed_final_pass and ssii_video_hires == "2") or not hr):
p.intermed_files.append((index, filename + ".png", None))
else:
# save intermediate image
save_image(image, p.intermed_outpath, "", info=infotext, p=p, forced_filename=filename, save_to_dirs=False)
filename_clean = re.sub(r"[^\d-]", "%", filename)
logger.debug(f"filename: {filename_clean}")
if ssii_video and ((hr and p.intermed_first_pass and ssii_video_hires == "1") or (hr and p.intermed_final_pass and ssii_video_hires == "2") or not hr):
p.intermed_files.append((index, filename + ".png", None))
else:
#save intermediate image
save_image(image, p.intermed_outpath, "", info=infotext, p=p, forced_filename=filename, save_to_dirs=False)
filename_clean = re.sub(r"[^\d-]", "%", filename)
logger.debug(f"filename: {filename_clean}")
if ssii_video and ((hr and p.intermed_first_pass and ssii_video_hires == "1") or (hr and p.intermed_final_pass and ssii_video_hires == "2") or not hr):
p.intermed_files.append((index, filename + ".png", None))
return orig_callback_state(self, d)
setattr(KDiffusionSampler, "callback_state", callback_state)
@ -310,68 +399,5 @@ class Script(scripts.Script):
def postprocess(self, p, processed, ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug):
setattr(KDiffusionSampler, "callback_state", orig_callback_state)
# Make a video file
if ssii_is_active and ssii_video and not state.skipped and not state.interrupted:
logger = logging.getLogger(__name__)
# ffmpeg requires sequential numbers in filenames (that is exactly +1)
p.intermed_files.sort(key=lambda x: x[0])
prev_batch = None
for real_i, (batch_no, name_org, _) in enumerate(p.intermed_files):
if prev_batch != batch_no:
i = 0
num_seq = '{:03}'.format(i)
name_seq = re.sub(r'^\d+-(\d{3})', f'{name_org.split("-")[0]}-{num_seq}', name_org)
p.intermed_files[real_i] = (batch_no, name_org, name_seq)
path_name_org = os.path.join(p.intermed_outpath, name_org)
path_name_seq = os.path.join(p.intermed_outpath, name_seq)
os.replace(path_name_org, path_name_seq)
logger.debug(f"replace {path_name_org} / {path_name_seq}")
i = i + 1
prev_batch = batch_no
frames_per_image = i
for intermed_pattern in p.intermed_pattern.values():
img_file = intermed_pattern.replace("%%%", "%03d") + ".png"
vid_file = intermed_pattern.replace("%%%-", "") + "." + ssii_video_format
if hasattr(p, "enable_hr"):
if p.enable_hr and ssii_video_hires == "1":
img_file = img_file.replace("-p2-", "-p1-")
vid_file = vid_file.replace("-p2-", "-p1-")
path_img_file = os.path.join(p.intermed_outpath, img_file)
path_vid_file = os.path.join(p.intermed_outpath, vid_file)
if ssii_smooth:
pts = (round(ssii_seconds / frames_per_image, 5))
logger.debug(f"pts: {pts}")
if pts < 1:
pts = "1"
else:
pts = str(pts)
if ssii_video_format == "gif":
ff = FFmpeg(
inputs={path_img_file: "-benchmark -framerate 1"},
outputs={path_vid_file: f'-filter_complex "split[v1][v2]; [v1]palettegen=stats_mode=full [palette]; [v2][palette]paletteuse=dither=sierra2_4a [v3]; [v3]setpts={pts}*PTS [v4]; [v4]minterpolate=fps={int(ssii_video_fps)}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1"'}
)
else:
ff = FFmpeg(
inputs={path_img_file: "-benchmark -framerate 1"},
outputs={path_vid_file: f'-filter_complex "setpts={pts}*PTS [v4]; [v4]minterpolate=fps={int(ssii_video_fps)}:mi_mode=mci:mc_mode=aobmc:me_mode=bidir:vsbmc=1"'}
)
else:
if ssii_video_format == "gif":
ff = FFmpeg(
inputs={path_img_file: f"-benchmark -framerate {int(ssii_video_fps)}"},
outputs={path_vid_file: '-filter_complex "split[v1][v2]; [v1]palettegen=stats_mode=full [palette]; [v2][palette]paletteuse=dither=sierra2_4a"'}
)
else:
ff = FFmpeg(
inputs={path_img_file: f"-benchmark -framerate {int(ssii_video_fps)}"},
outputs={path_vid_file: None}
)
ff.run()
# Back to original numbering
for (batch_no, name_org, name_seq) in reversed(p.intermed_files):
path_name_org = os.path.join(p.intermed_outpath, name_org)
path_name_seq = os.path.join(p.intermed_outpath, name_seq)
os.replace(path_name_seq, path_name_org)
logger.debug(f"replace {path_name_seq} / {path_name_org}")
# Make video for last batch_count
make_video(p, ssii_is_active, ssii_intermediate_type, ssii_every_n, ssii_stop_at_n, ssii_video, ssii_video_format, ssii_video_fps, ssii_video_hires, ssii_smooth, ssii_seconds, ssii_debug)