Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a12c5b19dc | ||
|
|
ea86b52e0f | ||
|
|
02a3518aa7 | ||
|
|
3746860aa4 | ||
|
|
f92ebeb653 | ||
|
|
f6776fded7 | ||
|
|
7b1233edc0 | ||
|
|
b3a0ac8cf5 | ||
|
|
de7e09db0f | ||
|
|
60b310dd7f | ||
|
|
4351dc4272 | ||
|
|
5f68562b6d | ||
|
|
b9f8683da5 | ||
|
|
78c8844f26 | ||
|
|
b01880c37f | ||
|
|
619eb16a1e | ||
|
|
4dab1f1b0a |
@@ -3,3 +3,4 @@ __pycache__/
|
||||
.vscode/
|
||||
example
|
||||
input
|
||||
*.dll
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<img src="https://github.com/Gourieff/Assets/raw/main/sd-webui-reactor/ReActor_logo_NEW_EN.png?raw=true" alt="logo" width="180px"/>
|
||||
|
||||

|
||||

|
||||
|
||||
<a href="https://boosty.to/artgourieff" target="_blank">
|
||||
<img src="https://lovemet.ru/img/boosty.jpg" width="108" alt="Support Me on Boosty"/>
|
||||
@@ -46,6 +46,14 @@
|
||||
|
||||
## What's new in the latest update
|
||||
|
||||
### 0.7.1 <sub><sup>BETA1</sup></sub>
|
||||
|
||||
- **New `DLSS5 Frame Enhancer` node**. NVIDIA's latest DLSS 5 technology for enhancing image quality (both overall frame or faces by mask). <br><u>See [Installation Instructions](https://github.com/Gourieff/ComfyUI-ReActor/blob/main/r_dlssnr/dll/README.md).</u><br><pre>The integration operates in an isolated Host mode, fully eliminating conflicts with ComfyUI's CUDA context.<br>Huge thanks to the author of the [Merserk/dlss5-visual-enhancer](https://github.com/Merserk/dlss5-visual-enhancer) project for the C++ wrapper (neuroframe_engine.dll and neuroframe_caller.dll), which formed the base of the computational bridge for this node.<br>Also thanks Gemini 3.1 Pro (via [Google Gemini](https://gemini.google.com/app)) for the contribution.</pre><u>Requirements:</u><br>
|
||||
-- Windows 10/11<br>
|
||||
-- NVIDIA display driver >= 616.x<br>
|
||||
-- NVIDIA RTX 40/50-series GPU<br>
|
||||
(compatibility with older RTX series is unconfirmed)
|
||||
|
||||
### 0.7.0
|
||||
|
||||
- 💥 **Big Update! ☢ New ReActor Core!**<br>✅ No `Insightface` required!<br>✅ No `C++ Build Tools` required!<br>✅ Instalation process is much easier now!<br>✅ `Numpy 2.x` friendly as well as `1.x`!<br>⚠ <u>A swap result is slightly different now</u>. Hard to say if it’s "better" or "worse" — it’s just a bit different. But if we look at the numbers (cosine similarity of face embeddings), the accuracy is actually a little higher than with Insightface.<br>More info you can find here: https://t.me/reactor_faceswap/55
|
||||
@@ -295,6 +303,7 @@ List of Nodes:
|
||||
- ReActorImageDublicator (Dublicate one Image to Images List)
|
||||
- ImageRGBA2RGB (Convert RGBA to RGB)
|
||||
- ReActorUnload (Unload ReActor models from VRAM)
|
||||
- DLSS5FrameEnhancer (Enhance frame quality with NVIDIA DLSS 5)
|
||||
|
||||
Connect all required slots and run the query.
|
||||
|
||||
|
||||
+10
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
<img src="https://github.com/Gourieff/Assets/raw/main/sd-webui-reactor/ReActor_logo_NEW_RU.png?raw=true" alt="logo" width="180px"/>
|
||||
|
||||

|
||||

|
||||
|
||||
<a href="https://boosty.to/artgourieff" target="_blank">
|
||||
<img src="https://lovemet.ru/img/boosty.jpg" width="108" alt="Поддержать проект на Boosty"/>
|
||||
@@ -46,6 +46,14 @@
|
||||
|
||||
## Что нового в последнем обновлении
|
||||
|
||||
### 0.7.1 <sub><sup>BETA1</sup></sub>
|
||||
|
||||
- **Новый узел `DLSS5 Frame Enhancer`**. Новейшая технология DLSS 5 от NVIDIA для улучшения качества изображения (кадра целиком или лиц по маске).<br><u>Следуйте [инструкции по установке](https://github.com/Gourieff/ComfyUI-ReActor/blob/main/r_dlssnr/dll/README.md).</u><br><pre>Интеграция работает в изолированном Host-режиме, что полностью исключает конфликты с CUDA-контекстом ComfyUI.<br>Огромная благодарность автору проекта [Merserk/dlss5-visual-enhancer](https://github.com/Merserk/dlss5-visual-enhancer) за C++ обертку (neuroframe_engine.dll и neuroframe_caller.dll), которая легла в основу вычислительного моста для данного узла.<br>Также благодарность Gemini 3.1 Pro (через [Google Gemini](https://gemini.google.com/app)) за ассистирование и помощь.</pre><u>Требования:</u><br>
|
||||
-- Windows 10/11<br>
|
||||
-- NVIDIA display driver >= 616.x<br>
|
||||
-- NVIDIA RTX 40/50-series GPU<br>
|
||||
(совместимость с более старыми сериями RTX не подтверждена)
|
||||
|
||||
### 0.7.0
|
||||
|
||||
- 💥 **Важное обновление! ☢ Новое ядро РеАктора!**<br>✅ Библиотека `Insightface` больше не требуется!<br>✅ `C++ Build Tools` больше не требуются!<br>✅ Более простой процесс установки!<br>✅ Поддержка `Numpy 2.x` и `1.x`!<br>⚠ <u>Результат Свапа теперь слегка отличается</u>. Сложно сказать, хуже или лучше — результат просто чуть-чуть другой. По показателям схожести (оценка косинусного сходства векторов эмбеддингов лиц) результат стал немного лучше (хоть и незначительно), чем с Insightface.<br>Подробнее здесь: https://t.me/reactor_faceswap/55
|
||||
@@ -297,6 +305,7 @@ Basic workflow [💾](https://github.com/Gourieff/Assets/blob/main/comfyui-react
|
||||
- ReActorImageDublicator (Сделать из одного изображения несколько дубликатов)
|
||||
- ImageRGBA2RGB (Конвертировать RGBA в RGB)
|
||||
- ReActorUnload (Выгрузить модели РеАктора из VRAM)
|
||||
- DLSS5FrameEnhancer (Улучшение детализации кадра с NVIDIA DLSS 5)
|
||||
|
||||
Соедините все необходимые слоты (slots) и запустите очередь (query).
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ import scripts.r_masking.segs as masking_segs
|
||||
|
||||
import scripts.reactor_sfw as sfw
|
||||
|
||||
from r_dlssnr.dlss5_node import DLSS5FrameEnhancer
|
||||
|
||||
|
||||
models_dir = folder_paths.models_dir
|
||||
REACTOR_MODELS_PATH = os.path.join(models_dir, "reactor")
|
||||
@@ -1744,6 +1746,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
"ReActorImageDublicator": ImageDublicator,
|
||||
"ImageRGBA2RGB": ImageRGBA2RGB,
|
||||
"ReActorUnload": ReActorUnload,
|
||||
"DLSS5FrameEnhancer": DLSS5FrameEnhancer,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
@@ -1766,4 +1769,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"ReActorImageDublicator": "Image Dublicator (List) 🌌 ReActor",
|
||||
"ImageRGBA2RGB": "Convert RGBA to RGB 🌌 ReActor",
|
||||
"ReActorUnload": "Unload ReActor Models 🌌 ReActor",
|
||||
"DLSS5FrameEnhancer": "DLSS5 Frame Enhancer 🌌 ReActor",
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "comfyui-reactor"
|
||||
description = "(SFW-Friendly) The Fast and Simple Face Swap Extension Node for ComfyUI, based on ReActor SD-WebUI Face Swap Extension"
|
||||
version = "0.7.0"
|
||||
description = "(SFW-Friendly) The Fast and Simple Face Swap Extension for ComfyUI"
|
||||
version = "0.7.1-b3"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = ["onnx>=1.14.0", "opencv-python>=4.7.0.72", "numpy", "segment_anything", "albumentations>=1.4.16", "ultralytics"]
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
## Third-party DLLs
|
||||
|
||||
1. Download [neuroframe_dlls.zip](https://huggingface.co/datasets/Gourieff/ReActor/blob/main/DLSSNR/neuroframe_dlls.zip) and place `neuroframe_caller.dll`\* and `neuroframe_engine.dll`* here (in `r_dlssnr/dll`)
|
||||
2. Place your `nvngx_dlssnr.dll`** here (in `r_dlssnr/dll`)
|
||||
|
||||
<sub>* Author [Merserk](https://github.com/Merserk), [LICENSE](https://huggingface.co/datasets/Gourieff/ReActor/blob/main/DLSSNR/LICENSE-Merserk.txt)
|
||||
<br>
|
||||
** Public distribution of this file is prohibited by NVIDIA, [LICENSE](https://huggingface.co/datasets/Gourieff/ReActor/blob/main/DLSSNR/LICENSE-NVIDIA-DLSS.txt)</sub>
|
||||
@@ -0,0 +1,147 @@
|
||||
import ctypes
|
||||
import threading
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
import numpy as np
|
||||
|
||||
# --- КОНСТАНТЫ ---
|
||||
BRIDGE_ABI_VERSION = 6
|
||||
MEMORY_HOST = 0
|
||||
MEMORY_CUDA = 1
|
||||
MEMORY_NONE = 2
|
||||
|
||||
class NeuralBridgeError(Exception):
|
||||
pass
|
||||
|
||||
# --- C-СТРУКТУРЫ ДЛЯ ВЗАИМОДЕЙСТВИЯ С DLL ---
|
||||
|
||||
class RenderParameters(ctypes.Structure):
|
||||
_fields_ = [
|
||||
("struct_size", ctypes.c_uint32),
|
||||
("abi_version", ctypes.c_uint32),
|
||||
("style", ctypes.c_int32),
|
||||
("intensity", ctypes.c_float),
|
||||
("tone", ctypes.c_float),
|
||||
("structure", ctypes.c_float),
|
||||
("skin", ctypes.c_float),
|
||||
("automask", ctypes.c_int32),
|
||||
("reset", ctypes.c_int32),
|
||||
("color_strength", ctypes.c_float),
|
||||
("tone_preservation", ctypes.c_float),
|
||||
("mask_memory_type", ctypes.c_uint32),
|
||||
("mask_width", ctypes.c_uint32),
|
||||
("mask_height", ctypes.c_uint32),
|
||||
("mask_stride", ctypes.c_uint32),
|
||||
("mask_plane", ctypes.c_uint64), # Из-за uint64 здесь будет 4 байта системного отступа
|
||||
("face_skin_protection", ctypes.c_float),
|
||||
("grain_preservation", ctypes.c_float),
|
||||
("nr_passes", ctypes.c_int32),
|
||||
("shimmer_suppression", ctypes.c_float),
|
||||
("prefer_nvof", ctypes.c_int32),
|
||||
]
|
||||
|
||||
|
||||
class DLSSStandaloneManager:
|
||||
def __init__(self, dll_dir: str):
|
||||
self._lock = threading.RLock()
|
||||
self._library = None
|
||||
self.dll_dir = dll_dir
|
||||
|
||||
def initialize(self, ordinal: int):
|
||||
with self._lock:
|
||||
if self._library is not None:
|
||||
return True
|
||||
|
||||
import os
|
||||
|
||||
if hasattr(os, 'add_dll_directory'):
|
||||
os.add_dll_directory(self.dll_dir)
|
||||
|
||||
engine_path = os.path.join(self.dll_dir, "neuroframe_engine.dll")
|
||||
if not os.path.exists(engine_path):
|
||||
raise NeuralBridgeError(f"Missing DLL: {engine_path}")
|
||||
|
||||
loader = getattr(ctypes, "WinDLL", ctypes.CDLL)
|
||||
try:
|
||||
self._library = loader(engine_path)
|
||||
except OSError as exc:
|
||||
raise NeuralBridgeError(f"DLL load failed: {exc}")
|
||||
|
||||
# Сигнатура инициализации
|
||||
self._library.dlss5nr_init.argtypes = [
|
||||
ctypes.c_int, ctypes.c_wchar_p, ctypes.c_char_p, ctypes.c_int
|
||||
]
|
||||
self._library.dlss5nr_init.restype = ctypes.c_int
|
||||
|
||||
# Сигнатура HOST-рендера (process_v6 вместо process_cuda_v6)
|
||||
c_float_p = ctypes.POINTER(ctypes.c_float)
|
||||
self._library.dlss5nr_process_v6.argtypes = [
|
||||
c_float_p, c_float_p, ctypes.c_int, ctypes.c_int,
|
||||
ctypes.POINTER(RenderParameters), ctypes.c_char_p, ctypes.c_int
|
||||
]
|
||||
self._library.dlss5nr_process_v6.restype = ctypes.c_int
|
||||
|
||||
try:
|
||||
self._library.dlss5nr_frame_abi_version.argtypes = []
|
||||
self._library.dlss5nr_frame_abi_version.restype = ctypes.c_uint32
|
||||
self.actual_abi = self._library.dlss5nr_frame_abi_version()
|
||||
except Exception:
|
||||
self.actual_abi = BRIDGE_ABI_VERSION
|
||||
|
||||
error = ctypes.create_string_buffer(4096)
|
||||
ok = self._library.dlss5nr_init(ordinal, self.dll_dir, error, len(error))
|
||||
|
||||
if not ok:
|
||||
err_msg = error.value.decode('utf-8', errors='ignore')
|
||||
raise NeuralBridgeError(f"Bridge initialization failed: {err_msg}")
|
||||
|
||||
return True
|
||||
|
||||
def process_host(self, source: np.ndarray, destination: np.ndarray, settings: dict, reset: bool, mask: np.ndarray = None):
|
||||
with self._lock:
|
||||
error = ctypes.create_string_buffer(4096)
|
||||
|
||||
params = RenderParameters()
|
||||
params.struct_size = ctypes.sizeof(RenderParameters)
|
||||
params.abi_version = getattr(self, "actual_abi", BRIDGE_ABI_VERSION)
|
||||
|
||||
params.style = int(settings.get("style"))
|
||||
params.intensity = float(settings.get("intensity"))
|
||||
params.tone = float(settings.get("local_tone"))
|
||||
params.structure = float(settings.get("local_structure"))
|
||||
params.skin = float(settings.get("skin_structure"))
|
||||
params.automask = int(bool(settings.get("auto_mask")))
|
||||
params.reset = int(bool(reset))
|
||||
params.color_strength = float(settings.get("color_strength"))
|
||||
params.tone_preservation = float(settings.get("tone_preservation"))
|
||||
params.face_skin_protection = float(settings.get("face_skin_protection"))
|
||||
params.grain_preservation = float(settings.get("grain_preservation"))
|
||||
params.nr_passes = int(settings.get("nr_passes"))
|
||||
params.shimmer_suppression = float(settings.get("shimmer_suppression", 0.0))
|
||||
params.prefer_nvof = int(bool(settings.get("prefer_nvof", False)))
|
||||
|
||||
# Обработка маски через HOST память
|
||||
params.mask_memory_type = MEMORY_NONE
|
||||
if mask is not None:
|
||||
params.mask_memory_type = MEMORY_HOST
|
||||
params.mask_width = int(mask.shape[1])
|
||||
params.mask_height = int(mask.shape[0])
|
||||
params.mask_stride = int(mask.strides[0])
|
||||
params.mask_plane = int(mask.ctypes.data) # Передаем указатель RAM
|
||||
|
||||
c_float_p = ctypes.POINTER(ctypes.c_float)
|
||||
|
||||
# Вызываем HOST функцию (DLL сама разберется с видеокартой)
|
||||
ok = self._library.dlss5nr_process_v6(
|
||||
source.ctypes.data_as(c_float_p),
|
||||
destination.ctypes.data_as(c_float_p),
|
||||
source.shape[1],
|
||||
source.shape[0],
|
||||
ctypes.byref(params),
|
||||
error,
|
||||
len(error)
|
||||
)
|
||||
|
||||
if not ok:
|
||||
err_msg = error.value.decode('utf-8', errors='ignore')
|
||||
raise NeuralBridgeError(f"DLSS-5 process failed: {err_msg}")
|
||||
@@ -0,0 +1,113 @@
|
||||
import torch
|
||||
import numpy as np
|
||||
import os
|
||||
import comfy.model_management as model_management
|
||||
from scripts.reactor_logger import logger
|
||||
from .dlss5_core import DLSSStandaloneManager
|
||||
from r_modules.shared import state
|
||||
from reactor_utils import (
|
||||
batch_tensor_to_pil,
|
||||
progress_bar,
|
||||
progress_bar_reset
|
||||
)
|
||||
|
||||
class DLSS5FrameEnhancer:
|
||||
def __init__(self):
|
||||
self.device = model_management.get_torch_device()
|
||||
self.manager = None
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"image": ("IMAGE",),
|
||||
"style": (["Default", "Nature", "Cinematic"],),
|
||||
"intensity": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.05, "tooltip": "0..2, def: 1.0"}),
|
||||
"local_tone": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 2.0, "step": 0.05, "tooltip": "0..2, def: 0.0"}),
|
||||
"local_structure": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 2.0, "step": 0.05, "tooltip": "0..2, def: 1.0"}),
|
||||
"skin_structure": ("FLOAT", {"default": 0.5, "min": -1.0, "max": 2.0, "step": 0.05, "tooltip": "-1..2, def: 0.5"}),
|
||||
"color_strength": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.05, "tooltip": "0..1, def: 0.5"}),
|
||||
"tone_preservation": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.05, "tooltip": "0..1, def: 0.5"}),
|
||||
"face_skin_protection": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.05, "tooltip": "0..1, def: 0.0"}),
|
||||
"grain_preservation": ("FLOAT", {"default": 0.0, "min": 0.0, "max": 1.0, "step": 0.05, "tooltip": "0..1, def: 0.0"}),
|
||||
"nr_passes": ("INT", {"default": 1, "min": 1, "max": 4, "tooltip": "0..4, def: 1"}),
|
||||
"auto_mask": ("BOOLEAN", {"default": False, "label_off": "OFF", "label_on": "ON", "tooltip": "AI Automatic masking of complex areas to prevent over-detailing"}),
|
||||
},
|
||||
"optional": {
|
||||
"mask": ("MASK",),
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_TYPES = ("IMAGE",)
|
||||
RETURN_NAMES = ("enhanced_image",)
|
||||
FUNCTION = "enhance"
|
||||
CATEGORY = "🌌 ReActor"
|
||||
DESCRIPTION = (
|
||||
"Requirements:\n"
|
||||
"- NVIDIA display driver >= 616.x\n"
|
||||
"- NVIDIA RTX 40/50-series GPU\n"
|
||||
"(compatibility with older RTX series is unconfirmed)\n"
|
||||
"- DLLs: neuroframe_caller.dll, neuroframe_engine.dll, nvngx_dlssnr.dll\nin custom_nodes/ComfyUI-ReActor/r_dlssnr/dll\nor custom_nodes/comfyui-reactor-node/r_dlssnr/dll\n"
|
||||
"(see README.md in dll folder for instructions)"
|
||||
)
|
||||
|
||||
def load_bridge(self):
|
||||
if self.manager is None:
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
dll_dir = os.path.join(current_dir, "dll")
|
||||
self.manager = DLSSStandaloneManager(dll_dir)
|
||||
ordinal = getattr(self.device, 'index', 0) if self.device.index is not None else 0
|
||||
self.manager.initialize(ordinal)
|
||||
logger.status(f"DLSS-5 Bridge initialized on GPU {ordinal}")
|
||||
|
||||
def enhance(self, image, style, intensity, local_tone, local_structure,
|
||||
skin_structure, color_strength, tone_preservation,
|
||||
face_skin_protection, grain_preservation, nr_passes, auto_mask, mask=None):
|
||||
|
||||
self.load_bridge()
|
||||
|
||||
style_map = {"Default": 0, "Nature": 1, "Cinematic": 2}
|
||||
settings = {
|
||||
"style": style_map[style], "intensity": intensity, "local_tone": local_tone,
|
||||
"local_structure": local_structure, "skin_structure": skin_structure,
|
||||
"color_strength": color_strength, "tone_preservation": tone_preservation,
|
||||
"face_skin_protection": face_skin_protection, "grain_preservation": grain_preservation,
|
||||
"nr_passes": nr_passes, "auto_mask": auto_mask,
|
||||
"shimmer_suppression": 0.0, "prefer_nvof": False
|
||||
}
|
||||
|
||||
enhanced_batch = []
|
||||
|
||||
pil_images = batch_tensor_to_pil(image)
|
||||
pbar = progress_bar(len(pil_images))
|
||||
|
||||
for i in range(len(image)):
|
||||
|
||||
if state.interrupted or model_management.processing_interrupted():
|
||||
logger.status("Interrupted by User")
|
||||
break
|
||||
|
||||
img_np = np.ascontiguousarray(image[i].cpu().numpy().astype(np.float32))
|
||||
dest_np = np.ascontiguousarray(np.zeros_like(img_np))
|
||||
|
||||
mask_np = None
|
||||
if mask is not None:
|
||||
mask_np = np.ascontiguousarray(mask[i].cpu().numpy().astype(np.float32))
|
||||
|
||||
# Вызываем Host-обработчик (без CUDA конфликтов)
|
||||
self.manager.process_host(
|
||||
source=img_np,
|
||||
destination=dest_np,
|
||||
settings=settings,
|
||||
reset=True,
|
||||
mask=mask_np
|
||||
)
|
||||
|
||||
out_tensor = torch.from_numpy(dest_np).to(self.device)
|
||||
enhanced_batch.append(out_tensor)
|
||||
|
||||
pbar.update(1)
|
||||
|
||||
progress_bar_reset(pbar)
|
||||
|
||||
return (torch.stack(enhanced_batch),)
|
||||
@@ -1,5 +1,5 @@
|
||||
app_title = "ReActor Node for ComfyUI"
|
||||
version_flag = "v0.7.0"
|
||||
version_flag = "v0.7.1-b3"
|
||||
|
||||
COLORS = {
|
||||
"CYAN": "\033[0;36m", # CYAN
|
||||
|
||||
Reference in New Issue
Block a user