Skip to content

Commit a9b5745

Browse files
committed
pass previous frame into ControlNet for video and fix ui-config
1 parent 6e58fa9 commit a9b5745

9 files changed

+69
-26
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ When you press the "Apply hires fix" button, the extension regenerates the image
8080
- ☑️ progress bar + interrupt
8181
- ☑️ option for pass into hires fix automatically
8282
- ☑️ control net
83-
- pass previous frame into ControlNet for video
83+
- ☑️ pass previous frame into ControlNet for video
8484
- tiled vae
8585
- ☑️ "hide segment anything extention" option
8686
- ☑️ txt2img script

docs/usage.md

+2
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ To suppress flickering you can generate in little fps (e.g. 10), then interpolat
9696

9797
You can also use [sd-webui-controlnet](https://github.com/Mikubill/sd-webui-controlnet) or [lama-cleaner](https://github.com/light-and-ray/sd-webui-lama-cleaner-masked-content) with (low denosing) extensions to increase consistency, if it fits to your scenario
9898

99+
Also a good can be to use `Pass previous frame into ControlNet` with _IP-Adapter_, _Reference_, _Revision_, _T2IA Color_, _T2IA Style_
100+
99101

100102
## Dedicated page
101103
Dedicated page (replacer tab only) is available on url `/replacer-dedicated`

replacer/generation_args.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ class GenerationArgs:
8080

8181
pass_into_hires_fix_automatically: bool
8282
save_before_hires_fix: bool
83-
hires_fix_args: HiresFixArgs
83+
previous_frame_into_controlnet: list
8484

85+
hires_fix_args: HiresFixArgs
8586
cn_args: list
8687
soft_inpaint_args: list
8788

replacer/inpaint.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ def inpaint(
6969
p.do_not_save_grid = True
7070
try:
7171
if replacer_scripts.script_controlnet and gArgs.cn_args is not None and len(gArgs.cn_args) != 0:
72-
replacer_scripts.enableInpaintModeForCN(gArgs.cn_args, p)
72+
previousFrame = None
73+
if batch_processed:
74+
previousFrame = batch_processed.images[-1]
75+
replacer_scripts.enableInpaintModeForCN(gArgs, p, previousFrame)
7376
except Exception as e:
7477
errors.report(f"Error {e}", exc_info=True)
7578

replacer/replacer_scripts.py

+23-9
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,32 @@ def restoreAfterCN(origImage, gArgs: GenerationArgs, processed):
101101
processed.images[i] = imageOrg
102102

103103

104-
def enableInpaintModeForCN(cn_args, p):
104+
def enableInpaintModeForCN(gArgs, p, previousFrame):
105105
if IS_SD_WEBUI_FORGE: return
106106
global external_code
107+
gArgs.cn_args = list(gArgs.cn_args)
107108
mask = None
108109

109-
for controlNetUnit in cn_args:
110-
controlNetUnit = external_code.to_processing_unit(controlNetUnit)
111-
112-
if not controlNetUnit.enabled:
110+
for i in range(len(gArgs.cn_args)):
111+
gArgs.cn_args[i] = external_code.to_processing_unit(gArgs.cn_args[i])
112+
113+
if f"Unit {i}" in gArgs.previous_frame_into_controlnet:
114+
if previousFrame:
115+
print(f'Passing the previous frame CN unit {i}')
116+
gArgs.cn_args[i].image = {
117+
"image": convertIntoCNImageFromat(previousFrame),
118+
# "mask": convertIntoCNImageFromat(p.image_mask),
119+
}
120+
gArgs.cn_args[i].enabled = True
121+
else:
122+
print(f'Disabling CN unit {i} for the first frame')
123+
gArgs.cn_args[i].enabled = False
124+
continue
125+
126+
if not gArgs.cn_args[i].enabled:
113127
continue
114128

115-
if not IS_SD_WEBUI_FORGE and controlNetUnit.module == 'inpaint_only':
129+
if not IS_SD_WEBUI_FORGE and gArgs.cn_args[i].module == 'inpaint_only':
116130
if p.image_mask is not None:
117131
mask = p.image_mask
118132
if p.inpainting_mask_invert:
@@ -121,15 +135,15 @@ def enableInpaintModeForCN(cn_args, p):
121135

122136
print('Use cn inpaint instead of sd inpaint')
123137
image = limitSizeByOneDemention(p.init_images[0], max(p.width, p.height))
124-
controlNetUnit.image = {
138+
gArgs.cn_args[i].image = {
125139
"image": convertIntoCNImageFromat(image),
126140
"mask": convertIntoCNImageFromat(mask.resize(image.size)),
127141
}
128142
p.image_mask = None
129143
p.inpaint_full_res = False
130144
p.width, p.height = image.size
131-
controlNetUnit.inpaint_crop_input_image = False
132-
controlNetUnit.resize_mode = external_code.ResizeMode.RESIZE
145+
gArgs.cn_args[i].inpaint_crop_input_image = False
146+
gArgs.cn_args[i].resize_mode = external_code.ResizeMode.RESIZE
133147
p.needRestoreAfterCN = True
134148

135149

replacer/ui/generate_ui.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ def generate_ui(
7474
clip_skip,
7575
pass_into_hires_fix_automatically,
7676
save_before_hires_fix,
77+
previous_frame_into_controlnet,
7778

7879
hf_upscaler,
7980
hf_steps,
@@ -225,8 +226,9 @@ def readImages(input_dir):
225226
clip_skip=clip_skip,
226227
pass_into_hires_fix_automatically=pass_into_hires_fix_automatically,
227228
save_before_hires_fix=save_before_hires_fix,
228-
hires_fix_args=hires_fix_args,
229+
previous_frame_into_controlnet=previous_frame_into_controlnet if tab_index == 3 else [],
229230

231+
hires_fix_args=hires_fix_args,
230232
cn_args=cn_args,
231233
soft_inpaint_args=soft_inpaint_args,
232234
)

replacer/ui/replacer_tab_ui.py

+25-11
Original file line numberDiff line numberDiff line change
@@ -160,17 +160,30 @@ def init_tab(self, isDedicatedPage: bool):
160160
placeholder="Leave blank to save images to the default path.",
161161
info='(default is the same directory with input video. Rusult is in "output_seed" subdirectory)',
162162
elem_id="replacer_video_output_dir")
163-
gr.Markdown("To increase consistency it's better to inpaint clear "\
164-
"objects on video with good quality and enough context. "\
165-
"Your prompts need to produce consistent results\n\n"\
166-
"To suppress flickering you can generate in little fps (e.g. 10), "\
167-
"then interpolate (x2) it with ai interpolation algorithm "\
168-
"(e.g [RIFE](https://github.com/megvii-research/ECCV2022-RIFE) or "\
169-
"[frame interpolation in deforum sd-webui extension]("\
170-
"https://github.com/deforum-art/sd-webui-deforum/wiki/Upscaling-and-Frame-Interpolation))\n\n"\
171-
"You can also use [sd-webui-controlnet](https://github.com/Mikubill/sd-webui-controlnet) or "\
172-
"[lama-cleaner](https://github.com/light-and-ray/sd-webui-lama-cleaner-masked-content) with (low denosing) "\
173-
"extensions to increase consistency, if it fits to your scenario")
163+
with gr.Accordion("Help", open=False):
164+
gr.Markdown(
165+
"To increase consistency it's better to inpaint clear "\
166+
"objects on video with good quality and enough context. "\
167+
"Your prompts need to produce consistent results\n\n"\
168+
\
169+
"To suppress flickering you can generate in little fps (e.g. 10), "\
170+
"then interpolate (x2) it with ai interpolation algorithm "\
171+
"(e.g [RIFE](https://github.com/megvii-research/ECCV2022-RIFE) or "\
172+
"[frame interpolation in deforum sd-webui extension]("\
173+
"https://github.com/deforum-art/sd-webui-deforum/wiki/Upscaling-and-Frame-Interpolation))\n\n"\
174+
\
175+
"You can also use [sd-webui-controlnet](https://github.com/Mikubill/sd-webui-controlnet) or "\
176+
"[lama-cleaner](https://github.com/light-and-ray/sd-webui-lama-cleaner-masked-content) with (low denosing) "\
177+
"extensions to increase consistency, if it fits to your scenario\n\n"\
178+
\
179+
"Also a good can be to use `Pass previous frame into ControlNet` "\
180+
"with _IP-Adapter_, _Reference_, _Revision_, _T2IA Color_, _T2IA Style_"
181+
)
182+
if replacer_scripts.script_controlnet:
183+
comp.previous_frame_into_controlnet = gr.CheckboxGroup(value=[], label='Pass previous frame into ControlNet',
184+
choices=[f"Unit {x}" for x in range(shared.opts.control_net_unit_count)], elem_id='replacer_previous_frame_into_controlnet')
185+
else:
186+
comp.previous_frame_into_controlnet = gr.CheckboxGroup(value=[], visible=False)
174187

175188
comp.cn_inputs = []
176189
setCustomScriptSourceForComponents("controlnet")
@@ -337,6 +350,7 @@ def init_tab(self, isDedicatedPage: bool):
337350
comp.clip_skip,
338351
comp.pass_into_hires_fix_automatically,
339352
comp.save_before_hires_fix,
353+
comp.previous_frame_into_controlnet,
340354

341355
comp.hf_upscaler,
342356
comp.hf_steps,

scripts/replacer_api.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,9 @@ async def api_replacer_replace(data: ReplaceRequest = Body(...)) -> Any:
146146
clip_skip=data.clip_skip,
147147
pass_into_hires_fix_automatically=data.use_hires_fix,
148148
save_before_hires_fix=False,
149-
hires_fix_args=hires_fix_args,
149+
previous_frame_into_controlnet=[],
150150

151+
hires_fix_args=hires_fix_args,
151152
cn_args=cn_args,
152153
soft_inpaint_args=soft_inpaint_args,
153154
)

scripts/replacer_script.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import copy
12
import gradio as gr
23
from modules import scripts, scripts_postprocessing, errors, ui_settings
34
from modules.processing import Processed, StableDiffusionProcessingTxt2Img
@@ -123,6 +124,10 @@ def ui(self, is_img2img):
123124
] + comp.cn_inputs \
124125
+ comp.soft_inpaint_inputs
125126

127+
for i in range(len(inputs)):
128+
inputs[i] = copy.copy(inputs[i])
129+
inputs[i].do_not_save_to_config = True
130+
126131
return inputs
127132

128133
def before_process(self, p: StableDiffusionProcessingTxt2Img,
@@ -273,8 +278,9 @@ def before_process(self, p: StableDiffusionProcessingTxt2Img,
273278
clip_skip=clip_skip,
274279
pass_into_hires_fix_automatically=pass_into_hires_fix_automatically,
275280
save_before_hires_fix=save_before_hires_fix,
276-
hires_fix_args=hires_fix_args,
281+
previous_frame_into_controlnet=[],
277282

283+
hires_fix_args=hires_fix_args,
278284
cn_args=cn_args,
279285
soft_inpaint_args=soft_inpaint_args,
280286
)

0 commit comments

Comments
 (0)