move postprocessing scripts to accordions

Signed-off-by: Vladimir Mandic <mandic00@live.com>
This commit is contained in:
Vladimir Mandic
2024-12-23 12:23:18 -05:00
parent 2794b1abc4
commit 7d663249e8
7 changed files with 118 additions and 112 deletions
+12 -15
View File
@@ -11,24 +11,21 @@ Main ToDo list can be found at [GitHub projects](https://github.com/users/vladma
## Future Candidates
- Flux NF4 loader: <https://github.com/huggingface/diffusers/issues/9996>
## Other
- IPAdapter negative: <https://github.com/huggingface/diffusers/discussions/7167>
- Control API enhance scripts compatibility
- PixelSmith: <https://github.com/Thanos-DB/Pixelsmith>
## Code TODO
- TODO install: python 3.12.4 or higher cause a mess with pydantic (fixme)
- TODO install: enable ROCm for windows when available (fixme)
- TODO resize image: enable full VAE mode for resize-latent (fixme)
- TODO processing: remove duplicate mask params (fixme)
- TODO flux: fix loader for civitai nf4 models (fixme)
- TODO model loader: implement model in-memory caching (fixme)
- TODO hypertile: vae breaks when using non-standard sizes (fixme)
- TODO model load: force-reloading entire model as loading transformers only leads to massive memory usage (fixme)
- TODO lora load: direct with bnb (fixme)
- TODO: lora make: support quantized flux (fixme)
- TODO control: support scripts via api (fixme)
- TODO modernui: monkey-patch for missing tabs.select event (fixme)
- TODO install: python 3.12.4 or higher cause a mess with pydantic
- TODO install: enable ROCm for windows when available
- TODO resize image: enable full VAE mode for resize-latent
- TODO processing: remove duplicate mask params
- TODO flux: fix loader for civitai nf4 models
- TODO model loader: implement model in-memory caching
- TODO hypertile: vae breaks when using non-standard sizes
- TODO model load: force-reloading entire model as loading transformers only leads to massive memory usage
- TODO lora load: direct with bnb
- TODO lora make: support quantized flux
- TODO control: support scripts via api
- TODO modernui: monkey-patch for missing tabs.select event
+32 -26
View File
@@ -330,6 +330,7 @@ class ScriptRunner:
self.scripts = []
self.selectable_scripts = []
self.alwayson_scripts = []
self.auto_processing_scripts = []
self.titles = []
self.infotext_fields = []
self.paste_field_names = []
@@ -337,6 +338,31 @@ class ScriptRunner:
self.is_img2img = False
self.inputs = [None]
def add_script(self, script_class, path, is_img2img, is_control):
try:
script = script_class()
script.filename = path
script.is_txt2img = not is_img2img
script.is_img2img = is_img2img
if is_control: # this is messy but show is a legacy function that is not aware of control tab
v1 = script.show(script.is_txt2img)
v2 = script.show(script.is_img2img)
if v1 == AlwaysVisible or v2 == AlwaysVisible:
visibility = AlwaysVisible
else:
visibility = v1 or v2
else:
visibility = script.show(script.is_img2img)
if visibility == AlwaysVisible:
self.scripts.append(script)
self.alwayson_scripts.append(script)
script.alwayson = True
elif visibility:
self.scripts.append(script)
self.selectable_scripts.append(script)
except Exception as e:
errors.log.error(f'Script initialize: {path} {e}')
def initialize_scripts(self, is_img2img=False, is_control=False):
from modules import scripts_auto_postprocessing
@@ -351,34 +377,14 @@ class ScriptRunner:
self.scripts.clear()
self.alwayson_scripts.clear()
self.selectable_scripts.clear()
auto_processing_scripts = scripts_auto_postprocessing.create_auto_preprocessing_script_data()
self.auto_processing_scripts = scripts_auto_postprocessing.create_auto_preprocessing_script_data()
all_scripts = auto_processing_scripts + scripts_data
sorted_scripts = sorted(all_scripts, key=lambda x: x.script_class().title().lower())
sorted_scripts = sorted(scripts_data, key=lambda x: x.script_class().title().lower())
for script_class, path, _basedir, _script_module in sorted_scripts:
try:
script = script_class()
script.filename = path
script.is_txt2img = not is_img2img
script.is_img2img = is_img2img
if is_control: # this is messy but show is a legacy function that is not aware of control tab
v1 = script.show(script.is_txt2img)
v2 = script.show(script.is_img2img)
if v1 == AlwaysVisible or v2 == AlwaysVisible:
visibility = AlwaysVisible
else:
visibility = v1 or v2
else:
visibility = script.show(script.is_img2img)
if visibility == AlwaysVisible:
self.scripts.append(script)
self.alwayson_scripts.append(script)
script.alwayson = True
elif visibility:
self.scripts.append(script)
self.selectable_scripts.append(script)
except Exception as e:
errors.log.error(f'Script initialize: {path} {e}')
self.add_script(script_class, path, is_img2img, is_control)
sorted_scripts = sorted(self.auto_processing_scripts, key=lambda x: x.script_class().title().lower())
for script_class, path, _basedir, _script_module in sorted_scripts:
self.add_script(script_class, path, is_img2img, is_control)
def prepare_ui(self):
self.inputs = [None]
+1 -1
View File
@@ -837,7 +837,7 @@ options_templates.update(options_section(('sampler-params', "Sampler Settings"),
options_templates.update(options_section(('postprocessing', "Postprocessing"), {
'postprocessing_enable_in_main_ui': OptionInfo([], "Additional postprocessing operations", gr.Dropdown, lambda: {"multiselect":True, "choices": [x.name for x in shared_items.postprocessing_scripts()]}),
'postprocessing_operation_order': OptionInfo([], "Postprocessing operation order", gr.Dropdown, lambda: {"multiselect":True, "choices": [x.name for x in shared_items.postprocessing_scripts()]}),
'postprocessing_operation_order': OptionInfo([], "Postprocessing operation order", gr.Dropdown, lambda: {"multiselect":True, "choices": [x.name for x in shared_items.postprocessing_scripts()], "visible": False }),
"postprocessing_sep_img2img": OptionInfo("<h2>Inpaint</h2>", "", gr.HTML),
"img2img_color_correction": OptionInfo(False, "Apply color correction"),
+4 -3
View File
@@ -10,9 +10,10 @@ class ScriptPostprocessingCodeFormer(scripts_postprocessing.ScriptPostprocessing
order = 3000
def ui(self):
with gr.Row():
codeformer_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Strength", value=0.0, elem_id="extras_codeformer_visibility")
codeformer_weight = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Weight", value=0.2, elem_id="extras_codeformer_weight")
with gr.Accordion('Restore faces: CodeFormer', open = False):
with gr.Row():
codeformer_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Strength", value=0.0, elem_id="extras_codeformer_visibility")
codeformer_weight = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label="Weight", value=0.2, elem_id="extras_codeformer_weight")
return { "codeformer_visibility": codeformer_visibility, "codeformer_weight": codeformer_weight }
def process(self, pp: scripts_postprocessing.PostprocessedImage, codeformer_visibility, codeformer_weight): # pylint: disable=arguments-differ
+3 -2
View File
@@ -9,8 +9,9 @@ class ScriptPostprocessingGfpGan(scripts_postprocessing.ScriptPostprocessing):
order = 2000
def ui(self):
with gr.Row():
gfpgan_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Strength", value=0, elem_id="extras_gfpgan_visibility")
with gr.Accordion('Restore faces: GFPGan', open = False):
with gr.Row():
gfpgan_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Strength", value=0, elem_id="extras_gfpgan_visibility")
return { "gfpgan_visibility": gfpgan_visibility }
def process(self, pp: scripts_postprocessing.PostprocessedImage, gfpgan_visibility): # pylint: disable=arguments-differ
+32 -32
View File
@@ -10,43 +10,43 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
order = 1000
def ui(self):
selected_tab = gr.State(value=0) # pylint: disable=abstract-class-instantiated
with gr.Accordion('Postprocess Upscale', open = False):
selected_tab = gr.State(value=0) # pylint: disable=abstract-class-instantiated
with gr.Column():
with gr.Row(elem_id="extras_upscale"):
with gr.Tabs(elem_id="extras_resize_mode"):
with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by:
upscaling_resize = gr.Slider(minimum=0.1, maximum=8.0, step=0.05, label="Resize", value=2.0, elem_id="extras_upscaling_resize")
with gr.Column():
with gr.Row(elem_id="extras_upscale"):
with gr.Tabs(elem_id="extras_resize_mode"):
with gr.TabItem('Scale by', elem_id="extras_scale_by_tab") as tab_scale_by:
upscaling_resize = gr.Slider(minimum=0.1, maximum=8.0, step=0.05, label="Resize", value=2.0, elem_id="extras_upscaling_resize")
with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to:
with gr.Row():
with gr.Row(elem_id="upscaling_column_size"):
upscaling_resize_w = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=1024, elem_id="extras_upscaling_resize_w")
upscaling_resize_h = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=1024, elem_id="extras_upscaling_resize_h")
upscaling_res_switch_btn = ToolButton(value=symbols.switch, elem_id="upscaling_res_switch_btn")
upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
with gr.TabItem('Scale to', elem_id="extras_scale_to_tab") as tab_scale_to:
with gr.Row():
with gr.Row(elem_id="upscaling_column_size"):
upscaling_resize_w = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=1024, elem_id="extras_upscaling_resize_w")
upscaling_resize_h = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=1024, elem_id="extras_upscaling_resize_h")
upscaling_res_switch_btn = ToolButton(value=symbols.switch, elem_id="upscaling_res_switch_btn")
upscaling_crop = gr.Checkbox(label='Crop to fit', value=True, elem_id="extras_upscaling_crop")
with gr.Row():
extras_upscaler_1 = gr.Dropdown(label='Upscaler', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
with gr.Row():
extras_upscaler_1 = gr.Dropdown(label='Upscaler', elem_id="extras_upscaler_1", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
with gr.Row():
extras_upscaler_2 = gr.Dropdown(label='Refine Upscaler', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility")
with gr.Row():
extras_upscaler_2 = gr.Dropdown(label='Refine Upscaler', elem_id="extras_upscaler_2", choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name)
extras_upscaler_2_visibility = gr.Slider(minimum=0.0, maximum=1.0, step=0.001, label="Upscaler 2 visibility", value=0.0, elem_id="extras_upscaler_2_visibility")
upscaling_res_switch_btn.click(lambda w, h: (h, w), inputs=[upscaling_resize_w, upscaling_resize_h], outputs=[upscaling_resize_w, upscaling_resize_h], show_progress=False)
tab_scale_by.select(fn=lambda: 0, inputs=[], outputs=[selected_tab])
tab_scale_to.select(fn=lambda: 1, inputs=[], outputs=[selected_tab])
upscaling_res_switch_btn.click(lambda w, h: (h, w), inputs=[upscaling_resize_w, upscaling_resize_h], outputs=[upscaling_resize_w, upscaling_resize_h], show_progress=False)
tab_scale_by.select(fn=lambda: 0, inputs=[], outputs=[selected_tab])
tab_scale_to.select(fn=lambda: 1, inputs=[], outputs=[selected_tab])
return {
"upscale_mode": selected_tab,
"upscale_by": upscaling_resize,
"upscale_to_width": upscaling_resize_w,
"upscale_to_height": upscaling_resize_h,
"upscale_crop": upscaling_crop,
"upscaler_1_name": extras_upscaler_1,
"upscaler_2_name": extras_upscaler_2,
"upscaler_2_visibility": extras_upscaler_2_visibility,
}
return {
"upscale_mode": selected_tab,
"upscale_by": upscaling_resize,
"upscale_to_width": upscaling_resize_w,
"upscale_to_height": upscaling_resize_h,
"upscale_crop": upscaling_crop,
"upscaler_1_name": extras_upscaler_1,
"upscaler_2_name": extras_upscaler_2,
"upscaler_2_visibility": extras_upscaler_2_visibility,
}
def upscale(self, image, info, upscaler, upscale_mode, upscale_by, upscale_to_width, upscale_to_height, upscale_crop):
if upscale_mode == 1:
+34 -33
View File
@@ -7,40 +7,41 @@ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
name = "Video"
def ui(self):
def video_type_change(video_type):
return [
gr.update(visible=video_type != 'None'),
gr.update(visible=video_type == 'GIF' or video_type == 'PNG'),
gr.update(visible=video_type == 'MP4'),
gr.update(visible=video_type == 'MP4'),
gr.update(visible=video_type == 'MP4'),
gr.update(visible=video_type == 'MP4'),
]
with gr.Accordion('Create video', open = False):
def video_type_change(video_type):
return [
gr.update(visible=video_type != 'None'),
gr.update(visible=video_type == 'GIF' or video_type == 'PNG'),
gr.update(visible=video_type == 'MP4'),
gr.update(visible=video_type == 'MP4'),
gr.update(visible=video_type == 'MP4'),
gr.update(visible=video_type == 'MP4'),
]
with gr.Row():
gr.HTML("<span>&nbsp Video</span><br>")
with gr.Row():
video_type = gr.Dropdown(label='Video file', choices=['None', 'GIF', 'PNG', 'MP4'], value='None', elem_id="extras_video_type")
duration = gr.Slider(label='Duration', minimum=0.25, maximum=10, step=0.25, value=2, visible=False, elem_id="extras_video_duration")
with gr.Row():
loop = gr.Checkbox(label='Loop', value=True, visible=False, elem_id="extras_video_loop")
pad = gr.Slider(label='Pad frames', minimum=0, maximum=24, step=1, value=1, visible=False, elem_id="extras_video_pad")
interpolate = gr.Slider(label='Interpolate frames', minimum=0, maximum=24, step=1, value=0, visible=False, elem_id="extras_video_interpolate")
scale = gr.Slider(label='Rescale', minimum=0.5, maximum=2, step=0.05, value=1, visible=False, elem_id="extras_video_scale")
change = gr.Slider(label='Frame change sensitivity', minimum=0, maximum=1, step=0.05, value=0.3, visible=False, elem_id="extras_video_change")
with gr.Row():
filename = gr.Textbox(label='Filename', placeholder='enter filename', lines=1, elem_id="extras_video_filename")
video_type.change(fn=video_type_change, inputs=[video_type], outputs=[duration, loop, pad, interpolate, scale, change])
return {
"filename": filename,
"video_type": video_type,
"duration": duration,
"loop": loop,
"pad": pad,
"interpolate": interpolate,
"scale": scale,
"change": change,
}
with gr.Row():
gr.HTML("<span>&nbsp Video</span><br>")
with gr.Row():
video_type = gr.Dropdown(label='Video file', choices=['None', 'GIF', 'PNG', 'MP4'], value='None', elem_id="extras_video_type")
duration = gr.Slider(label='Duration', minimum=0.25, maximum=10, step=0.25, value=2, visible=False, elem_id="extras_video_duration")
with gr.Row():
loop = gr.Checkbox(label='Loop', value=True, visible=False, elem_id="extras_video_loop")
pad = gr.Slider(label='Pad frames', minimum=0, maximum=24, step=1, value=1, visible=False, elem_id="extras_video_pad")
interpolate = gr.Slider(label='Interpolate frames', minimum=0, maximum=24, step=1, value=0, visible=False, elem_id="extras_video_interpolate")
scale = gr.Slider(label='Rescale', minimum=0.5, maximum=2, step=0.05, value=1, visible=False, elem_id="extras_video_scale")
change = gr.Slider(label='Frame change sensitivity', minimum=0, maximum=1, step=0.05, value=0.3, visible=False, elem_id="extras_video_change")
with gr.Row():
filename = gr.Textbox(label='Filename', placeholder='enter filename', lines=1, elem_id="extras_video_filename")
video_type.change(fn=video_type_change, inputs=[video_type], outputs=[duration, loop, pad, interpolate, scale, change])
return {
"filename": filename,
"video_type": video_type,
"duration": duration,
"loop": loop,
"pad": pad,
"interpolate": interpolate,
"scale": scale,
"change": change,
}
def postprocess(self, images, filename, video_type, duration, loop, pad, interpolate, scale, change): # pylint: disable=arguments-differ
filename = filename.strip() if filename is not None else ''