Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
869ac6fd1f | ||
|
|
cb168d64ab | ||
|
|
a89e9e01a6 | ||
|
|
e70b4df9b5 | ||
|
|
af1ef7e441 | ||
|
|
d8738eee2f | ||
|
|
c397c68ca3 | ||
|
|
0e0722ec08 | ||
|
|
70d0540895 |
@@ -1,35 +0,0 @@
|
|||||||
import { ComfyApp, app } from "../../scripts/app.js";
|
|
||||||
|
|
||||||
let conflict_check = undefined;
|
|
||||||
|
|
||||||
app.registerExtension({
|
|
||||||
name: "Comfy.impact.comboBoolMigration",
|
|
||||||
|
|
||||||
nodeCreated(node, app) {
|
|
||||||
for(let i in node.widgets) {
|
|
||||||
let widget = node.widgets[i];
|
|
||||||
|
|
||||||
if(conflict_check == undefined) {
|
|
||||||
conflict_check = !!app.extensions.find((ext) => ext.name === "Comfy.comboBoolMigration");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(conflict_check)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(widget.type == "toggle") {
|
|
||||||
let value = widget.value;
|
|
||||||
|
|
||||||
var v = Object.getOwnPropertyDescriptor(widget, 'value');
|
|
||||||
if(!v) {
|
|
||||||
Object.defineProperty(widget, "value", {
|
|
||||||
set: (value) => {
|
|
||||||
delete widget.value;
|
|
||||||
widget.value = value == true || value == widget.options.on;
|
|
||||||
},
|
|
||||||
get: () => { return value; }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
+16
-6
@@ -93,7 +93,7 @@ const input_dirty = {};
|
|||||||
const output_tracking = {};
|
const output_tracking = {};
|
||||||
|
|
||||||
function progressExecuteHandler(event) {
|
function progressExecuteHandler(event) {
|
||||||
if(event.detail.output.aux){
|
if(event.detail?.output?.aux){
|
||||||
const id = event.detail.node;
|
const id = event.detail.node;
|
||||||
if(input_tracking.hasOwnProperty(id)) {
|
if(input_tracking.hasOwnProperty(id)) {
|
||||||
if(input_tracking.hasOwnProperty(id) && input_tracking[id][0] != event.detail.output.aux[0]) {
|
if(input_tracking.hasOwnProperty(id) && input_tracking[id][0] != event.detail.output.aux[0]) {
|
||||||
@@ -273,7 +273,7 @@ app.registerExtension({
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const node = app.graph.getNodeById(link_info.origin_id);
|
const node = app.graph.getNodeById(link_info.origin_id);
|
||||||
slot_type = node.outputs[link_info.origin_slot].type;
|
slot_type = node.outputs[link_info.origin_slot]?.type;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.inputs[0].type = slot_type;
|
this.inputs[0].type = slot_type;
|
||||||
@@ -365,7 +365,11 @@ app.registerExtension({
|
|||||||
// connect input
|
// connect input
|
||||||
if(this.inputs[0].type == '*'){
|
if(this.inputs[0].type == '*'){
|
||||||
const node = app.graph.getNodeById(link_info.origin_id);
|
const node = app.graph.getNodeById(link_info.origin_id);
|
||||||
let origin_type = node.outputs[link_info.origin_slot].type;
|
let origin_type = node.outputs[link_info.origin_slot]?.type;
|
||||||
|
|
||||||
|
if(origin_type==undefined) {
|
||||||
|
return; // fallback
|
||||||
|
}
|
||||||
|
|
||||||
if(origin_type == '*') {
|
if(origin_type == '*') {
|
||||||
this.disconnectInput(link_info.target_slot);
|
this.disconnectInput(link_info.target_slot);
|
||||||
@@ -755,14 +759,20 @@ app.registerExtension({
|
|||||||
// mode combo
|
// mode combo
|
||||||
Object.defineProperty(mode_widget, "value", {
|
Object.defineProperty(mode_widget, "value", {
|
||||||
set: (value) => {
|
set: (value) => {
|
||||||
node._mode_value = value == true || value == "Populate";
|
if(value == true)
|
||||||
populated_text_widget.inputEl.disabled = value == true || value == "Populate";
|
node._mode_value = "populate";
|
||||||
|
else if(value == false)
|
||||||
|
node._mode_value = "fixed";
|
||||||
|
else
|
||||||
|
node._mode_value = value; // combo value
|
||||||
|
|
||||||
|
populated_text_widget.inputEl.disabled = node._mode_value != 'populate';
|
||||||
},
|
},
|
||||||
get: () => {
|
get: () => {
|
||||||
if(node._mode_value != undefined)
|
if(node._mode_value != undefined)
|
||||||
return node._mode_value;
|
return node._mode_value;
|
||||||
else
|
else
|
||||||
return true;
|
return 'populate';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class SEGSDetailerForAnimateDiff:
|
|||||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
|
||||||
"scheduler": (core.SCHEDULERS,),
|
"scheduler": (core.SCHEDULERS,),
|
||||||
"denoise": ("FLOAT", {"default": 0.5, "min": 0.0001, "max": 1.0, "step": 0.01}),
|
"denoise": ("FLOAT", {"default": 0.5, "min": 0.0001, "max": 1.0, "step": 0.01}),
|
||||||
"basic_pipe": ("BASIC_PIPE",),
|
"basic_pipe": ("BASIC_PIPE", {"tooltip": "If the `ImpactDummyInput` is connected to the model in the basic_pipe, the inference stage is skipped."}),
|
||||||
"refiner_ratio": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0}),
|
"refiner_ratio": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0}),
|
||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
@@ -60,7 +60,7 @@ class SEGSDetailerForAnimateDiff:
|
|||||||
new_segs = []
|
new_segs = []
|
||||||
cnet_image_list = []
|
cnet_image_list = []
|
||||||
|
|
||||||
if noise_mask_feather > 0 and 'denoise_mask_function' not in model.model_options:
|
if not (isinstance(model, str) and model == "DUMMY") and noise_mask_feather > 0 and 'denoise_mask_function' not in model.model_options:
|
||||||
model = nodes_differential_diffusion.DifferentialDiffusion().apply(model)[0]
|
model = nodes_differential_diffusion.DifferentialDiffusion().apply(model)[0]
|
||||||
|
|
||||||
for seg in segs[1]:
|
for seg in segs[1]:
|
||||||
@@ -94,13 +94,18 @@ class SEGSDetailerForAnimateDiff:
|
|||||||
for condition, details in negative
|
for condition, details in negative
|
||||||
]
|
]
|
||||||
|
|
||||||
enhanced_image_tensor, cnet_images = core.enhance_detail_for_animatediff(cropped_image_frames, model, clip, vae, guide_size, guide_size_for, max_size,
|
if not (isinstance(model, str) and model == "DUMMY"):
|
||||||
seg.bbox, seed, steps, cfg, sampler_name, scheduler,
|
enhanced_image_tensor, cnet_images = core.enhance_detail_for_animatediff(cropped_image_frames, model, clip, vae, guide_size, guide_size_for, max_size,
|
||||||
cropped_positive, cropped_negative, denoise, seg.cropped_mask,
|
seg.bbox, seed, steps, cfg, sampler_name, scheduler,
|
||||||
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
cropped_positive, cropped_negative, denoise, seg.cropped_mask,
|
||||||
refiner_clip=refiner_clip, refiner_positive=refiner_positive,
|
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
||||||
refiner_negative=refiner_negative, control_net_wrapper=seg.control_net_wrapper,
|
refiner_clip=refiner_clip, refiner_positive=refiner_positive,
|
||||||
noise_mask_feather=noise_mask_feather, scheduler_func=scheduler_func_opt)
|
refiner_negative=refiner_negative, control_net_wrapper=seg.control_net_wrapper,
|
||||||
|
noise_mask_feather=noise_mask_feather, scheduler_func=scheduler_func_opt)
|
||||||
|
else:
|
||||||
|
enhanced_image_tensor = cropped_image_frames
|
||||||
|
cnet_images = None
|
||||||
|
|
||||||
if cnet_images is not None:
|
if cnet_images is not None:
|
||||||
cnet_image_list.extend(cnet_images)
|
cnet_image_list.extend(cnet_images)
|
||||||
|
|
||||||
@@ -143,7 +148,7 @@ class DetailerForEachPipeForAnimateDiff:
|
|||||||
"scheduler": (core.SCHEDULERS,),
|
"scheduler": (core.SCHEDULERS,),
|
||||||
"denoise": ("FLOAT", {"default": 0.5, "min": 0.0001, "max": 1.0, "step": 0.01}),
|
"denoise": ("FLOAT", {"default": 0.5, "min": 0.0001, "max": 1.0, "step": 0.01}),
|
||||||
"feather": ("INT", {"default": 5, "min": 0, "max": 100, "step": 1}),
|
"feather": ("INT", {"default": 5, "min": 0, "max": 100, "step": 1}),
|
||||||
"basic_pipe": ("BASIC_PIPE", ),
|
"basic_pipe": ("BASIC_PIPE", {"tooltip": "If the `ImpactDummyInput` is connected to the model in the basic_pipe, the inference stage is skipped."}),
|
||||||
"refiner_ratio": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0}),
|
"refiner_ratio": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0}),
|
||||||
},
|
},
|
||||||
"optional": {
|
"optional": {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import configparser
|
import configparser
|
||||||
import os
|
import os
|
||||||
|
|
||||||
version_code = [8, 3]
|
version_code = [8, 6]
|
||||||
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||||
|
|
||||||
dependency_version = 24
|
dependency_version = 24
|
||||||
|
|||||||
+15
-8
@@ -244,7 +244,8 @@ def enhance_detail(image, model, clip, vae, guide_size, guide_size_for_bbox, max
|
|||||||
detailer_hook=None,
|
detailer_hook=None,
|
||||||
refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None,
|
refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None,
|
||||||
refiner_negative=None, control_net_wrapper=None, cycle=1,
|
refiner_negative=None, control_net_wrapper=None, cycle=1,
|
||||||
inpaint_model=False, noise_mask_feather=0, scheduler_func=None):
|
inpaint_model=False, noise_mask_feather=0, scheduler_func=None,
|
||||||
|
vae_tiled_encode=False, vae_tiled_decode=False):
|
||||||
|
|
||||||
if noise_mask is not None:
|
if noise_mask is not None:
|
||||||
noise_mask = utils.tensor_gaussian_blur_mask(noise_mask, noise_mask_feather)
|
noise_mask = utils.tensor_gaussian_blur_mask(noise_mask, noise_mask_feather)
|
||||||
@@ -334,7 +335,7 @@ def enhance_detail(image, model, clip, vae, guide_size, guide_size_for_bbox, max
|
|||||||
print(f"[Impact Pack] ComfyUI is an outdated version.")
|
print(f"[Impact Pack] ComfyUI is an outdated version.")
|
||||||
positive, negative, latent_image = imc_encode(positive, negative, upscaled_image, vae, noise_mask)
|
positive, negative, latent_image = imc_encode(positive, negative, upscaled_image, vae, noise_mask)
|
||||||
else:
|
else:
|
||||||
latent_image = to_latent_image(upscaled_image, vae)
|
latent_image = to_latent_image(upscaled_image, vae, vae_tiled_encode=vae_tiled_encode)
|
||||||
if noise_mask is not None:
|
if noise_mask is not None:
|
||||||
latent_image['noise_mask'] = noise_mask
|
latent_image['noise_mask'] = noise_mask
|
||||||
|
|
||||||
@@ -369,12 +370,18 @@ def enhance_detail(image, model, clip, vae, guide_size, guide_size_for_bbox, max
|
|||||||
refined_latent = detailer_hook.pre_decode(refined_latent)
|
refined_latent = detailer_hook.pre_decode(refined_latent)
|
||||||
|
|
||||||
# non-latent downscale - latent downscale cause bad quality
|
# non-latent downscale - latent downscale cause bad quality
|
||||||
try:
|
start = time.time()
|
||||||
# try to decode image normally
|
if vae_tiled_decode:
|
||||||
refined_image = vae.decode(refined_latent['samples'])
|
(refined_image,) = nodes.VAEDecodeTiled().decode(vae, refined_latent, 512) # using default settings
|
||||||
except Exception as e:
|
print(f"[Impact Pack] vae decoded (tiled) in {time.time() - start:.1f}s")
|
||||||
#usually an out-of-memory exception from the decode, so try a tiled approach
|
else:
|
||||||
refined_image = vae.decode_tiled(refined_latent["samples"], tile_x=64, tile_y=64, )
|
try:
|
||||||
|
refined_image = vae.decode(refined_latent['samples'])
|
||||||
|
except Exception as e:
|
||||||
|
# usually an out-of-memory exception from the decode, so try a tiled approach
|
||||||
|
print(f"[Impact Pack] failed after {time.time() - start:.1f}s, doing vae.decode_tiled 64...")
|
||||||
|
refined_image = vae.decode_tiled(refined_latent["samples"], tile_x=64, tile_y=64, )
|
||||||
|
print(f"[Impact Pack] vae decoded in {time.time() - start:.1f}s")
|
||||||
|
|
||||||
if detailer_hook is not None:
|
if detailer_hook is not None:
|
||||||
refined_image = detailer_hook.post_decode(refined_image)
|
refined_image = detailer_hook.post_decode(refined_image)
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ class DetailerForEach:
|
|||||||
return {"required": {
|
return {"required": {
|
||||||
"image": ("IMAGE", ),
|
"image": ("IMAGE", ),
|
||||||
"segs": ("SEGS", ),
|
"segs": ("SEGS", ),
|
||||||
"model": ("MODEL",),
|
"model": ("MODEL", {"tooltip": "If the `ImpactDummyInput` is connected to the model, the inference stage is skipped."}),
|
||||||
"clip": ("CLIP",),
|
"clip": ("CLIP",),
|
||||||
"vae": ("VAE",),
|
"vae": ("VAE",),
|
||||||
"guide_size": ("FLOAT", {"default": 512, "min": 64, "max": nodes.MAX_RESOLUTION, "step": 8}),
|
"guide_size": ("FLOAT", {"default": 512, "min": 64, "max": nodes.MAX_RESOLUTION, "step": 8}),
|
||||||
@@ -218,6 +218,8 @@ class DetailerForEach:
|
|||||||
"inpaint_model": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
"inpaint_model": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
"noise_mask_feather": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}),
|
"noise_mask_feather": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}),
|
||||||
"scheduler_func_opt": ("SCHEDULER_FUNC",),
|
"scheduler_func_opt": ("SCHEDULER_FUNC",),
|
||||||
|
"tiled_encode": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
|
"tiled_decode": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,7 +236,7 @@ class DetailerForEach:
|
|||||||
def do_detail(image, segs, model, clip, vae, guide_size, guide_size_for_bbox, max_size, seed, steps, cfg, sampler_name, scheduler,
|
def do_detail(image, segs, model, clip, vae, guide_size, guide_size_for_bbox, max_size, seed, steps, cfg, sampler_name, scheduler,
|
||||||
positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard_opt=None, detailer_hook=None,
|
positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard_opt=None, detailer_hook=None,
|
||||||
refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None,
|
refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None,
|
||||||
cycle=1, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None):
|
cycle=1, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None, tiled_encode=False, tiled_decode=False):
|
||||||
|
|
||||||
if len(image) > 1:
|
if len(image) > 1:
|
||||||
raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.')
|
raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.')
|
||||||
@@ -338,7 +340,8 @@ class DetailerForEach:
|
|||||||
refiner_clip=refiner_clip, refiner_positive=refiner_positive,
|
refiner_clip=refiner_clip, refiner_positive=refiner_positive,
|
||||||
refiner_negative=refiner_negative, control_net_wrapper=seg.control_net_wrapper,
|
refiner_negative=refiner_negative, control_net_wrapper=seg.control_net_wrapper,
|
||||||
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather,
|
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather,
|
||||||
scheduler_func=scheduler_func_opt)
|
scheduler_func=scheduler_func_opt, vae_tiled_encode=tiled_encode,
|
||||||
|
vae_tiled_decode=tiled_decode)
|
||||||
else:
|
else:
|
||||||
enhanced_image = cropped_image
|
enhanced_image = cropped_image
|
||||||
cnet_pils = None
|
cnet_pils = None
|
||||||
@@ -384,13 +387,15 @@ class DetailerForEach:
|
|||||||
|
|
||||||
def doit(self, image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name,
|
def doit(self, image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name,
|
||||||
scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, cycle=1,
|
scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, cycle=1,
|
||||||
detailer_hook=None, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None):
|
detailer_hook=None, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None,
|
||||||
|
tiled_encode=False, tiled_decode=False):
|
||||||
|
|
||||||
enhanced_img, *_ = \
|
enhanced_img, *_ = \
|
||||||
DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps,
|
DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps,
|
||||||
cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask,
|
cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask,
|
||||||
force_inpaint, wildcard, detailer_hook,
|
force_inpaint, wildcard, detailer_hook,
|
||||||
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt)
|
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather,
|
||||||
|
scheduler_func_opt=scheduler_func_opt, tiled_encode=tiled_encode, tiled_decode=tiled_decode)
|
||||||
|
|
||||||
return (enhanced_img, )
|
return (enhanced_img, )
|
||||||
|
|
||||||
@@ -413,7 +418,7 @@ class DetailerForEachPipe:
|
|||||||
"feather": ("INT", {"default": 5, "min": 0, "max": 100, "step": 1}),
|
"feather": ("INT", {"default": 5, "min": 0, "max": 100, "step": 1}),
|
||||||
"noise_mask": ("BOOLEAN", {"default": True, "label_on": "enabled", "label_off": "disabled"}),
|
"noise_mask": ("BOOLEAN", {"default": True, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
"force_inpaint": ("BOOLEAN", {"default": True, "label_on": "enabled", "label_off": "disabled"}),
|
"force_inpaint": ("BOOLEAN", {"default": True, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
"basic_pipe": ("BASIC_PIPE", ),
|
"basic_pipe": ("BASIC_PIPE", {"tooltip": "If the `ImpactDummyInput` is connected to the model in the basic_pipe, the inference stage is skipped."}),
|
||||||
"wildcard": ("STRING", {"multiline": True, "dynamicPrompts": False}),
|
"wildcard": ("STRING", {"multiline": True, "dynamicPrompts": False}),
|
||||||
"refiner_ratio": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0}),
|
"refiner_ratio": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0}),
|
||||||
|
|
||||||
@@ -425,6 +430,8 @@ class DetailerForEachPipe:
|
|||||||
"inpaint_model": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
"inpaint_model": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
"noise_mask_feather": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}),
|
"noise_mask_feather": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}),
|
||||||
"scheduler_func_opt": ("SCHEDULER_FUNC",),
|
"scheduler_func_opt": ("SCHEDULER_FUNC",),
|
||||||
|
"tiled_encode": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
|
"tiled_decode": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -438,7 +445,8 @@ class DetailerForEachPipe:
|
|||||||
def doit(self, image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler,
|
def doit(self, image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler,
|
||||||
denoise, feather, noise_mask, force_inpaint, basic_pipe, wildcard,
|
denoise, feather, noise_mask, force_inpaint, basic_pipe, wildcard,
|
||||||
refiner_ratio=None, detailer_hook=None, refiner_basic_pipe_opt=None,
|
refiner_ratio=None, detailer_hook=None, refiner_basic_pipe_opt=None,
|
||||||
cycle=1, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None):
|
cycle=1, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None,
|
||||||
|
tiled_encode=False, tiled_decode=False):
|
||||||
|
|
||||||
if len(image) > 1:
|
if len(image) > 1:
|
||||||
raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.')
|
raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.')
|
||||||
@@ -456,7 +464,8 @@ class DetailerForEachPipe:
|
|||||||
force_inpaint, wildcard, detailer_hook,
|
force_inpaint, wildcard, detailer_hook,
|
||||||
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
||||||
refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative,
|
refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative,
|
||||||
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt)
|
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt,
|
||||||
|
tiled_encode=tiled_encode, tiled_decode=tiled_decode)
|
||||||
|
|
||||||
# set fallback image
|
# set fallback image
|
||||||
if len(cnet_pil_list) == 0:
|
if len(cnet_pil_list) == 0:
|
||||||
@@ -470,7 +479,7 @@ class FaceDetailer:
|
|||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {"required": {
|
return {"required": {
|
||||||
"image": ("IMAGE", ),
|
"image": ("IMAGE", ),
|
||||||
"model": ("MODEL",),
|
"model": ("MODEL", {"tooltip": "If the `ImpactDummyInput` is connected to the model, the inference stage is skipped."}),
|
||||||
"clip": ("CLIP",),
|
"clip": ("CLIP",),
|
||||||
"vae": ("VAE",),
|
"vae": ("VAE",),
|
||||||
"guide_size": ("FLOAT", {"default": 512, "min": 64, "max": nodes.MAX_RESOLUTION, "step": 8}),
|
"guide_size": ("FLOAT", {"default": 512, "min": 64, "max": nodes.MAX_RESOLUTION, "step": 8}),
|
||||||
@@ -513,6 +522,8 @@ class FaceDetailer:
|
|||||||
"inpaint_model": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
"inpaint_model": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
"noise_mask_feather": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}),
|
"noise_mask_feather": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}),
|
||||||
"scheduler_func_opt": ("SCHEDULER_FUNC",),
|
"scheduler_func_opt": ("SCHEDULER_FUNC",),
|
||||||
|
"tiled_encode": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
|
"tiled_decode": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
RETURN_TYPES = ("IMAGE", "IMAGE", "IMAGE", "MASK", "DETAILER_PIPE", "IMAGE")
|
RETURN_TYPES = ("IMAGE", "IMAGE", "IMAGE", "MASK", "DETAILER_PIPE", "IMAGE")
|
||||||
@@ -530,7 +541,7 @@ class FaceDetailer:
|
|||||||
sam_mask_hint_use_negative, drop_size,
|
sam_mask_hint_use_negative, drop_size,
|
||||||
bbox_detector, segm_detector=None, sam_model_opt=None, wildcard_opt=None, detailer_hook=None,
|
bbox_detector, segm_detector=None, sam_model_opt=None, wildcard_opt=None, detailer_hook=None,
|
||||||
refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None, cycle=1,
|
refiner_ratio=None, refiner_model=None, refiner_clip=None, refiner_positive=None, refiner_negative=None, cycle=1,
|
||||||
inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None):
|
inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None, tiled_encode=False, tiled_decode=False):
|
||||||
|
|
||||||
# make default prompt as 'face' if empty prompt for CLIPSeg
|
# make default prompt as 'face' if empty prompt for CLIPSeg
|
||||||
bbox_detector.setAux('face')
|
bbox_detector.setAux('face')
|
||||||
@@ -562,7 +573,8 @@ class FaceDetailer:
|
|||||||
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
||||||
refiner_clip=refiner_clip, refiner_positive=refiner_positive,
|
refiner_clip=refiner_clip, refiner_positive=refiner_positive,
|
||||||
refiner_negative=refiner_negative,
|
refiner_negative=refiner_negative,
|
||||||
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt)
|
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather,
|
||||||
|
scheduler_func_opt=scheduler_func_opt, tiled_encode=tiled_encode, tiled_decode=tiled_decode)
|
||||||
else:
|
else:
|
||||||
enhanced_img = image
|
enhanced_img = image
|
||||||
cropped_enhanced = []
|
cropped_enhanced = []
|
||||||
@@ -588,7 +600,8 @@ class FaceDetailer:
|
|||||||
bbox_threshold, bbox_dilation, bbox_crop_factor,
|
bbox_threshold, bbox_dilation, bbox_crop_factor,
|
||||||
sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold,
|
sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold,
|
||||||
sam_mask_hint_use_negative, drop_size, bbox_detector, wildcard, cycle=1,
|
sam_mask_hint_use_negative, drop_size, bbox_detector, wildcard, cycle=1,
|
||||||
sam_model_opt=None, segm_detector_opt=None, detailer_hook=None, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None):
|
sam_model_opt=None, segm_detector_opt=None, detailer_hook=None, inpaint_model=False, noise_mask_feather=0,
|
||||||
|
scheduler_func_opt=None, tiled_encode=False, tiled_decode=False):
|
||||||
|
|
||||||
result_img = None
|
result_img = None
|
||||||
result_mask = None
|
result_mask = None
|
||||||
@@ -606,7 +619,8 @@ class FaceDetailer:
|
|||||||
bbox_threshold, bbox_dilation, bbox_crop_factor,
|
bbox_threshold, bbox_dilation, bbox_crop_factor,
|
||||||
sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold,
|
sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion, sam_mask_hint_threshold,
|
||||||
sam_mask_hint_use_negative, drop_size, bbox_detector, segm_detector_opt, sam_model_opt, wildcard, detailer_hook,
|
sam_mask_hint_use_negative, drop_size, bbox_detector, segm_detector_opt, sam_model_opt, wildcard, detailer_hook,
|
||||||
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt)
|
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt,
|
||||||
|
tiled_encode=tiled_encode, tiled_decode=tiled_decode)
|
||||||
|
|
||||||
result_img = torch.cat((result_img, enhanced_img), dim=0) if result_img is not None else enhanced_img
|
result_img = torch.cat((result_img, enhanced_img), dim=0) if result_img is not None else enhanced_img
|
||||||
result_mask = torch.cat((result_mask, mask), dim=0) if result_mask is not None else mask
|
result_mask = torch.cat((result_mask, mask), dim=0) if result_mask is not None else mask
|
||||||
@@ -1347,7 +1361,7 @@ class FaceDetailerPipe:
|
|||||||
def INPUT_TYPES(s):
|
def INPUT_TYPES(s):
|
||||||
return {"required": {
|
return {"required": {
|
||||||
"image": ("IMAGE", ),
|
"image": ("IMAGE", ),
|
||||||
"detailer_pipe": ("DETAILER_PIPE",),
|
"detailer_pipe": ("DETAILER_PIPE", {"tooltip": "If the `ImpactDummyInput` is connected to the model in the detailer_pipe, the inference stage is skipped."}),
|
||||||
"guide_size": ("FLOAT", {"default": 512, "min": 64, "max": nodes.MAX_RESOLUTION, "step": 8}),
|
"guide_size": ("FLOAT", {"default": 512, "min": 64, "max": nodes.MAX_RESOLUTION, "step": 8}),
|
||||||
"guide_size_for": ("BOOLEAN", {"default": True, "label_on": "bbox", "label_off": "crop_region"}),
|
"guide_size_for": ("BOOLEAN", {"default": True, "label_on": "bbox", "label_off": "crop_region"}),
|
||||||
"max_size": ("FLOAT", {"default": 1024, "min": 64, "max": nodes.MAX_RESOLUTION, "step": 8}),
|
"max_size": ("FLOAT", {"default": 1024, "min": 64, "max": nodes.MAX_RESOLUTION, "step": 8}),
|
||||||
@@ -1381,6 +1395,8 @@ class FaceDetailerPipe:
|
|||||||
"inpaint_model": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
"inpaint_model": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
"noise_mask_feather": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}),
|
"noise_mask_feather": ("INT", {"default": 20, "min": 0, "max": 100, "step": 1}),
|
||||||
"scheduler_func_opt": ("SCHEDULER_FUNC",),
|
"scheduler_func_opt": ("SCHEDULER_FUNC",),
|
||||||
|
"tiled_encode": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
|
"tiled_decode": ("BOOLEAN", {"default": False, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1395,7 +1411,8 @@ class FaceDetailerPipe:
|
|||||||
denoise, feather, noise_mask, force_inpaint, bbox_threshold, bbox_dilation, bbox_crop_factor,
|
denoise, feather, noise_mask, force_inpaint, bbox_threshold, bbox_dilation, bbox_crop_factor,
|
||||||
sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion,
|
sam_detection_hint, sam_dilation, sam_threshold, sam_bbox_expansion,
|
||||||
sam_mask_hint_threshold, sam_mask_hint_use_negative, drop_size, refiner_ratio=None,
|
sam_mask_hint_threshold, sam_mask_hint_use_negative, drop_size, refiner_ratio=None,
|
||||||
cycle=1, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None):
|
cycle=1, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None,
|
||||||
|
tiled_encode=False, tiled_decode=False):
|
||||||
|
|
||||||
result_img = None
|
result_img = None
|
||||||
result_mask = None
|
result_mask = None
|
||||||
@@ -1418,7 +1435,8 @@ class FaceDetailerPipe:
|
|||||||
sam_mask_hint_use_negative, drop_size, bbox_detector, segm_detector, sam_model_opt, wildcard, detailer_hook,
|
sam_mask_hint_use_negative, drop_size, bbox_detector, segm_detector, sam_model_opt, wildcard, detailer_hook,
|
||||||
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
||||||
refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative,
|
refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative,
|
||||||
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt)
|
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt,
|
||||||
|
tiled_encode=tiled_encode, tiled_decode=tiled_decode)
|
||||||
|
|
||||||
result_img = torch.cat((result_img, enhanced_img), dim=0) if result_img is not None else enhanced_img
|
result_img = torch.cat((result_img, enhanced_img), dim=0) if result_img is not None else enhanced_img
|
||||||
result_mask = torch.cat((result_mask, mask), dim=0) if result_mask is not None else mask
|
result_mask = torch.cat((result_mask, mask), dim=0) if result_mask is not None else mask
|
||||||
@@ -1552,7 +1570,7 @@ class DetailerForEachTest(DetailerForEach):
|
|||||||
|
|
||||||
def doit(self, image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name,
|
def doit(self, image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name,
|
||||||
scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, detailer_hook=None,
|
scheduler, positive, negative, denoise, feather, noise_mask, force_inpaint, wildcard, detailer_hook=None,
|
||||||
cycle=1, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None):
|
cycle=1, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None, tiled_encode=False, tiled_decode=False):
|
||||||
|
|
||||||
if len(image) > 1:
|
if len(image) > 1:
|
||||||
raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.')
|
raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.')
|
||||||
@@ -1561,7 +1579,8 @@ class DetailerForEachTest(DetailerForEach):
|
|||||||
DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps,
|
DetailerForEach.do_detail(image, segs, model, clip, vae, guide_size, guide_size_for, max_size, seed, steps,
|
||||||
cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask,
|
cfg, sampler_name, scheduler, positive, negative, denoise, feather, noise_mask,
|
||||||
force_inpaint, wildcard, detailer_hook,
|
force_inpaint, wildcard, detailer_hook,
|
||||||
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt)
|
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather,
|
||||||
|
scheduler_func_opt=scheduler_func_opt, tiled_encode=tiled_encode, tiled_decode=tiled_decode)
|
||||||
|
|
||||||
# set fallback image
|
# set fallback image
|
||||||
if len(cropped) == 0:
|
if len(cropped) == 0:
|
||||||
@@ -1590,7 +1609,8 @@ class DetailerForEachTestPipe(DetailerForEachPipe):
|
|||||||
|
|
||||||
def doit(self, image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler,
|
def doit(self, image, segs, guide_size, guide_size_for, max_size, seed, steps, cfg, sampler_name, scheduler,
|
||||||
denoise, feather, noise_mask, force_inpaint, basic_pipe, wildcard, cycle=1,
|
denoise, feather, noise_mask, force_inpaint, basic_pipe, wildcard, cycle=1,
|
||||||
refiner_ratio=None, detailer_hook=None, refiner_basic_pipe_opt=None, inpaint_model=False, noise_mask_feather=0, scheduler_func_opt=None):
|
refiner_ratio=None, detailer_hook=None, refiner_basic_pipe_opt=None, inpaint_model=False, noise_mask_feather=0,
|
||||||
|
scheduler_func_opt=None, tiled_encode=False, tiled_decode=False):
|
||||||
|
|
||||||
if len(image) > 1:
|
if len(image) > 1:
|
||||||
raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.')
|
raise Exception('[Impact Pack] ERROR: DetailerForEach does not allow image batches.\nPlease refer to https://github.com/ltdrdata/ComfyUI-extension-tutorials/blob/Main/ComfyUI-Impact-Pack/tutorial/batching-detailer.md for more information.')
|
||||||
@@ -1609,7 +1629,8 @@ class DetailerForEachTestPipe(DetailerForEachPipe):
|
|||||||
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
||||||
refiner_clip=refiner_clip, refiner_positive=refiner_positive,
|
refiner_clip=refiner_clip, refiner_positive=refiner_positive,
|
||||||
refiner_negative=refiner_negative,
|
refiner_negative=refiner_negative,
|
||||||
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func_opt=scheduler_func_opt)
|
cycle=cycle, inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather,
|
||||||
|
scheduler_func_opt=scheduler_func_opt, tiled_encode=tiled_encode, tiled_decode=tiled_decode)
|
||||||
|
|
||||||
# set fallback image
|
# set fallback image
|
||||||
if len(cropped) == 0:
|
if len(cropped) == 0:
|
||||||
@@ -2322,7 +2343,11 @@ class ImpactWildcardProcessor:
|
|||||||
return {"required": {
|
return {"required": {
|
||||||
"wildcard_text": ("STRING", {"multiline": True, "dynamicPrompts": False, "tooltip": "Enter a prompt using wildcard syntax."}),
|
"wildcard_text": ("STRING", {"multiline": True, "dynamicPrompts": False, "tooltip": "Enter a prompt using wildcard syntax."}),
|
||||||
"populated_text": ("STRING", {"multiline": True, "dynamicPrompts": False, "tooltip": "The actual value passed during the execution of 'ImpactWildcardProcessor' is what is shown here. The behavior varies slightly depending on the mode. Wildcard syntax can also be used in 'populated_text'."}),
|
"populated_text": ("STRING", {"multiline": True, "dynamicPrompts": False, "tooltip": "The actual value passed during the execution of 'ImpactWildcardProcessor' is what is shown here. The behavior varies slightly depending on the mode. Wildcard syntax can also be used in 'populated_text'."}),
|
||||||
"mode": ("BOOLEAN", {"default": True, "label_on": "Populate", "label_off": "Fixed", "tooltip": "Populate: Before running the workflow, it overwrites the existing value of 'populated_text' with the prompt processed from 'wildcard_text'. In this mode, 'populated_text' cannot be edited.\nFixed: Ignores wildcard_text and keeps 'populated_text' as is. You can edit 'populated_text' in this mode."}),
|
"mode": (["populate", "fixed", "reproduce"], {"default": "populate", "tooltip":
|
||||||
|
"populate: Before running the workflow, it overwrites the existing value of 'populated_text' with the prompt processed from 'wildcard_text'. In this mode, 'populated_text' cannot be edited.\n"
|
||||||
|
"fixed: Ignores wildcard_text and keeps 'populated_text' as is. You can edit 'populated_text' in this mode.\n"
|
||||||
|
"reproduce: This mode operates as 'fixed' mode only once for reproduction, and then it switches to 'populate' mode."
|
||||||
|
}),
|
||||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "tooltip": "Determines the random seed to be used for wildcard processing."}),
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "tooltip": "Determines the random seed to be used for wildcard processing."}),
|
||||||
"Select to add Wildcard": (["Select the Wildcard to add to the text"],),
|
"Select to add Wildcard": (["Select the Wildcard to add to the text"],),
|
||||||
},
|
},
|
||||||
@@ -2331,7 +2356,7 @@ class ImpactWildcardProcessor:
|
|||||||
CATEGORY = "ImpactPack/Prompt"
|
CATEGORY = "ImpactPack/Prompt"
|
||||||
|
|
||||||
DESCRIPTION = ("The 'ImpactWildcardProcessor' processes text prompts written in wildcard syntax and outputs the processed text prompt.\n\n"
|
DESCRIPTION = ("The 'ImpactWildcardProcessor' processes text prompts written in wildcard syntax and outputs the processed text prompt.\n\n"
|
||||||
"TIP: Before the workflow is executed, the processing result of 'wildcard_text' is displayed in 'populated_text', and the populated text is saved along with the workflow. If you want to use a seed converted as input, write the prompt directly in 'populated_text' instead of 'wildcard_text', and set the mode to 'Fixed'.")
|
"TIP: Before the workflow is executed, the processing result of 'wildcard_text' is displayed in 'populated_text', and the populated text is saved along with the workflow. If you want to use a seed converted as input, write the prompt directly in 'populated_text' instead of 'wildcard_text', and set the mode to 'fixed'.")
|
||||||
|
|
||||||
RETURN_TYPES = ("STRING", )
|
RETURN_TYPES = ("STRING", )
|
||||||
FUNCTION = "doit"
|
FUNCTION = "doit"
|
||||||
@@ -2353,8 +2378,10 @@ class ImpactWildcardEncode:
|
|||||||
"clip": ("CLIP",),
|
"clip": ("CLIP",),
|
||||||
"wildcard_text": ("STRING", {"multiline": True, "dynamicPrompts": False, "tooltip": "Enter a prompt using wildcard syntax."}),
|
"wildcard_text": ("STRING", {"multiline": True, "dynamicPrompts": False, "tooltip": "Enter a prompt using wildcard syntax."}),
|
||||||
"populated_text": ("STRING", {"multiline": True, "dynamicPrompts": False, "tooltip": "The actual value passed during the execution of 'ImpactWildcardEncode' is what is shown here. The behavior varies slightly depending on the mode. Wildcard syntax can also be used in 'populated_text'."}),
|
"populated_text": ("STRING", {"multiline": True, "dynamicPrompts": False, "tooltip": "The actual value passed during the execution of 'ImpactWildcardEncode' is what is shown here. The behavior varies slightly depending on the mode. Wildcard syntax can also be used in 'populated_text'."}),
|
||||||
"mode": ("BOOLEAN", {"default": True, "label_on": "Populate", "label_off": "Fixed", "tooltip": "Populate: Before running the workflow, it overwrites the existing value of 'populated_text' with the prompt processed from 'wildcard_text'. In this mode, 'populated_text' cannot be edited.\n"
|
"mode": (["populate", "fixed", "reproduce"], {"tooltip":
|
||||||
"Fixed: Ignores wildcard_text and keeps 'populated_text' as is. You can edit 'populated_text' in this mode."}),
|
"populate: Before running the workflow, it overwrites the existing value of 'populated_text' with the prompt processed from 'wildcard_text'. In this mode, 'populated_text' cannot be edited.\n"
|
||||||
|
"fixed: Ignores wildcard_text and keeps 'populated_text' as is. You can edit 'populated_text' in this mode\n."
|
||||||
|
"reproduce: This mode operates as 'fixed' mode only once for reproduction, and then it switches to 'populate' mode."}),
|
||||||
"Select to add LoRA": (["Select the LoRA to add to the text"] + folder_paths.get_filename_list("loras"), ),
|
"Select to add LoRA": (["Select the LoRA to add to the text"] + folder_paths.get_filename_list("loras"), ),
|
||||||
"Select to add Wildcard": (["Select the Wildcard to add to the text"], ),
|
"Select to add Wildcard": (["Select the Wildcard to add to the text"], ),
|
||||||
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "tooltip": "Determines the random seed to be used for wildcard processing."}),
|
"seed": ("INT", {"default": 0, "min": 0, "max": 0xffffffffffffffff, "tooltip": "Determines the random seed to be used for wildcard processing."}),
|
||||||
@@ -2364,7 +2391,7 @@ class ImpactWildcardEncode:
|
|||||||
CATEGORY = "ImpactPack/Prompt"
|
CATEGORY = "ImpactPack/Prompt"
|
||||||
|
|
||||||
DESCRIPTION = ("The 'ImpactWildcardEncode' node processes text prompts written in wildcard syntax and outputs them as conditioning. It also supports LoRA syntax, with the applied LoRA reflected in the model's output.\n\n"
|
DESCRIPTION = ("The 'ImpactWildcardEncode' node processes text prompts written in wildcard syntax and outputs them as conditioning. It also supports LoRA syntax, with the applied LoRA reflected in the model's output.\n\n"
|
||||||
"TIP1: Before the workflow is executed, the processing result of 'wildcard_text' is displayed in 'populated_text', and the populated text is saved along with the workflow. If you want to use a seed converted as input, write the prompt directly in 'populated_text' instead of 'wildcard_text', and set the mode to 'Fixed'.\n"
|
"TIP1: Before the workflow is executed, the processing result of 'wildcard_text' is displayed in 'populated_text', and the populated text is saved along with the workflow. If you want to use a seed converted as input, write the prompt directly in 'populated_text' instead of 'wildcard_text', and set the mode to 'fixed'.\n"
|
||||||
"TIP2: If the 'Inspire Pack' is installed, LBW(LoRA Block Weight) syntax can also be applied.")
|
"TIP2: If the 'Inspire Pack' is installed, LBW(LoRA Block Weight) syntax can also be applied.")
|
||||||
|
|
||||||
RETURN_TYPES = ("MODEL", "CLIP", "CONDITIONING", "STRING")
|
RETURN_TYPES = ("MODEL", "CLIP", "CONDITIONING", "STRING")
|
||||||
|
|||||||
@@ -78,9 +78,13 @@ async def sam_prepare(request):
|
|||||||
if data['sam_model_name'] == 'auto':
|
if data['sam_model_name'] == 'auto':
|
||||||
model_name = impact.config.get_config()['sam_editor_model']
|
model_name = impact.config.get_config()['sam_editor_model']
|
||||||
|
|
||||||
model_name = os.path.join(impact_pack.model_path, "sams", model_name)
|
model_path = folder_paths.get_full_path("sams", model_name)
|
||||||
|
|
||||||
logging.info(f"[Impact Pack] Loading SAM model '{impact_pack.model_path}'")
|
if model_path is None:
|
||||||
|
logging.error(f"[Impact Pack] The '{model_name}' model file cannot be found in any sams model path.")
|
||||||
|
return web.Response(status=400)
|
||||||
|
|
||||||
|
logging.info(f"[Impact Pack] Loading SAM model '{model_path}'")
|
||||||
|
|
||||||
filename, image_dir = folder_paths.annotated_filepath(data["filename"])
|
filename, image_dir = folder_paths.annotated_filepath(data["filename"])
|
||||||
|
|
||||||
@@ -93,7 +97,7 @@ async def sam_prepare(request):
|
|||||||
if image_dir is None:
|
if image_dir is None:
|
||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
|
||||||
thread = threading.Thread(target=async_prepare_sam, args=(image_dir, model_name, filename,))
|
thread = threading.Thread(target=async_prepare_sam, args=(image_dir, model_path, filename,))
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
logging.info("[Impact Pack] SAM model loaded. ")
|
logging.info("[Impact Pack] SAM model loaded. ")
|
||||||
@@ -478,7 +482,17 @@ def onprompt_populate_wildcards(json_data):
|
|||||||
for k, v in prompt.items():
|
for k, v in prompt.items():
|
||||||
if 'class_type' in v and (v['class_type'] == 'ImpactWildcardEncode' or v['class_type'] == 'ImpactWildcardProcessor'):
|
if 'class_type' in v and (v['class_type'] == 'ImpactWildcardEncode' or v['class_type'] == 'ImpactWildcardProcessor'):
|
||||||
inputs = v['inputs']
|
inputs = v['inputs']
|
||||||
if inputs['mode'] and isinstance(inputs['populated_text'], str):
|
|
||||||
|
# legacy adapter
|
||||||
|
if isinstance(inputs['mode'], bool):
|
||||||
|
if inputs['mode']:
|
||||||
|
new_mode = 'populate'
|
||||||
|
else:
|
||||||
|
new_mode = 'fixed'
|
||||||
|
|
||||||
|
inputs['mode'] = new_mode
|
||||||
|
|
||||||
|
if inputs['mode'] == 'populate' and isinstance(inputs['populated_text'], str):
|
||||||
if isinstance(inputs['seed'], list):
|
if isinstance(inputs['seed'], list):
|
||||||
try:
|
try:
|
||||||
input_node = prompt[inputs['seed'][0]]
|
input_node = prompt[inputs['seed'][0]]
|
||||||
@@ -499,17 +513,22 @@ def onprompt_populate_wildcards(json_data):
|
|||||||
input_seed = int(inputs['seed'])
|
input_seed = int(inputs['seed'])
|
||||||
|
|
||||||
inputs['populated_text'] = wildcards.process(inputs['wildcard_text'], input_seed)
|
inputs['populated_text'] = wildcards.process(inputs['wildcard_text'], input_seed)
|
||||||
inputs['mode'] = False
|
inputs['mode'] = 'reproduce'
|
||||||
|
|
||||||
PromptServer.instance.send_sync("impact-node-feedback", {"node_id": k, "widget_name": "populated_text", "type": "STRING", "value": inputs['populated_text']})
|
PromptServer.instance.send_sync("impact-node-feedback", {"node_id": k, "widget_name": "populated_text", "type": "STRING", "value": inputs['populated_text']})
|
||||||
updated_widget_values[k] = inputs['populated_text']
|
updated_widget_values[k] = inputs['populated_text']
|
||||||
|
|
||||||
|
if inputs['mode'] == 'reproduce':
|
||||||
|
PromptServer.instance.send_sync("impact-node-feedback", {"node_id": k, "widget_name": "mode", "type": "STRING", "value": 'populate'})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if 'extra_data' in json_data and 'extra_pnginfo' in json_data['extra_data']:
|
if 'extra_data' in json_data and 'extra_pnginfo' in json_data['extra_data']:
|
||||||
for node in json_data['extra_data']['extra_pnginfo']['workflow']['nodes']:
|
for node in json_data['extra_data']['extra_pnginfo']['workflow']['nodes']:
|
||||||
key = str(node['id'])
|
key = str(node['id'])
|
||||||
if key in updated_widget_values:
|
if key in updated_widget_values:
|
||||||
node['widgets_values'][1] = updated_widget_values[key]
|
node['widgets_values'][1] = updated_widget_values[key]
|
||||||
node['widgets_values'][2] = False
|
node['widgets_values'][2] = 'reproduce'
|
||||||
|
|
||||||
|
|
||||||
def onprompt_for_remote(json_data):
|
def onprompt_for_remote(json_data):
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class SEGSDetailer:
|
|||||||
"denoise": ("FLOAT", {"default": 0.5, "min": 0.0001, "max": 1.0, "step": 0.01}),
|
"denoise": ("FLOAT", {"default": 0.5, "min": 0.0001, "max": 1.0, "step": 0.01}),
|
||||||
"noise_mask": ("BOOLEAN", {"default": True, "label_on": "enabled", "label_off": "disabled"}),
|
"noise_mask": ("BOOLEAN", {"default": True, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
"force_inpaint": ("BOOLEAN", {"default": True, "label_on": "enabled", "label_off": "disabled"}),
|
"force_inpaint": ("BOOLEAN", {"default": True, "label_on": "enabled", "label_off": "disabled"}),
|
||||||
"basic_pipe": ("BASIC_PIPE",),
|
"basic_pipe": ("BASIC_PIPE", {"tooltip": "If the `ImpactDummyInput` is connected to the model in the basic_pipe, the inference stage is skipped."}),
|
||||||
"refiner_ratio": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0}),
|
"refiner_ratio": ("FLOAT", {"default": 0.2, "min": 0.0, "max": 1.0}),
|
||||||
"batch_size": ("INT", {"default": 1, "min": 1, "max": 100}),
|
"batch_size": ("INT", {"default": 1, "min": 1, "max": 100}),
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ class SEGSDetailer:
|
|||||||
new_segs = []
|
new_segs = []
|
||||||
cnet_pil_list = []
|
cnet_pil_list = []
|
||||||
|
|
||||||
if noise_mask_feather > 0 and 'denoise_mask_function' not in model.model_options:
|
if not (isinstance(model, str) and model == "DUMMY") and noise_mask_feather > 0 and 'denoise_mask_function' not in model.model_options:
|
||||||
model = nodes_differential_diffusion.DifferentialDiffusion().apply(model)[0]
|
model = nodes_differential_diffusion.DifferentialDiffusion().apply(model)[0]
|
||||||
|
|
||||||
for i in range(batch_size):
|
for i in range(batch_size):
|
||||||
@@ -113,13 +113,17 @@ class SEGSDetailer:
|
|||||||
for condition, details in negative
|
for condition, details in negative
|
||||||
]
|
]
|
||||||
|
|
||||||
enhanced_image, cnet_pils = core.enhance_detail(cropped_image, model, clip, vae, guide_size, guide_size_for, max_size,
|
if not (isinstance(model, str) and model == "DUMMY"):
|
||||||
seg.bbox, seed, steps, cfg, sampler_name, scheduler,
|
enhanced_image, cnet_pils = core.enhance_detail(cropped_image, model, clip, vae, guide_size, guide_size_for, max_size,
|
||||||
cropped_positive, cropped_negative, denoise, cropped_mask, force_inpaint,
|
seg.bbox, seed, steps, cfg, sampler_name, scheduler,
|
||||||
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
cropped_positive, cropped_negative, denoise, cropped_mask, force_inpaint,
|
||||||
refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative,
|
refiner_ratio=refiner_ratio, refiner_model=refiner_model,
|
||||||
control_net_wrapper=seg.control_net_wrapper, cycle=cycle,
|
refiner_clip=refiner_clip, refiner_positive=refiner_positive, refiner_negative=refiner_negative,
|
||||||
inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func=scheduler_func_opt)
|
control_net_wrapper=seg.control_net_wrapper, cycle=cycle,
|
||||||
|
inpaint_model=inpaint_model, noise_mask_feather=noise_mask_feather, scheduler_func=scheduler_func_opt)
|
||||||
|
else:
|
||||||
|
enhanced_image = cropped_image
|
||||||
|
cnet_pils = None
|
||||||
|
|
||||||
if cnet_pils is not None:
|
if cnet_pils is not None:
|
||||||
cnet_pil_list.extend(cnet_pils)
|
cnet_pil_list.extend(cnet_pils)
|
||||||
|
|||||||
+10
-3
@@ -7,6 +7,7 @@ import nodes
|
|||||||
from . import config
|
from . import config
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import comfy
|
import comfy
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
class TensorBatchBuilder:
|
class TensorBatchBuilder:
|
||||||
@@ -501,15 +502,21 @@ def crop_image(image, crop_region):
|
|||||||
return crop_tensor4(image, crop_region)
|
return crop_tensor4(image, crop_region)
|
||||||
|
|
||||||
|
|
||||||
def to_latent_image(pixels, vae):
|
def to_latent_image(pixels, vae, vae_tiled_encode=False):
|
||||||
x = pixels.shape[1]
|
x = pixels.shape[1]
|
||||||
y = pixels.shape[2]
|
y = pixels.shape[2]
|
||||||
if pixels.shape[1] != x or pixels.shape[2] != y:
|
if pixels.shape[1] != x or pixels.shape[2] != y:
|
||||||
pixels = pixels[:, :x, :y, :]
|
pixels = pixels[:, :x, :y, :]
|
||||||
|
|
||||||
vae_encode = nodes.VAEEncode()
|
start = time.time()
|
||||||
|
if vae_tiled_encode:
|
||||||
|
encoded = nodes.VAEEncodeTiled().encode(vae, pixels, 512, overlap=64)[0] # using default settings
|
||||||
|
print(f"[Impact Pack] vae encoded (tiled) in {time.time() - start:.1f}s")
|
||||||
|
else:
|
||||||
|
encoded = nodes.VAEEncode().encode(vae, pixels)[0]
|
||||||
|
print(f"[Impact Pack] vae encoded in {time.time() - start:.1f}s")
|
||||||
|
|
||||||
return vae_encode.encode(vae, pixels)[0]
|
return encoded
|
||||||
|
|
||||||
|
|
||||||
def empty_pil_tensor(w=64, h=64):
|
def empty_pil_tensor(w=64, h=64):
|
||||||
|
|||||||
@@ -237,7 +237,23 @@ def process(text, seed=None):
|
|||||||
keyword = match.lower()
|
keyword = match.lower()
|
||||||
keyword = wildcard_normalize(keyword)
|
keyword = wildcard_normalize(keyword)
|
||||||
if keyword in local_wildcard_dict:
|
if keyword in local_wildcard_dict:
|
||||||
replacement = random_gen.choice(local_wildcard_dict[keyword])
|
# look for adjusted probability
|
||||||
|
adjusted_probabilities = []
|
||||||
|
total_prob = 0
|
||||||
|
options=local_wildcard_dict[keyword]
|
||||||
|
for option in options:
|
||||||
|
parts = option.split('::', 1)
|
||||||
|
if len(parts) == 2 and is_numeric_string(parts[0].strip()):
|
||||||
|
config_value = float(parts[0].strip())
|
||||||
|
else:
|
||||||
|
config_value = 1 # Default value if no configuration is provided
|
||||||
|
|
||||||
|
adjusted_probabilities.append(config_value)
|
||||||
|
total_prob += config_value
|
||||||
|
|
||||||
|
normalized_probabilities = [prob / total_prob for prob in adjusted_probabilities]
|
||||||
|
selected_item = random_gen.choice(options, p=normalized_probabilities, replace=False)
|
||||||
|
replacement = re.sub(r'^\s*[0-9.]+::', '', selected_item, 1)
|
||||||
replacements_found = True
|
replacements_found = True
|
||||||
string = string.replace(f"__{match}__", replacement, 1)
|
string = string.replace(f"__{match}__", replacement, 1)
|
||||||
elif '*' in keyword:
|
elif '*' in keyword:
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "comfyui-impact-pack"
|
name = "comfyui-impact-pack"
|
||||||
description = "This node pack offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler."
|
description = "This node pack offers various detector nodes and detailer nodes that allow you to configure a workflow that automatically enhances facial details. And provide iterative upscaler."
|
||||||
version = "8.3"
|
version = "8.6"
|
||||||
license = { file = "LICENSE.txt" }
|
license = { file = "LICENSE.txt" }
|
||||||
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]
|
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user