Skip to content

Commit

Permalink
Merge pull request #869 from rewbs/rewbs/a1111-1.6-cn-hack
Browse files Browse the repository at this point in the history
Workaround for 'unhashable type: 'slice' /  'No ControlNetUnit detected in args' since 1.6 upgrade, and for drop_path issue related to timm upgrade.
  • Loading branch information
rewbs committed Sep 4, 2023
2 parents bb54132 + 8d3df10 commit 86921f7
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
uses: actions/checkout@v3
with:
repository: AUTOMATIC1111/stable-diffusion-webui
ref: v1.5.1
ref: v1.6.0
- name: Checkout Controlnet extension
uses: actions/checkout@v3
with:
Expand Down
30 changes: 28 additions & 2 deletions scripts/deforum_helpers/deforum_controlnet.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
# https://github.com/Mikubill/sd-webui-controlnet — controlnet repo

import os
import copy
import gradio as gr
import scripts
from PIL import Image
Expand Down Expand Up @@ -264,7 +265,27 @@ def read_cn_data(cn_idx):
if not any(os.path.exists(cn_inputframes) for cn_inputframes in cn_inputframes_list) and not any_loopback_mode:
print(f'\033[33mNeither the base nor the masking frames for ControlNet were found. Using the regular pipeline\033[0m')

p.scripts = scripts.scripts_img2img if is_img2img else scripts.scripts_txt2img
# Remove all scripts except controlnet.
#
# This is required because controlnet's access to p.script_args invokes @script_args.setter,
# which triggers *all* alwayson_scripts' setup() functions, with whatever happens to be in script_args.
# In the case of seed.py (which we really don't need with deforum), this ovewrites our p.seed & co, which we
# had carefully prepared previously. So let's remove the scripts to avoid the problem.
#
# An alternative would be to populate all the args with the correct values
# for all scripts, but this seems even more fragile, as it would break
# if a1111 adds or removed scripts.
#
# Note that we must copy scripts.scripts_img2img or scripts.scripts_txt2img before mutating it
# because it persists across requests. Shallow-copying is sufficient because we only mutate a top-level
# reference (scripts.alwayson_scripts)
#
p.scripts = copy.copy(scripts.scripts_img2img if is_img2img else scripts.scripts_txt2img)
controlnet_script = find_controlnet_script(p)
p.scripts.alwayson_scripts = [controlnet_script]
# Filling the list with None is safe because only the length will be considered,
# and all cn args will be replaced.
p.script_args_value = [None] * controlnet_script.args_to

def create_cnu_dict(cn_args, prefix, img_np, mask_np, frame_idx, CnSchKeys):

Expand Down Expand Up @@ -292,9 +313,14 @@ def create_cnu_dict(cn_args, prefix, img_np, mask_np, frame_idx, CnSchKeys):
cn_units = [cnet.ControlNetUnit(**create_cnu_dict(controlnet_args, f"cn_{i + 1}", img_np, mask_np, frame_idx, CnSchKeys))
for i, (img_np, mask_np) in enumerate(zip(images_np, masks_np))]

p.script_args = {"enabled": True}
cnet.update_cn_script_in_processing(p, cn_units, is_img2img=is_img2img, is_ui=False)

def find_controlnet_script(p):
controlnet_script = next((script for script in p.scripts.alwayson_scripts if script.title().lower() == "controlnet"), None)
if not controlnet_script:
raise Exception("ControlNet script not found.")
return controlnet_script

def process_controlnet_input_frames(args, anim_args, controlnet_args, video_path, mask_path, outdir_suffix, id):
if (video_path or mask_path) and getattr(controlnet_args, f'cn_{id}_enabled'):
frame_path = os.path.join(args.outdir, f'controlnet_{id}_{outdir_suffix}')
Expand Down
17 changes: 12 additions & 5 deletions scripts/deforum_helpers/src/midas/backbones/beit.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,23 @@ def block_forward(self, x, resolution, shared_rel_pos_bias: Optional[torch.Tenso
"""
Modification of timm.models.beit.py: Block.forward to support arbitrary window sizes.
"""

if hasattr(self, 'drop_path1'):
drop_path_compat = self.drop_path1
elif hasattr(self.target, 'drop_path'):
drop_path_compat = self.drop_path
else:
raise AttributeError("Neither drop_path1 nor drop_path exists on the target.")

if self.gamma_1 is None:
x = x + self.drop_path(self.attn(self.norm1(x), resolution, shared_rel_pos_bias=shared_rel_pos_bias))
x = x + self.drop_path(self.mlp(self.norm2(x)))
x = x + drop_path_compat(self.attn(self.norm1(x), resolution, shared_rel_pos_bias=shared_rel_pos_bias))
x = x + drop_path_compat(self.mlp(self.norm2(x)))
else:
x = x + self.drop_path(self.gamma_1 * self.attn(self.norm1(x), resolution,
x = x + drop_path_compat(self.gamma_1 * self.attn(self.norm1(x), resolution,
shared_rel_pos_bias=shared_rel_pos_bias))
x = x + self.drop_path(self.gamma_2 * self.mlp(self.norm2(x)))
x = x + drop_path_compat(self.gamma_2 * self.mlp(self.norm2(x)))
return x


def beit_forward_features(self, x):
"""
Modification of timm.models.beit.py: Beit.forward_features to support arbitrary window sizes.
Expand Down

0 comments on commit 86921f7

Please sign in to comment.