Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a2adda580 | ||
|
|
d05882a9e0 | ||
|
|
d900939861 | ||
|
|
cd2696f6fd | ||
|
|
0b1ac0f1c5 | ||
|
|
216d7fd60c | ||
|
|
28cd2f70b2 |
@@ -132,6 +132,8 @@ NOTE: The UltralyticsDetectorProvider node is not part of the ComfyUI-Impact-Pac
|
||||
* `SEGS Filter (label)` - This node filters SEGS based on the label of the detected areas.
|
||||
* `SEGS Filter (ordered)` - This node sorts SEGS based on size and position and retrieves SEGs within a certain range.
|
||||
* `SEGS Filter (range)` - This node retrieves only SEGs from SEGS that have a size and position within a certain range.
|
||||
* `SEGS Filter (non max suppression)` - This node filters SEGS by removing those with high overlap based on the Intersection over Union (IoU) threshold, keeping only the most confident detections.
|
||||
* `SEGS Filter (intersection)` - This node filters segs1, keeping only the SEGS that do not significantly overlap with any SEGS in segs2, based on the Intersection over Area (IoA) threshold.
|
||||
* `SEGS Assign (label)` - Assign labels sequentially to SEGS. This node is useful when used with `[LAB]` of FaceDetailer.
|
||||
* `SEGSConcat` - Concatenate segs1 and segs2. If source shape of segs1 and segs2 are different from segs2 will be ignored.
|
||||
* `SEGS Merge` - SEGS contains multiple SEGs. SEGS Merge integrates several SEGs into a single merged SEG. The label is changed to `merged` and the confidence becomes the minimum confidence. The applied controlnet and cropped_image are removed.
|
||||
@@ -249,7 +251,7 @@ NOTE: The UltralyticsDetectorProvider node is not part of the ComfyUI-Impact-Pac
|
||||
|
||||
|
||||
### Impact KSampler
|
||||
* These samplers support basic_pipe and AYS scheduler
|
||||
* These samplers support basic_pipe and AYS/OSS/GITS scheduler
|
||||
* `KSampler (pipe)` - pipe version of KSampler
|
||||
* `KSampler (advanced/pipe)` - pipe version of KSamplerAdvacned
|
||||
* When converting the scheduler widget to input, refer to the `Impact Scheduler Adapter` node to resolve compatibility issues.
|
||||
|
||||
@@ -3,6 +3,48 @@ import { app } from "../../scripts/app.js";
|
||||
|
||||
let original_show = app.ui.dialog.show;
|
||||
|
||||
export function customAlert(message) {
|
||||
try {
|
||||
app.extensionManager.toast.addAlert(message);
|
||||
}
|
||||
catch {
|
||||
alert(message);
|
||||
}
|
||||
}
|
||||
|
||||
export function isBeforeFrontendVersion(compareVersion) {
|
||||
try {
|
||||
const frontendVersion = window['__COMFYUI_FRONTEND_VERSION__'];
|
||||
if (typeof frontendVersion !== 'string') {
|
||||
return false;
|
||||
}
|
||||
|
||||
function parseVersion(versionString) {
|
||||
const parts = versionString.split('.').map(Number);
|
||||
return parts.length === 3 && parts.every(part => !isNaN(part)) ? parts : null;
|
||||
}
|
||||
|
||||
const currentVersion = parseVersion(frontendVersion);
|
||||
const comparisonVersion = parseVersion(compareVersion);
|
||||
|
||||
if (!currentVersion || !comparisonVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
if (currentVersion[i] > comparisonVersion[i]) {
|
||||
return false;
|
||||
} else if (currentVersion[i] < comparisonVersion[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function dialog_show_wrapper(html) {
|
||||
if (typeof html === "string") {
|
||||
if(html.includes("IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE")) {
|
||||
|
||||
+19
-13
@@ -1,6 +1,13 @@
|
||||
import { ComfyApp, app } from "../../scripts/app.js";
|
||||
import { ComfyDialog, $el } from "../../scripts/ui.js";
|
||||
import { api } from "../../scripts/api.js";
|
||||
import { customAlert, isBeforeFrontendVersion } from "./common.js";
|
||||
|
||||
const is_legacy_front = () => isBeforeFrontendVersion('1.16.9');
|
||||
|
||||
if(is_legacy_front()) {
|
||||
customAlert("An outdated version(<1.16.9) of the `comfyui-frontend-package` is installed. It is not compatible with the current version of the Impact Pack.");
|
||||
}
|
||||
|
||||
let wildcards_list = [];
|
||||
async function load_wildcards() {
|
||||
@@ -403,6 +410,9 @@ app.registerExtension({
|
||||
let slot_i = 1;
|
||||
for (let i = 0; i < this.outputs.length; i++) {
|
||||
this.outputs[i].name = `output${slot_i}`
|
||||
if (this.outputs[i].slot_index === undefined) {
|
||||
this.outputs[i].slot_index = i;
|
||||
}
|
||||
slot_i++;
|
||||
}
|
||||
|
||||
@@ -471,6 +481,11 @@ app.registerExtension({
|
||||
|
||||
const onConnectionsChange = nodeType.prototype.onConnectionsChange;
|
||||
nodeType.prototype.onConnectionsChange = function (type, index, connected, link_info) {
|
||||
const stackTrace = new Error().stack;
|
||||
if(stackTrace.includes('LGraph.configure')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!link_info)
|
||||
return;
|
||||
|
||||
@@ -513,7 +528,7 @@ app.registerExtension({
|
||||
if(this.inputs[0].type == '*'){
|
||||
const node = app.graph.getNodeById(link_info.origin_id);
|
||||
let origin_type = node.outputs[link_info.origin_slot]?.type;
|
||||
if(link_info.target_slot == 0 && this.inputs.length > 1) {
|
||||
if(link_info.target_slot == 0 && this.inputs.length > 3) { // NOTE: widgets are regarded as input since new front
|
||||
origin_type = this.inputs[1].type;
|
||||
node.connect(link_info.origin_slot, node.id, 'input1');
|
||||
}
|
||||
@@ -538,13 +553,7 @@ app.registerExtension({
|
||||
let select_slot = this.inputs.find(x => x.name == "select");
|
||||
let mode_slot = this.inputs.find(x => x.name == "sel_mode");
|
||||
|
||||
let converted_count = 0;
|
||||
converted_count += select_slot?1:0;
|
||||
converted_count += mode_slot?1:0;
|
||||
|
||||
if (!connected && (this.inputs.length > 1+converted_count)) {
|
||||
const stackTrace = new Error().stack;
|
||||
|
||||
if (!connected && (this.inputs.length > 3)) {
|
||||
if(
|
||||
!stackTrace.includes('LGraphNode.prototype.connect') && // for touch device
|
||||
!stackTrace.includes('LGraphNode.connect') && // for mouse device
|
||||
@@ -554,6 +563,7 @@ app.registerExtension({
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
let slot_i = 1;
|
||||
for (let i = 0; i < this.inputs.length; i++) {
|
||||
let input_i = this.inputs[i];
|
||||
@@ -564,11 +574,7 @@ app.registerExtension({
|
||||
}
|
||||
|
||||
let last_slot = this.inputs[this.inputs.length - 1];
|
||||
if (
|
||||
(last_slot.name == 'select' && last_slot.name != 'sel_mode' && this.inputs[this.inputs.length - 2].link != undefined)
|
||||
|| (last_slot.name != 'select' && last_slot.name != 'sel_mode' && last_slot.link != undefined)) {
|
||||
this.addInput(`${input_name}${slot_i}`, this.outputs[0].type);
|
||||
}
|
||||
this.addInput(`${input_name}${slot_i}`, this.outputs[0].type);
|
||||
|
||||
if(this.widgets?.length) {
|
||||
this.widgets[0].options.max = select_slot?this.inputs.length-1:this.inputs.length;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import configparser
|
||||
import os
|
||||
|
||||
version_code = [8, 9]
|
||||
version_code = [8, 12]
|
||||
version = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||
|
||||
dependency_version = 24
|
||||
|
||||
@@ -48,7 +48,7 @@ preview_bridge_last_mask_cache = {}
|
||||
|
||||
current_prompt = None
|
||||
|
||||
SCHEDULERS = comfy.samplers.KSampler.SCHEDULERS + ['AYS SDXL', 'AYS SD1', 'AYS SVD', 'GITS[coeff=1.2]', 'LTXV[default]']
|
||||
SCHEDULERS = comfy.samplers.KSampler.SCHEDULERS + ['AYS SDXL', 'AYS SD1', 'AYS SVD', 'GITS[coeff=1.2]', 'LTXV[default]', 'OSS FLUX', 'OSS Wan']
|
||||
|
||||
|
||||
def is_execution_model_version_supported():
|
||||
|
||||
@@ -2435,7 +2435,7 @@ class ImpactSchedulerAdapter:
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"defaultInput": True, }),
|
||||
"extra_scheduler": (['None', 'AYS SDXL', 'AYS SD1', 'AYS SVD', 'GITS[coeff=1.2]', 'LTXV[default]'],),
|
||||
"extra_scheduler": (['None', 'AYS SDXL', 'AYS SD1', 'AYS SVD', 'GITS[coeff=1.2]', 'LTXV[default]', 'OSS FLUX', 'OSS Wan'],),
|
||||
}}
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
@@ -29,6 +29,8 @@ def calculate_sigmas(model, sampler, scheduler, steps):
|
||||
sigmas = nodes.NODE_CLASS_MAPPINGS['GITSScheduler']().get_sigmas(float(scheduler[11:-1]), steps, denoise=1.0)[0]
|
||||
elif scheduler == 'LTXV[default]':
|
||||
sigmas = nodes.NODE_CLASS_MAPPINGS['LTXVScheduler']().get_sigmas(20, 2.05, 0.95, True, 0.1)[0]
|
||||
elif scheduler.startswith('OSS'):
|
||||
sigmas = nodes.NODE_CLASS_MAPPINGS['OptimalStepsScheduler']().get_sigmas(scheduler[4:], steps, denoise=1.0)[0]
|
||||
else:
|
||||
sigmas = samplers.calculate_sigmas(model.get_model_object("model_sampling"), scheduler, steps)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from impact.utils import any_typ
|
||||
import impact.core as core
|
||||
import re
|
||||
import nodes
|
||||
import traceback
|
||||
|
||||
|
||||
class ImpactCompare:
|
||||
@classmethod
|
||||
@@ -574,27 +574,6 @@ class ImpactSleep:
|
||||
return (signal,)
|
||||
|
||||
|
||||
error_skip_flag = False
|
||||
try:
|
||||
import cm_global
|
||||
def filter_message(str):
|
||||
global error_skip_flag
|
||||
|
||||
if "IMPACT-PACK-SIGNAL: STOP CONTROL BRIDGE" in str:
|
||||
return True
|
||||
elif error_skip_flag and "ERROR:root:!!! Exception during processing !!!\n" == str:
|
||||
error_skip_flag = False
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
cm_global.try_call(api='cm.register_message_collapse', f=filter_message)
|
||||
|
||||
except Exception as e:
|
||||
print(f"[WARN] ComfyUI-Impact-Pack: `ComfyUI` or `ComfyUI-Manager` is an outdated version.")
|
||||
pass
|
||||
|
||||
|
||||
def workflow_to_map(workflow):
|
||||
nodes = {}
|
||||
links = {}
|
||||
|
||||
@@ -13,6 +13,7 @@ from . import segs_upscaler
|
||||
from comfy.cli_args import args
|
||||
import math
|
||||
|
||||
from typing import Callable, Union
|
||||
|
||||
try:
|
||||
from comfy_extras import nodes_differential_diffusion
|
||||
@@ -504,7 +505,7 @@ class SEGSOrderedFilter:
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": {
|
||||
"segs": ("SEGS", ),
|
||||
"target": (["area(=w*h)", "width", "height", "x1", "y1", "x2", "y2", "confidence"],),
|
||||
"target": (["area(=w*h)", "width", "height", "x1", "y1", "x2", "y2", "confidence", "none"],),
|
||||
"order": ("BOOLEAN", {"default": True, "label_on": "descending", "label_off": "ascending"}),
|
||||
"take_start": ("INT", {"default": 0, "min": 0, "max": sys.maxsize, "step": 1}),
|
||||
"take_count": ("INT", {"default": 1, "min": 0, "max": sys.maxsize, "step": 1}),
|
||||
@@ -517,51 +518,35 @@ class SEGSOrderedFilter:
|
||||
|
||||
CATEGORY = "ImpactPack/Util"
|
||||
|
||||
@staticmethod
|
||||
def get_sort_key_fn(target: str) -> Union[Callable, None]:
|
||||
if target == "none":
|
||||
return None
|
||||
|
||||
def sort_key_fn(seg):
|
||||
x1, y1, x2, y2 = seg.crop_region
|
||||
if target == "confidence": return seg.confidence
|
||||
if target == "area(=w*h)": return (x2 - x1) * (y2 - y1)
|
||||
if target == "width": return x2 - x1
|
||||
if target == "height": return y2 - y1
|
||||
if target == "x1": return x1
|
||||
if target == "y1": return y1
|
||||
if target == "x2": return x2
|
||||
if target == "y2": return y2
|
||||
raise Exception(f"[Impact Pack] SEGSOrderedFilter - Unexpected target '{target}'")
|
||||
|
||||
return sort_key_fn
|
||||
|
||||
def doit(self, segs, target, order, take_start, take_count):
|
||||
segs_with_order = []
|
||||
sort_key_fn = SEGSOrderedFilter.get_sort_key_fn(target)
|
||||
|
||||
for seg in segs[1]:
|
||||
x1 = seg.crop_region[0]
|
||||
y1 = seg.crop_region[1]
|
||||
x2 = seg.crop_region[2]
|
||||
y2 = seg.crop_region[3]
|
||||
sorted_list = list(segs[1]) # make a shallow copy, so it does not mutate the original list when sort
|
||||
if sort_key_fn is not None:
|
||||
sorted_list.sort(key=sort_key_fn, reverse=order)
|
||||
|
||||
if target == "area(=w*h)":
|
||||
value = (y2 - y1) * (x2 - x1)
|
||||
elif target == "width":
|
||||
value = x2 - x1
|
||||
elif target == "height":
|
||||
value = y2 - y1
|
||||
elif target == "x1":
|
||||
value = x1
|
||||
elif target == "x2":
|
||||
value = x2
|
||||
elif target == "y1":
|
||||
value = y1
|
||||
elif target == "y2":
|
||||
value = y2
|
||||
elif target == "confidence":
|
||||
value = seg.confidence
|
||||
else:
|
||||
raise Exception(f"[Impact Pack] SEGSOrderedFilter - Unexpected target '{target}'")
|
||||
|
||||
segs_with_order.append((value, seg))
|
||||
|
||||
if order:
|
||||
sorted_list = sorted(segs_with_order, key=lambda x: x[0], reverse=True)
|
||||
else:
|
||||
sorted_list = sorted(segs_with_order, key=lambda x: x[0], reverse=False)
|
||||
|
||||
result_list = []
|
||||
remained_list = []
|
||||
|
||||
for i, item in enumerate(sorted_list):
|
||||
if take_start <= i < take_start + take_count:
|
||||
result_list.append(item[1])
|
||||
else:
|
||||
remained_list.append(item[1])
|
||||
|
||||
return (segs[0], result_list), (segs[0], remained_list),
|
||||
take_stop = take_start + take_count
|
||||
return (segs[0], sorted_list[take_start:take_stop]), \
|
||||
(segs[0], sorted_list[:take_start] + sorted_list[take_stop:]),
|
||||
|
||||
|
||||
class SEGSRangeFilter:
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
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."
|
||||
version = "8.9"
|
||||
version = "8.12"
|
||||
license = { file = "LICENSE.txt" }
|
||||
dependencies = ["segment-anything", "scikit-image", "piexif", "transformers", "opencv-python-headless", "GitPython", "scipy>=1.11.4"]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user