Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50c7b71a6a | ||
|
|
5b4e55058a | ||
|
|
45cb4dfe59 | ||
|
|
1365a5d377 | ||
|
|
122a1fffa1 | ||
|
|
0e2638b699 | ||
|
|
f10e457c30 | ||
|
|
f69aab1460 | ||
|
|
ef1053fbb9 | ||
|
|
1a3bf8c90c | ||
|
|
b67bdff24a | ||
|
|
4b36344be6 | ||
|
|
af3543d6cb | ||
|
|
54066cb848 | ||
|
|
f5c9e24148 | ||
|
|
f8a2591c65 | ||
|
|
eaa7d4a0b8 | ||
|
|
5809fcdcb9 | ||
|
|
40a3ba4d41 | ||
|
|
74db20c95e | ||
|
|
6dfb6e1acd | ||
|
|
7ba0e2760c | ||
|
|
2074152852 | ||
|
|
979f356783 | ||
|
|
f5467e1a37 | ||
|
|
769bc0f14a | ||
|
|
3345986dd7 | ||
|
|
d21517351d | ||
|
|
3d54756136 | ||
|
|
b61465c06f | ||
|
|
55dd4ccef5 | ||
|
|
4401965637 |
@@ -7,15 +7,19 @@ on:
|
||||
paths:
|
||||
- "pyproject.toml"
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
|
||||
jobs:
|
||||
publish-node:
|
||||
name: Publish Custom Node to registry
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.repository_owner == 'ltdrdata' }}
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v4
|
||||
- name: Publish Custom Node
|
||||
uses: Comfy-Org/publish-node-action@main
|
||||
uses: Comfy-Org/publish-node-action@v1
|
||||
with:
|
||||
## Add your own personal access token to your Github Repository secrets and reference it here.
|
||||
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
|
||||
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }}
|
||||
|
||||
@@ -15,6 +15,19 @@ This node pack provides nodes that complement the [ComfyUI Impact Pack](https://
|
||||
* civitai/[adetailer](https://civitai.com/search/models?sortBy=models_v5&query=adetailer) - You can download various types detection models....Many models are associated with NSFW content.
|
||||
|
||||
|
||||
## Paths
|
||||
* In `extra_model_paths.yaml`, you can add the following entries:
|
||||
- `ultralytics_bbox` - Specifies the paths for bbox YOLO models.
|
||||
- `ultralytics_segm` - Specifies the paths for segm YOLO models.
|
||||
- `ultralytics` - Allows the presence of `bbox/` and `segm/` subdirectories.
|
||||
|
||||
|
||||
## Model loading configuration related to `weights_only`
|
||||
* Loading model files can involve executing code, so if malicious code is embedded in a model, it can pose a security risk. For this reason, PyTorch 2.6 and later have introduced features for safer model loading. The issue is that older model files, which were created without such safe loading (weights_only) restrictions, may occasionally fail to load properly.
|
||||
* By listing the paths of models deemed safe in `<user_directory>/default/ComfyUI-Impact-Subpack/model-whitelist.txt`, those specific models will have weights_only disabled, allowing them to be loaded without restriction.
|
||||
* `<user_directory>`: typically located at ComfyUI/user.
|
||||
|
||||
|
||||
## How To Install?
|
||||
|
||||
### Install via ComfyUI-Manager (Recommended)
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@
|
||||
import importlib
|
||||
import logging
|
||||
|
||||
version_code = [1, 2, 2]
|
||||
version_code = [1, 3, 5]
|
||||
version_str = f"V{version_code[0]}.{version_code[1]}" + (f'.{version_code[2]}' if len(version_code) > 2 else '')
|
||||
logging.info(f"### Loading: ComfyUI-Impact-Subpack ({version_str})")
|
||||
|
||||
|
||||
+5
-4
@@ -1,21 +1,22 @@
|
||||
import os
|
||||
import sys
|
||||
from torchvision.datasets.utils import download_url
|
||||
import logging
|
||||
|
||||
subpack_path = os.path.join(os.path.dirname(__file__))
|
||||
|
||||
comfy_path = os.environ.get('COMFYUI_PATH')
|
||||
if comfy_path is None:
|
||||
comfy_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||
print(f"\nWARN: The `COMFYUI_PATH` environment variable is not set. Assuming `{comfy_path}` as the ComfyUI path.", file=sys.stderr)
|
||||
|
||||
logging.warning(f"\nWARN: The `COMFYUI_PATH` environment variable is not set. Assuming `{comfy_path}` as the ComfyUI path.")
|
||||
|
||||
sys.path.append(comfy_path)
|
||||
|
||||
model_path = os.environ.get('COMFYUI_MODEL_PATH')
|
||||
if model_path is None:
|
||||
model_path = os.path.abspath(os.path.join(comfy_path, 'models'))
|
||||
print(f"\nWARN: The `COMFYUI_MODEL_PATH` environment variable is not set. Assuming `{model_path}` as the ComfyUI path.", file=sys.stderr)
|
||||
|
||||
logging.warning(f"\nWARN: The `COMFYUI_MODEL_PATH` environment variable is not set. Assuming `{model_path}` as the ComfyUI path.")
|
||||
|
||||
|
||||
ultralytics_bbox_path = os.path.join(model_path, "ultralytics", "bbox")
|
||||
ultralytics_segm_path = os.path.join(model_path, "ultralytics", "segm")
|
||||
|
||||
+239
-81
@@ -7,6 +7,10 @@ from collections import namedtuple
|
||||
from . import utils
|
||||
import inspect
|
||||
import logging
|
||||
import os
|
||||
|
||||
import pickle
|
||||
import folder_paths
|
||||
|
||||
|
||||
orig_torch_load = torch.load
|
||||
@@ -17,6 +21,99 @@ SEG = namedtuple("SEG",
|
||||
defaults=[None])
|
||||
|
||||
|
||||
# --- Whitelist Configuration ---
|
||||
WHITELIST_DIR = None
|
||||
WHITELIST_FILE_PATH = None
|
||||
|
||||
try:
|
||||
# --- Attempting: Use ComfyUI's folder_paths (Preferred Method) ---
|
||||
user_dir = folder_paths.get_user_directory()
|
||||
if user_dir and os.path.isdir(user_dir):
|
||||
WHITELIST_DIR = os.path.join(user_dir, "default", "ComfyUI-Impact-Subpack")
|
||||
WHITELIST_FILE_PATH = os.path.join(WHITELIST_DIR, "model-whitelist.txt")
|
||||
logging.info(f"[Impact Pack/Subpack] Using folder_paths to determine whitelist path: {WHITELIST_FILE_PATH}")
|
||||
else:
|
||||
logging.warning(f"[Impact Pack/Subpack] folder_paths.get_user_directory() returned invalid path: {user_dir}.")
|
||||
|
||||
# --- Ensure directory exists---
|
||||
if WHITELIST_FILE_PATH: # Check if any method succeeded in setting the path
|
||||
try:
|
||||
# Crucially, create the DIRECTORY first
|
||||
# Use the WHITELIST_DIR determined by one of the methods above
|
||||
os.makedirs(WHITELIST_DIR, exist_ok=True)
|
||||
logging.info(f"[Impact Pack/Subpack] Ensured whitelist directory exists: {WHITELIST_DIR}")
|
||||
except OSError as e:
|
||||
logging.error(f"[Impact Pack/Subpack] Failed to create whitelist directory {WHITELIST_DIR}: {e}. Whitelisting may not function.")
|
||||
WHITELIST_FILE_PATH = None # Indicate failure / disable whitelisting
|
||||
except Exception as e:
|
||||
logging.error(f"[Impact Pack/Subpack] Unexpected error creating whitelist directory: {e}", exc_info=True)
|
||||
WHITELIST_FILE_PATH = None # Indicate failure / disable whitelisting
|
||||
else:
|
||||
# Handle case where path determination failed via all methods
|
||||
logging.error("[Impact Pack/Subpack] Whitelist path determination failed using all methods. Whitelisting disabled.")
|
||||
# WHITELIST_FILE_PATH is already None
|
||||
|
||||
|
||||
except Exception as e:
|
||||
# Catch errors during the whole setup process (e.g., inspect failing)
|
||||
logging.error(f"[Impact Pack/Subpack] Critical error during whitelist path setup: {e}", exc_info=True)
|
||||
WHITELIST_FILE_PATH = None # Disable whitelisting on critical setup error
|
||||
logging.error("[Impact Pack/Subpack] Whitelisting disabled due to critical setup error.")
|
||||
|
||||
|
||||
def load_whitelist(filepath):
|
||||
"""
|
||||
Loads filenames from the whitelist file.
|
||||
Attempts to create the file with instructions if it doesn't exist.
|
||||
Returns a set of approved base filenames.
|
||||
"""
|
||||
approved_files = set()
|
||||
# Check again if filepath is valid before proceeding
|
||||
if filepath is None or not isinstance(filepath, str):
|
||||
# Log was already done if None during setup, avoid duplicate messages
|
||||
# logging.error("[Impact Pack/Subpack] Whitelist file path is invalid. Whitelisting disabled.")
|
||||
return approved_files # Return empty set
|
||||
|
||||
try:
|
||||
# Try reading the existing file
|
||||
with open(filepath, 'r') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
# Store only the base filename for easier matching
|
||||
if line and not line.startswith('#'):
|
||||
approved_files.add(os.path.basename(line))
|
||||
logging.info(f"[Impact Pack/Subpack] Loaded {len(approved_files)} model(s) from whitelist: {filepath}")
|
||||
|
||||
except FileNotFoundError:
|
||||
# This block now runs only if the directory was created successfully but the file is missing
|
||||
logging.warning(f"[Impact Pack/Subpack] Model whitelist file not found at: {filepath}. ")
|
||||
logging.warning(" >> An empty whitelist file will be created.")
|
||||
logging.warning(" >> To allow unsafe loading for specific trusted legacy models (e.g., older .pt),")
|
||||
logging.warning(" >> add their base filenames (one per line) to this file.")
|
||||
try:
|
||||
# Attempt to create the file with comments since it wasn't found
|
||||
# This should now succeed because os.makedirs created the directory
|
||||
with open(filepath, 'w') as f:
|
||||
f.write("# Add base filenames of trusted models (e.g., my_old_yolo.pt) here, one per line.\n")
|
||||
f.write("# This allows loading them with `weights_only=False` if they fail safe loading\n")
|
||||
f.write("# due to errors like 'restricted getattr' in newer PyTorch versions.\n")
|
||||
f.write("# WARNING: Only add files you absolutely trust, as this bypasses a security feature.\n")
|
||||
f.write("# Prefer using .safetensors files whenever possible.\n")
|
||||
logging.info(f"[Impact Pack/Subpack] Created empty whitelist file: {filepath}")
|
||||
except Exception as create_e:
|
||||
# Log error if creating the file fails even after creating the directory
|
||||
logging.error(f"[Impact Pack/Subpack] Failed to create empty whitelist file at {filepath}: {create_e}", exc_info=True)
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"[Impact Pack/Subpack] Error loading model whitelist from {filepath}: {e}", exc_info=True)
|
||||
|
||||
return approved_files
|
||||
|
||||
# Now call the function using the dynamically determined (or None) path
|
||||
_MODEL_WHITELIST = load_whitelist(WHITELIST_FILE_PATH)
|
||||
|
||||
# ---------- End of Whitelist Management ----------
|
||||
|
||||
class NO_BBOX_DETECTOR:
|
||||
pass
|
||||
|
||||
@@ -42,7 +139,7 @@ def restricted_getattr(obj, name, *args):
|
||||
if name != "forward":
|
||||
logging.error(f"Access to potentially dangerous attribute '{obj.__module__}.{obj.__name__}.{name}' is blocked.\nIf you believe the use of this code is genuinely safe, please report it.\nhttps://github.com/ltdrdata/ComfyUI-Impact-Subpack/issues")
|
||||
raise RuntimeError(f"Access to potentially dangerous attribute '{obj.__module__}.{obj.__name__}.{name}' is blocked.")
|
||||
|
||||
|
||||
return getattr(obj, name, *args)
|
||||
|
||||
restricted_getattr.__module__ = 'builtins'
|
||||
@@ -61,69 +158,16 @@ try:
|
||||
import ultralytics.utils.loss as loss_modules
|
||||
import dill._dill
|
||||
from numpy.core.multiarray import scalar
|
||||
from numpy import dtype
|
||||
from numpy.dtypes import Float64DType
|
||||
try:
|
||||
from numpy import dtype
|
||||
from numpy.dtypes import Float64DType
|
||||
except:
|
||||
logging.error("[Impact Subpack] installed 'numpy' is outdated. Please update 'numpy>=1.26.4'")
|
||||
raise Exception("[Impact Subpack] installed 'numpy' is outdated. Please update 'numpy>=1.26.4'")
|
||||
|
||||
|
||||
torch_whitelist = []
|
||||
|
||||
# https://github.com/comfyanonymous/ComfyUI/issues/5516#issuecomment-2466152838
|
||||
def build_torch_whitelist():
|
||||
"""
|
||||
For security, only a limited set of namespaces is allowed during loading.
|
||||
|
||||
Since the same module may be identified by different namespaces depending on the model,
|
||||
some modules are additionally registered with aliases to ensure backward compatibility.
|
||||
"""
|
||||
global torch_whitelist
|
||||
|
||||
for name, obj in inspect.getmembers(modules):
|
||||
if inspect.isclass(obj) and obj.__module__.startswith("ultralytics.nn.modules"):
|
||||
aliasObj = type(name, (obj,), {})
|
||||
aliasObj.__module__ = "ultralytics.nn.modules"
|
||||
|
||||
torch_whitelist.append(obj)
|
||||
torch_whitelist.append(aliasObj)
|
||||
|
||||
for name, obj in inspect.getmembers(block_modules):
|
||||
if inspect.isclass(obj) and obj.__module__.startswith("ultralytics.nn.modules"):
|
||||
aliasObj = type(name, (obj,), {})
|
||||
aliasObj.__module__ = "ultralytics.nn.modules.block"
|
||||
|
||||
torch_whitelist.append(obj)
|
||||
torch_whitelist.append(aliasObj)
|
||||
|
||||
for name, obj in inspect.getmembers(loss_modules):
|
||||
if inspect.isclass(obj) and obj.__module__.startswith("ultralytics.utils.loss"):
|
||||
aliasObj = type(name, (obj,), {})
|
||||
aliasObj.__module__ = "ultralytics.yolo.utils.loss"
|
||||
|
||||
torch_whitelist.append(obj)
|
||||
torch_whitelist.append(aliasObj)
|
||||
|
||||
for name, obj in inspect.getmembers(torch_modules):
|
||||
if inspect.isclass(obj) and obj.__module__.startswith("torch.nn.modules"):
|
||||
torch_whitelist.append(obj)
|
||||
|
||||
aliasIterableSimpleNamespace = type("IterableSimpleNamespace", (IterableSimpleNamespace,), {})
|
||||
aliasIterableSimpleNamespace.__module__ = "ultralytics.yolo.utils"
|
||||
|
||||
aliasTaskAlignedAssigner = type("TaskAlignedAssigner", (TaskAlignedAssigner,), {})
|
||||
aliasTaskAlignedAssigner.__module__ = "ultralytics.yolo.utils.tal"
|
||||
|
||||
aliasYOLOv10DetectionModel = type("YOLOv10DetectionModel", (DetectionModel,), {})
|
||||
aliasYOLOv10DetectionModel.__module__ = "ultralytics.nn.tasks"
|
||||
aliasYOLOv10DetectionModel.__name__ = "YOLOv10DetectionModel"
|
||||
|
||||
aliasv10DetectLoss = type("v10DetectLoss", (loss_modules.E2EDetectLoss,), {})
|
||||
aliasv10DetectLoss.__name__ = "v10DetectLoss"
|
||||
aliasv10DetectLoss.__module__ = "ultralytics.utils.loss"
|
||||
|
||||
torch_whitelist += [DetectionModel, aliasYOLOv10DetectionModel, SegmentationModel, IterableSimpleNamespace,
|
||||
aliasIterableSimpleNamespace, TaskAlignedAssigner, aliasTaskAlignedAssigner, aliasv10DetectLoss,
|
||||
restricted_getattr, dill._dill._load_type, scalar, dtype, Float64DType]
|
||||
|
||||
build_torch_whitelist()
|
||||
|
||||
except Exception as e:
|
||||
logging.error(e)
|
||||
logging.error("\n!!!!!\n\n[ComfyUI-Impact-Subpack] If this error occurs, please check the following link:\n\thttps://github.com/ltdrdata/ComfyUI-Impact-Pack/blob/Main/troubleshooting/TROUBLESHOOTING.md\n\n!!!!!\n")
|
||||
@@ -131,33 +175,147 @@ except Exception as e:
|
||||
|
||||
# HOTFIX: https://github.com/ltdrdata/ComfyUI-Impact-Pack/issues/754
|
||||
# importing YOLO breaking original torch.load capabilities
|
||||
|
||||
# --- Start: REPLACE the existing torch_wrapper function ---
|
||||
|
||||
def torch_wrapper(*args, **kwargs):
|
||||
"""
|
||||
Wrapper for torch.load that attempts safe loading (weights_only=True) first.
|
||||
If a specific UnpicklingError related to disallowed globals (like 'getattr')
|
||||
occurs, it checks a user-defined whitelist (_MODEL_WHITELIST). If the file
|
||||
is whitelisted, it retries with weights_only=False. Otherwise, it blocks
|
||||
the unsafe load and raises the error.
|
||||
"""
|
||||
# Use the globally saved original torch.load reference from the top of the file
|
||||
# Check if weights_only was explicitly passed by the caller
|
||||
# Explicitly declare modification of global scope is intended
|
||||
global _MODEL_WHITELIST
|
||||
weights_only_explicit = kwargs.get('weights_only', None) # Read value without popping yet
|
||||
|
||||
# Try to get the filename being loaded (usually the first arg if it's a path)
|
||||
filename = None
|
||||
filename_arg_source = "[unknown source]"
|
||||
if args and isinstance(args[0], str):
|
||||
filename = os.path.basename(args[0]) # Get just the filename part
|
||||
filename_arg_source = args[0]
|
||||
elif 'f' in kwargs and isinstance(kwargs['f'], str):
|
||||
filename = os.path.basename(kwargs['f']) # Get just the filename part
|
||||
filename_arg_source = kwargs['f']
|
||||
# Note: filename might remain None if loading from a file-like object
|
||||
|
||||
# Check if using newer PyTorch with safe_globals attribute (indicates >= 2.6 behavior likely)
|
||||
if hasattr(torch.serialization, 'safe_globals'):
|
||||
return orig_torch_load(*args, **kwargs)
|
||||
|
||||
# Determine the effective weights_only setting for the FIRST attempt
|
||||
load_kwargs = kwargs.copy()
|
||||
|
||||
try:
|
||||
# --- Attempt 1: Default Load ---
|
||||
# Try loading with the determined weights_only setting (usually True)
|
||||
logging.debug(f"[Impact Pack/Subpack] Attempting safe load (weights_only=True) for: {filename_arg_source}")
|
||||
return orig_torch_load(*args, **load_kwargs)
|
||||
|
||||
except pickle.UnpicklingError as e:
|
||||
# --- Handle Specific Load Failure ---
|
||||
# Check if the error is the specific one caused by disallowed globals
|
||||
# like 'getattr' AND we were attempting a safe load (weights_only=True)
|
||||
# Using 'getattr' because it was the specific error reported.
|
||||
is_disallowed_global_error = 'getattr' in str(e)
|
||||
|
||||
if is_disallowed_global_error:
|
||||
# Check the whitelist
|
||||
if filename and filename in _MODEL_WHITELIST:
|
||||
# --- Fallback: Whitelisted Unsafe Load ---
|
||||
logging.warning("##############################################################################")
|
||||
logging.warning(f"[Impact Pack/Subpack] WARNING: Safe load failed for '{filename}' (Reason: {e}).")
|
||||
logging.warning(f" >> FILE IS IN THE WHITELIST: {WHITELIST_FILE_PATH}")
|
||||
logging.warning(" >> This model likely uses legacy Python features blocked by default for security.")
|
||||
logging.warning(" >> RETRYING WITH 'weights_only=False' because it's whitelisted.")
|
||||
logging.warning(" >> SECURITY RISK: Ensure you added this file to the whitelist consciously")
|
||||
logging.warning(f" >> and trust its source: {filename_arg_source}")
|
||||
logging.warning(" >> Prefer using .safetensors files whenever available.")
|
||||
logging.warning("##############################################################################")
|
||||
|
||||
retry_kwargs = kwargs.copy()
|
||||
retry_kwargs['weights_only'] = False
|
||||
# Call the original function again, now unsafely (because whitelisted)
|
||||
return orig_torch_load(*args, **retry_kwargs)
|
||||
|
||||
else:
|
||||
# --- File not in current whitelist, try reloading ---
|
||||
logging.warning(f"[Impact Pack/Subpack] File '{filename}' not found in current whitelist cache.")
|
||||
whitelist_path_msg = WHITELIST_FILE_PATH if WHITELIST_FILE_PATH else "[Path not determined]"
|
||||
logging.info(f"[Impact Pack/Subpack] Attempting to reload whitelist from: {whitelist_path_msg}")
|
||||
try:
|
||||
# Reload the whitelist from the file
|
||||
_MODEL_WHITELIST = load_whitelist(WHITELIST_FILE_PATH)
|
||||
logging.info(f"[Impact Pack/Subpack] Whitelist reloaded. Now contains {len(_MODEL_WHITELIST)} entries.")
|
||||
|
||||
# --- Re-check Whitelist After Reload ---
|
||||
if filename and filename in _MODEL_WHITELIST:
|
||||
logging.warning("##############################################################################")
|
||||
logging.warning(f"[Impact Pack/Subpack] SUCCESS: File '{filename}' FOUND in reloaded whitelist.")
|
||||
logging.warning(" >> Proceeding with whitelisted unsafe load (weights_only=False).")
|
||||
logging.warning(f" >> Ensure you recently added this file to: {whitelist_path_msg}")
|
||||
logging.warning(" >> SECURITY RISK: Ensure you trust its source.")
|
||||
logging.warning("##############################################################################")
|
||||
retry_kwargs = kwargs.copy()
|
||||
retry_kwargs['weights_only'] = False
|
||||
return orig_torch_load(*args, **retry_kwargs)
|
||||
else:
|
||||
# File still not found after reload, proceed with blocking
|
||||
logging.error("[Impact Pack/Subpack] File still not found in whitelist after reload.")
|
||||
# Fall through to the original blocking logic below
|
||||
|
||||
except Exception as reload_e:
|
||||
logging.error(f"[Impact Pack/Subpack] Error occurred during whitelist reload attempt: {reload_e}", exc_info=True)
|
||||
# Fall through to the original blocking logic below if reload fails
|
||||
|
||||
# --- Blocked: Not Whitelisted (Original Logic - runs if reload failed or file still not found) ---
|
||||
logging.error("##############################################################################")
|
||||
logging.error(f"[Impact Pack/Subpack] ERROR: Safe load failed for '{filename_arg_source}' (Reason: {e}).")
|
||||
logging.error(" >> This model likely uses legacy Python features blocked by default for security.")
|
||||
# Updated log message here:
|
||||
logging.error(f" >> UNSAFE LOAD BLOCKED because the file ('{filename or 'unknown'}') is NOT in the whitelist (even after reload attempt).")
|
||||
logging.error(f" >> Whitelist path: {whitelist_path_msg}")
|
||||
if filename:
|
||||
logging.error(" >> To allow loading this specific file (IF YOU TRUST IT), ensure its base name")
|
||||
logging.error(f" >> ('{filename}') is correctly added to the whitelist file (one name per line) and saved.")
|
||||
else:
|
||||
logging.error(" >> Cannot determine filename to check against whitelist.")
|
||||
logging.error(" >> SECURITY RISK: Only whitelist files from sources you absolutely trust.")
|
||||
logging.error(" >> Prefer using .safetensors files whenever available.")
|
||||
logging.error("##############################################################################")
|
||||
raise e # Re-raise the original security-related error
|
||||
|
||||
else:
|
||||
# If it's a different UnpicklingError, re-raise it. Don't attempt unsafe load.
|
||||
logging.error(f"[Impact Pack/Subpack] UnpicklingError during safe load (not 'getattr' related): {e}. Re-raising.")
|
||||
raise e # Re-raise other UnpicklingErrors
|
||||
|
||||
else:
|
||||
logging.warning("[Impact Subpack] Your torch version is outdated, and security features cannot be applied properly.")
|
||||
return orig_torch_load(*args, **kwargs, weights_only=False)
|
||||
# --- Handle Older PyTorch Versions (no safe_globals) ---
|
||||
# Behavior here respects the caller's explicit request or defaults to False
|
||||
load_kwargs = kwargs.copy()
|
||||
effective_weights_only = weights_only_explicit if weights_only_explicit is not None else False # Default False for old torch
|
||||
load_kwargs['weights_only'] = effective_weights_only
|
||||
|
||||
if not effective_weights_only:
|
||||
logging.warning(f"[Impact Pack/Subpack] Older PyTorch version detected. Proceeding with potentially unsafe load (weights_only=False) for: {filename_arg_source}")
|
||||
else:
|
||||
logging.debug(f"[Impact Pack/Subpack] Older PyTorch version detected. Proceeding with explicit weights_only=True for: {filename_arg_source}")
|
||||
|
||||
# Call the original torch.load directly with the determined settings for older PyTorch
|
||||
return orig_torch_load(*args, **load_kwargs)
|
||||
|
||||
# --- End: Replacement block for the torch_wrapper function ---
|
||||
|
||||
torch.load = torch_wrapper
|
||||
|
||||
|
||||
def load_yolo(model_path: str):
|
||||
# https://github.com/comfyanonymous/ComfyUI/issues/5516#issuecomment-2466152838
|
||||
if hasattr(torch.serialization, 'safe_globals'):
|
||||
with torch.serialization.safe_globals(torch_whitelist):
|
||||
try:
|
||||
return YOLO(model_path)
|
||||
except ModuleNotFoundError:
|
||||
# https://github.com/ultralytics/ultralytics/issues/3856
|
||||
YOLO("yolov8n.pt")
|
||||
return YOLO(model_path)
|
||||
else:
|
||||
try:
|
||||
return YOLO(model_path)
|
||||
except ModuleNotFoundError:
|
||||
YOLO("yolov8n.pt")
|
||||
return YOLO(model_path)
|
||||
|
||||
return YOLO(model_path)
|
||||
|
||||
|
||||
def inference_bbox(
|
||||
model,
|
||||
@@ -366,4 +524,4 @@ class UltraSegmDetector:
|
||||
return utils.combine_masks(segmasks)
|
||||
|
||||
def setAux(self, x):
|
||||
pass
|
||||
pass
|
||||
|
||||
@@ -9,8 +9,8 @@ def update_model_paths(model_path):
|
||||
utils.add_folder_path_and_extensions("ultralytics_bbox", [os.path.join(model_path, "ultralytics", "bbox")], folder_paths.supported_pt_extensions)
|
||||
utils.add_folder_path_and_extensions("ultralytics_segm", [os.path.join(model_path, "ultralytics", "segm")], folder_paths.supported_pt_extensions)
|
||||
utils.add_folder_path_and_extensions("ultralytics", [os.path.join(model_path, "ultralytics")], folder_paths.supported_pt_extensions)
|
||||
logging.info(f'[Impact Subpack] ultralytics_bbox: {os.path.join(model_path, "ultralytics", "bbox")}')
|
||||
logging.info(f'[Impact Subpack] ultralytics_segm: {os.path.join(model_path, "ultralytics", "segm")}')
|
||||
logging.info(f'[Impact Subpack] ultralytics_bbox: {", ".join(folder_paths.folder_names_and_paths["ultralytics_bbox"][0])}')
|
||||
logging.info(f'[Impact Subpack] ultralytics_segm: {", ".join(folder_paths.folder_names_and_paths["ultralytics_segm"][0])}')
|
||||
|
||||
update_model_paths(folder_paths.models_dir)
|
||||
if 'download_model_base' in folder_paths.folder_names_and_paths:
|
||||
@@ -30,6 +30,28 @@ class UltralyticsDetectorProvider:
|
||||
|
||||
def doit(self, model_name):
|
||||
model_path = folder_paths.get_full_path("ultralytics", model_name)
|
||||
|
||||
if model_path is None:
|
||||
if model_name.startswith('bbox/'):
|
||||
model_path = folder_paths.get_full_path("ultralytics_bbox", model_name[5:])
|
||||
elif model_name.startswith('segm/'):
|
||||
model_path = folder_paths.get_full_path("ultralytics_segm", model_name[5:])
|
||||
|
||||
if model_path is None:
|
||||
logging.error(f"[Impact Subpack] model file '{model_name}' is not found in one of the following directories:")
|
||||
|
||||
cands = []
|
||||
cands.extend(folder_paths.get_folder_paths("ultralytics"))
|
||||
if model_name.startswith('bbox/'):
|
||||
cands.extend(folder_paths.get_folder_paths("ultralytics_bbox"))
|
||||
elif model_name.startswith('segm/'):
|
||||
cands.extend(folder_paths.get_folder_paths("ultralytics_segm"))
|
||||
|
||||
formatted_cands = "\n\t".join(cands)
|
||||
logging.error(f'\t{formatted_cands}\n')
|
||||
|
||||
raise ValueError(f"[Impact Subpack] model file '{model_name}' is not found.")
|
||||
|
||||
model = subcore.load_yolo(model_path)
|
||||
|
||||
if model_name.startswith("bbox"):
|
||||
|
||||
+1
-1
@@ -133,7 +133,7 @@ def crop_ndarray2(npimg, crop_region):
|
||||
|
||||
return cropped
|
||||
|
||||
|
||||
|
||||
def crop_ndarray4(npimg, crop_region):
|
||||
x1 = crop_region[0]
|
||||
y1 = crop_region[1]
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
[project]
|
||||
name = "comfyui-impact-subpack"
|
||||
description = "This node pack provides nodes that complement the Impact Pack, such as the UltralyticsDetectorProvider."
|
||||
version = "1.2.2"
|
||||
version = "1.3.5"
|
||||
license = { file = "LICENSE.txt" }
|
||||
dependencies = ["matplotlib", "ultralytics==8.3.40"]
|
||||
dependencies = ["matplotlib", "ultralytics"]
|
||||
|
||||
[project.urls]
|
||||
Repository = "https://github.com/ltdrdata/ComfyUI-Impact-Subpack"
|
||||
|
||||
+4
-3
@@ -1,4 +1,5 @@
|
||||
matplotlib
|
||||
ultralytics==8.3.40
|
||||
numpy<2
|
||||
opencv-python-headless
|
||||
ultralytics>=8.3.162
|
||||
numpy
|
||||
opencv-python-headless
|
||||
dill
|
||||
Reference in New Issue
Block a user