Update negative_rejection_steering/scripts/negative_rejection_steering_script.py
Browse files
negative_rejection_steering/scripts/negative_rejection_steering_script.py
CHANGED
|
@@ -66,15 +66,73 @@ def calc_nrs(x_orig, cond, uncond, sigma, skew, stretch, squash):
|
|
| 66 |
return (x_div - (x_orig - x_final)) * (sig_root / sig_tens)
|
| 67 |
|
| 68 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
# ==============================================================================
|
| 70 |
# ЧАСТЬ 2: Перехват управления (Hooking)
|
| 71 |
# ==============================================================================
|
| 72 |
|
| 73 |
-
# Хук 1: Сохраняем Sigma
|
| 74 |
def hook_cfg_denoiser_params(params):
|
| 75 |
if hasattr(params.denoiser, 'p') and getattr(params.denoiser.p, '_nrs_enabled', False):
|
| 76 |
params.denoiser.p._nrs_current_sigma = params.sigma
|
| 77 |
params.denoiser.p._nrs_current_x_in = params.x
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
script_callbacks.on_cfg_denoiser(hook_cfg_denoiser_params)
|
| 80 |
|
|
@@ -82,7 +140,7 @@ script_callbacks.on_cfg_denoiser(hook_cfg_denoiser_params)
|
|
| 82 |
if not hasattr(sd_samplers_cfg_denoiser.CFGDenoiser, 'original_combine_denoised_nrs_backup'):
|
| 83 |
sd_samplers_cfg_denoiser.CFGDenoiser.original_combine_denoised_nrs_backup = sd_samplers_cfg_denoiser.CFGDenoiser.combine_denoised
|
| 84 |
|
| 85 |
-
# Хук 2: Подменная функция
|
| 86 |
def hijacked_combine_denoised(self, x_out, conds_list, uncond, cond_scale):
|
| 87 |
# Проверка активности NRS
|
| 88 |
if not getattr(self, 'p', None) or not getattr(self.p, '_nrs_enabled', False):
|
|
@@ -92,8 +150,77 @@ def hijacked_combine_denoised(self, x_out, conds_list, uncond, cond_scale):
|
|
| 92 |
return sd_samplers_cfg_denoiser.CFGDenoiser.original_combine_denoised_nrs_backup(self, x_out, conds_list, uncond, cond_scale)
|
| 93 |
|
| 94 |
try:
|
| 95 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
denoised_uncond = x_out[-uncond.shape[0]:]
|
| 98 |
denoised = torch.clone(denoised_uncond)
|
| 99 |
|
|
@@ -132,11 +259,11 @@ def hijacked_combine_denoised(self, x_out, conds_list, uncond, cond_scale):
|
|
| 132 |
|
| 133 |
|
| 134 |
# ==============================================================================
|
| 135 |
-
# ЧАСТЬ 3: Интерфейс (UI) с
|
| 136 |
# ==============================================================================
|
| 137 |
class NRSScript(scripts.Script):
|
| 138 |
def title(self):
|
| 139 |
-
return "Negative Rejection Steering"
|
| 140 |
|
| 141 |
def show(self, is_img2img):
|
| 142 |
return scripts.AlwaysVisible
|
|
@@ -164,10 +291,15 @@ class NRSScript(scripts.Script):
|
|
| 164 |
1. **Skew** ≈ Половина вашего обычного CFG (например, **3.0** - **4.0**).
|
| 165 |
2. **Stretch** ≈ Ваш обычный CFG (например, **6.0** - **7.0**).
|
| 166 |
3. **Squash** ≈ Оставьте **0.0** для начала.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
""")
|
| 168 |
|
| 169 |
-
# ---
|
| 170 |
-
gr.HTML("<div style='margin-bottom: 0.5em; opacity: 0.8; font-size: 0.9em; border-bottom: 1px solid #444;'>
|
| 171 |
|
| 172 |
with gr.Row():
|
| 173 |
skew = gr.Slider(
|
|
@@ -187,14 +319,249 @@ class NRSScript(scripts.Script):
|
|
| 187 |
info="0.0 = Макс. эффект. 1.0 = Ослабление (больше деталей, меньше контраста)."
|
| 188 |
)
|
| 189 |
|
| 190 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
|
| 192 |
-
def process(self, p, enabled, skew, stretch, squash
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 193 |
p._nrs_enabled = enabled
|
| 194 |
p._nrs_params = (skew, stretch, squash)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
|
| 196 |
if enabled:
|
| 197 |
sd_samplers_cfg_denoiser.CFGDenoiser.combine_denoised = hijacked_combine_denoised
|
|
|
|
|
|
|
|
|
|
| 198 |
|
| 199 |
def postprocess(self, p, processed, *args):
|
| 200 |
pass
|
|
|
|
| 66 |
return (x_div - (x_orig - x_final)) * (sig_root / sig_tens)
|
| 67 |
|
| 68 |
|
| 69 |
+
# ==============================================================================
|
| 70 |
+
# ЧАСТЬ 1.5: Утилиты для управления шагами
|
| 71 |
+
# ==============================================================================
|
| 72 |
+
def should_apply_at_step(current_step, total_steps, start_step, end_step, start_frac, end_frac, step_mode):
|
| 73 |
+
"""
|
| 74 |
+
Определяет, нужно ли применять эффект на текущем шаге
|
| 75 |
+
|
| 76 |
+
Args:
|
| 77 |
+
current_step: Текущий шаг сэмплера
|
| 78 |
+
total_steps: Общее количество шагов
|
| 79 |
+
start_step: Начальный абсолютный шаг
|
| 80 |
+
end_step: Конечный абсолютный шаг
|
| 81 |
+
start_frac: Начальная доля (0.0-1.0)
|
| 82 |
+
end_frac: Конечная доля (0.0-1.0)
|
| 83 |
+
step_mode: Режим ("Absolute Steps" или "Fraction of Steps")
|
| 84 |
+
|
| 85 |
+
Returns:
|
| 86 |
+
bool: True если эффект должен применяться
|
| 87 |
+
"""
|
| 88 |
+
if step_mode == "Absolute Steps":
|
| 89 |
+
# Абсолютные шаги
|
| 90 |
+
effective_start = max(0, start_step)
|
| 91 |
+
effective_end = min(total_steps, end_step) if end_step > 0 else total_steps
|
| 92 |
+
return effective_start <= current_step < effective_end
|
| 93 |
+
else:
|
| 94 |
+
# Доли от общего количества шагов
|
| 95 |
+
effective_start = int(total_steps * max(0.0, min(1.0, start_frac)))
|
| 96 |
+
effective_end = int(total_steps * max(0.0, min(1.0, end_frac)))
|
| 97 |
+
if effective_end == 0:
|
| 98 |
+
effective_end = total_steps
|
| 99 |
+
return effective_start <= current_step < effective_end
|
| 100 |
+
|
| 101 |
+
|
| 102 |
+
def get_param_value_at_step(base_value, current_step, total_steps, start_step, end_step,
|
| 103 |
+
start_frac, end_frac, step_mode, enabled):
|
| 104 |
+
"""
|
| 105 |
+
Возвращает значение параметра для текущего шага
|
| 106 |
+
Если шаг вне диапазона - возвращает 0.0
|
| 107 |
+
"""
|
| 108 |
+
if not enabled:
|
| 109 |
+
return base_value
|
| 110 |
+
|
| 111 |
+
if should_apply_at_step(current_step, total_steps, start_step, end_step,
|
| 112 |
+
start_frac, end_frac, step_mode):
|
| 113 |
+
return base_value
|
| 114 |
+
else:
|
| 115 |
+
return 0.0
|
| 116 |
+
|
| 117 |
+
|
| 118 |
# ==============================================================================
|
| 119 |
# ЧАСТЬ 2: Перехват управления (Hooking)
|
| 120 |
# ==============================================================================
|
| 121 |
|
| 122 |
+
# Хук 1: Сохраняем Sigma, Input Latent и текущий шаг
|
| 123 |
def hook_cfg_denoiser_params(params):
|
| 124 |
if hasattr(params.denoiser, 'p') and getattr(params.denoiser.p, '_nrs_enabled', False):
|
| 125 |
params.denoiser.p._nrs_current_sigma = params.sigma
|
| 126 |
params.denoiser.p._nrs_current_x_in = params.x
|
| 127 |
+
|
| 128 |
+
# Определяем текущий шаг
|
| 129 |
+
if hasattr(params, 'sampling_step'):
|
| 130 |
+
params.denoiser.p._nrs_current_step = params.sampling_step
|
| 131 |
+
elif hasattr(params.denoiser, 'step'):
|
| 132 |
+
params.denoiser.p._nrs_current_step = params.denoiser.step
|
| 133 |
+
else:
|
| 134 |
+
# Fallback: пытаемся определить по sigma
|
| 135 |
+
params.denoiser.p._nrs_current_step = getattr(params.denoiser.p, '_nrs_current_step', 0)
|
| 136 |
|
| 137 |
script_callbacks.on_cfg_denoiser(hook_cfg_denoiser_params)
|
| 138 |
|
|
|
|
| 140 |
if not hasattr(sd_samplers_cfg_denoiser.CFGDenoiser, 'original_combine_denoised_nrs_backup'):
|
| 141 |
sd_samplers_cfg_denoiser.CFGDenoiser.original_combine_denoised_nrs_backup = sd_samplers_cfg_denoiser.CFGDenoiser.combine_denoised
|
| 142 |
|
| 143 |
+
# Хук 2: Подменная функция с поддержкой step control
|
| 144 |
def hijacked_combine_denoised(self, x_out, conds_list, uncond, cond_scale):
|
| 145 |
# Проверка активности NRS
|
| 146 |
if not getattr(self, 'p', None) or not getattr(self.p, '_nrs_enabled', False):
|
|
|
|
| 150 |
return sd_samplers_cfg_denoiser.CFGDenoiser.original_combine_denoised_nrs_backup(self, x_out, conds_list, uncond, cond_scale)
|
| 151 |
|
| 152 |
try:
|
| 153 |
+
# Получаем базовые параметры
|
| 154 |
+
base_skew, base_stretch, base_squash = self.p._nrs_params
|
| 155 |
+
|
| 156 |
+
# Получаем настройки step control
|
| 157 |
+
step_control_enabled = getattr(self.p, '_nrs_step_control_enabled', False)
|
| 158 |
+
step_control_mode = getattr(self.p, '_nrs_step_control_mode', 'Global')
|
| 159 |
+
|
| 160 |
+
# Определяем текущий и общий шаги
|
| 161 |
+
current_step = getattr(self.p, '_nrs_current_step', 0)
|
| 162 |
+
total_steps = getattr(self.p, 'steps', 20)
|
| 163 |
|
| 164 |
+
# Если step control включен, вычисляем эффективные значения параметров
|
| 165 |
+
if step_control_enabled:
|
| 166 |
+
if step_control_mode == 'Global':
|
| 167 |
+
# Глобальный режим - одни настройки для всех
|
| 168 |
+
global_settings = getattr(self.p, '_nrs_global_step_settings', {})
|
| 169 |
+
start_step = global_settings.get('start_step', 0)
|
| 170 |
+
end_step = global_settings.get('end_step', total_steps)
|
| 171 |
+
start_frac = global_settings.get('start_frac', 0.0)
|
| 172 |
+
end_frac = global_settings.get('end_frac', 1.0)
|
| 173 |
+
step_mode = global_settings.get('step_mode', 'Absolute Steps')
|
| 174 |
+
|
| 175 |
+
# Проверяем, нужно ли применять эффекты
|
| 176 |
+
if not should_apply_at_step(current_step, total_steps, start_step, end_step,
|
| 177 |
+
start_frac, end_frac, step_mode):
|
| 178 |
+
# Вне диапазона - используем fallback
|
| 179 |
+
return sd_samplers_cfg_denoiser.CFGDenoiser.original_combine_denoised_nrs_backup(
|
| 180 |
+
self, x_out, conds_list, uncond, cond_scale)
|
| 181 |
+
|
| 182 |
+
skew, stretch, squash = base_skew, base_stretch, base_squash
|
| 183 |
+
else:
|
| 184 |
+
# Индивидуальный режим - отдельные настройки для каждого параметра
|
| 185 |
+
individual_settings = getattr(self.p, '_nrs_individual_step_settings', {})
|
| 186 |
+
|
| 187 |
+
skew_settings = individual_settings.get('skew', {})
|
| 188 |
+
skew = get_param_value_at_step(
|
| 189 |
+
base_skew, current_step, total_steps,
|
| 190 |
+
skew_settings.get('start_step', 0),
|
| 191 |
+
skew_settings.get('end_step', total_steps),
|
| 192 |
+
skew_settings.get('start_frac', 0.0),
|
| 193 |
+
skew_settings.get('end_frac', 1.0),
|
| 194 |
+
skew_settings.get('step_mode', 'Absolute Steps'),
|
| 195 |
+
skew_settings.get('enabled', True)
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
stretch_settings = individual_settings.get('stretch', {})
|
| 199 |
+
stretch = get_param_value_at_step(
|
| 200 |
+
base_stretch, current_step, total_steps,
|
| 201 |
+
stretch_settings.get('start_step', 0),
|
| 202 |
+
stretch_settings.get('end_step', total_steps),
|
| 203 |
+
stretch_settings.get('start_frac', 0.0),
|
| 204 |
+
stretch_settings.get('end_frac', 1.0),
|
| 205 |
+
stretch_settings.get('step_mode', 'Absolute Steps'),
|
| 206 |
+
stretch_settings.get('enabled', True)
|
| 207 |
+
)
|
| 208 |
+
|
| 209 |
+
squash_settings = individual_settings.get('squash', {})
|
| 210 |
+
squash = get_param_value_at_step(
|
| 211 |
+
base_squash, current_step, total_steps,
|
| 212 |
+
squash_settings.get('start_step', 0),
|
| 213 |
+
squash_settings.get('end_step', total_steps),
|
| 214 |
+
squash_settings.get('start_frac', 0.0),
|
| 215 |
+
squash_settings.get('end_frac', 1.0),
|
| 216 |
+
squash_settings.get('step_mode', 'Absolute Steps'),
|
| 217 |
+
squash_settings.get('enabled', True)
|
| 218 |
+
)
|
| 219 |
+
else:
|
| 220 |
+
# Step control выключен - используем базовые значения
|
| 221 |
+
skew, stretch, squash = base_skew, base_stretch, base_squash
|
| 222 |
+
|
| 223 |
+
# Основная логика NRS
|
| 224 |
denoised_uncond = x_out[-uncond.shape[0]:]
|
| 225 |
denoised = torch.clone(denoised_uncond)
|
| 226 |
|
|
|
|
| 259 |
|
| 260 |
|
| 261 |
# ==============================================================================
|
| 262 |
+
# ЧАСТЬ 3: Интерфейс (UI) с расширенными настройками
|
| 263 |
# ==============================================================================
|
| 264 |
class NRSScript(scripts.Script):
|
| 265 |
def title(self):
|
| 266 |
+
return "Negative Rejection Steering (Enhanced)"
|
| 267 |
|
| 268 |
def show(self, is_img2img):
|
| 269 |
return scripts.AlwaysVisible
|
|
|
|
| 291 |
1. **Skew** ≈ Половина вашего обычного CFG (например, **3.0** - **4.0**).
|
| 292 |
2. **Stretch** ≈ Ваш обычный CFG (например, **6.0** - **7.0**).
|
| 293 |
3. **Squash** ≈ Оставьте **0.0** для начала.
|
| 294 |
+
|
| 295 |
+
### ⏱️ Step Control (Управление шагами):
|
| 296 |
+
Позволяет применять NRS только на определенных шагах генерации.
|
| 297 |
+
- **Global Mode**: Одинаковые настройки для всех трех параметров
|
| 298 |
+
- **Individual Mode**: Отдельные настройки для каждого параметра (Skew, Stretch, Squash)
|
| 299 |
""")
|
| 300 |
|
| 301 |
+
# --- ОСНОВНЫЕ ПАРАМЕТРЫ ---
|
| 302 |
+
gr.HTML("<div style='margin-bottom: 0.5em; opacity: 0.8; font-size: 0.9em; border-bottom: 1px solid #444;'>Основные настройки</div>")
|
| 303 |
|
| 304 |
with gr.Row():
|
| 305 |
skew = gr.Slider(
|
|
|
|
| 319 |
info="0.0 = Макс. эффект. 1.0 = Ослабление (больше деталей, меньше контраста)."
|
| 320 |
)
|
| 321 |
|
| 322 |
+
# --- STEP CONTROL ---
|
| 323 |
+
with gr.Accordion("⏱️ Step Control (Управление шагами)", open=False):
|
| 324 |
+
with gr.Row():
|
| 325 |
+
step_control_enabled = gr.Checkbox(
|
| 326 |
+
label="Включить Step Control",
|
| 327 |
+
value=False,
|
| 328 |
+
info="Применять NRS только на определенных шагах"
|
| 329 |
+
)
|
| 330 |
+
step_control_mode = gr.Radio(
|
| 331 |
+
label="Режим управления",
|
| 332 |
+
choices=["Global", "Individual"],
|
| 333 |
+
value="Global",
|
| 334 |
+
info="Global: общие настройки | Individual: настройки для каждого параметра"
|
| 335 |
+
)
|
| 336 |
+
|
| 337 |
+
# ГЛОБАЛЬНЫЕ НАСТРОЙКИ
|
| 338 |
+
with gr.Group(visible=True) as global_group:
|
| 339 |
+
gr.HTML("<div style='margin: 0.5em 0; font-weight: bold;'>Глобальные настройки (для всех параметров)</div>")
|
| 340 |
+
|
| 341 |
+
global_step_mode = gr.Radio(
|
| 342 |
+
label="Режим шагов",
|
| 343 |
+
choices=["Absolute Steps", "Fraction of Steps"],
|
| 344 |
+
value="Absolute Steps",
|
| 345 |
+
info="Absolute: номера шагов | Fraction: доли от общего числа"
|
| 346 |
+
)
|
| 347 |
+
|
| 348 |
+
with gr.Row():
|
| 349 |
+
global_start_step = gr.Slider(
|
| 350 |
+
label="Start Step (абсолютный)",
|
| 351 |
+
minimum=0, maximum=150, step=1, value=0,
|
| 352 |
+
visible=True
|
| 353 |
+
)
|
| 354 |
+
global_end_step = gr.Slider(
|
| 355 |
+
label="End Step (абсолютный, 0=конец)",
|
| 356 |
+
minimum=0, maximum=150, step=1, value=0,
|
| 357 |
+
visible=True
|
| 358 |
+
)
|
| 359 |
+
|
| 360 |
+
with gr.Row():
|
| 361 |
+
global_start_frac = gr.Slider(
|
| 362 |
+
label="Start (доля от общего числа)",
|
| 363 |
+
minimum=0.0, maximum=1.0, step=0.01, value=0.0,
|
| 364 |
+
visible=False
|
| 365 |
+
)
|
| 366 |
+
global_end_frac = gr.Slider(
|
| 367 |
+
label="End (доля от общего числа)",
|
| 368 |
+
minimum=0.0, maximum=1.0, step=0.01, value=1.0,
|
| 369 |
+
visible=False
|
| 370 |
+
)
|
| 371 |
+
|
| 372 |
+
# ИНДИВИДУАЛЬНЫЕ НАСТРОЙКИ
|
| 373 |
+
with gr.Group(visible=False) as individual_group:
|
| 374 |
+
gr.HTML("<div style='margin: 0.5em 0; font-weight: bold;'>Индивидуальные настройки</div>")
|
| 375 |
+
|
| 376 |
+
# SKEW
|
| 377 |
+
with gr.Accordion("Skew (Композиция) - Step Settings", open=False):
|
| 378 |
+
skew_step_enabled = gr.Checkbox(label="Включить управление шагами для Skew", value=True)
|
| 379 |
+
skew_step_mode = gr.Radio(
|
| 380 |
+
label="Режим",
|
| 381 |
+
choices=["Absolute Steps", "Fraction of Steps"],
|
| 382 |
+
value="Absolute Steps"
|
| 383 |
+
)
|
| 384 |
+
with gr.Row():
|
| 385 |
+
skew_start_step = gr.Slider(label="Start Step", minimum=0, maximum=150, step=1, value=0, visible=True)
|
| 386 |
+
skew_end_step = gr.Slider(label="End Step (0=конец)", minimum=0, maximum=150, step=1, value=0, visible=True)
|
| 387 |
+
with gr.Row():
|
| 388 |
+
skew_start_frac = gr.Slider(label="Start (fraction)", minimum=0.0, maximum=1.0, step=0.01, value=0.0, visible=False)
|
| 389 |
+
skew_end_frac = gr.Slider(label="End (fraction)", minimum=0.0, maximum=1.0, step=0.01, value=1.0, visible=False)
|
| 390 |
+
|
| 391 |
+
# STRETCH
|
| 392 |
+
with gr.Accordion("Stretch (Цвета/Текстура) - Step Settings", open=False):
|
| 393 |
+
stretch_step_enabled = gr.Checkbox(label="Включить управление шагами для Stretch", value=True)
|
| 394 |
+
stretch_step_mode = gr.Radio(
|
| 395 |
+
label="Режим",
|
| 396 |
+
choices=["Absolute Steps", "Fraction of Steps"],
|
| 397 |
+
value="Absolute Steps"
|
| 398 |
+
)
|
| 399 |
+
with gr.Row():
|
| 400 |
+
stretch_start_step = gr.Slider(label="Start Step", minimum=0, maximum=150, step=1, value=0, visible=True)
|
| 401 |
+
stretch_end_step = gr.Slider(label="End Step (0=конец)", minimum=0, maximum=150, step=1, value=0, visible=True)
|
| 402 |
+
with gr.Row():
|
| 403 |
+
stretch_start_frac = gr.Slider(label="Start (fraction)", minimum=0.0, maximum=1.0, step=0.01, value=0.0, visible=False)
|
| 404 |
+
stretch_end_frac = gr.Slider(label="End (fraction)", minimum=0.0, maximum=1.0, step=0.01, value=1.0, visible=False)
|
| 405 |
+
|
| 406 |
+
# SQUASH
|
| 407 |
+
with gr.Accordion("Squash (Защита от пережарки) - Step Settings", open=False):
|
| 408 |
+
squash_step_enabled = gr.Checkbox(label="Включить управление шагами для Squash", value=True)
|
| 409 |
+
squash_step_mode = gr.Radio(
|
| 410 |
+
label="Режим",
|
| 411 |
+
choices=["Absolute Steps", "Fraction of Steps"],
|
| 412 |
+
value="Absolute Steps"
|
| 413 |
+
)
|
| 414 |
+
with gr.Row():
|
| 415 |
+
squash_start_step = gr.Slider(label="Start Step", minimum=0, maximum=150, step=1, value=0, visible=True)
|
| 416 |
+
squash_end_step = gr.Slider(label="End Step (0=конец)", minimum=0, maximum=150, step=1, value=0, visible=True)
|
| 417 |
+
with gr.Row():
|
| 418 |
+
squash_start_frac = gr.Slider(label="Start (fraction)", minimum=0.0, maximum=1.0, step=0.01, value=0.0, visible=False)
|
| 419 |
+
squash_end_frac = gr.Slider(label="End (fraction)", minimum=0.0, maximum=1.0, step=0.01, value=1.0, visible=False)
|
| 420 |
+
|
| 421 |
+
# Переключение видимости групп при изменении режима
|
| 422 |
+
def update_mode_visibility(mode):
|
| 423 |
+
return {
|
| 424 |
+
global_group: gr.update(visible=(mode == "Global")),
|
| 425 |
+
individual_group: gr.update(visible=(mode == "Individual"))
|
| 426 |
+
}
|
| 427 |
+
|
| 428 |
+
step_control_mode.change(
|
| 429 |
+
fn=update_mode_visibility,
|
| 430 |
+
inputs=[step_control_mode],
|
| 431 |
+
outputs=[global_group, individual_group]
|
| 432 |
+
)
|
| 433 |
+
|
| 434 |
+
# Переключение между абсолютными и дробными шагами (GLOBAL)
|
| 435 |
+
def update_global_step_inputs(mode):
|
| 436 |
+
is_absolute = (mode == "Absolute Steps")
|
| 437 |
+
return {
|
| 438 |
+
global_start_step: gr.update(visible=is_absolute),
|
| 439 |
+
global_end_step: gr.update(visible=is_absolute),
|
| 440 |
+
global_start_frac: gr.update(visible=not is_absolute),
|
| 441 |
+
global_end_frac: gr.update(visible=not is_absolute)
|
| 442 |
+
}
|
| 443 |
+
|
| 444 |
+
global_step_mode.change(
|
| 445 |
+
fn=update_global_step_inputs,
|
| 446 |
+
inputs=[global_step_mode],
|
| 447 |
+
outputs=[global_start_step, global_end_step, global_start_frac, global_end_frac]
|
| 448 |
+
)
|
| 449 |
+
|
| 450 |
+
# Переключение для SKEW
|
| 451 |
+
def update_skew_step_inputs(mode):
|
| 452 |
+
is_absolute = (mode == "Absolute Steps")
|
| 453 |
+
return {
|
| 454 |
+
skew_start_step: gr.update(visible=is_absolute),
|
| 455 |
+
skew_end_step: gr.update(visible=is_absolute),
|
| 456 |
+
skew_start_frac: gr.update(visible=not is_absolute),
|
| 457 |
+
skew_end_frac: gr.update(visible=not is_absolute)
|
| 458 |
+
}
|
| 459 |
+
|
| 460 |
+
skew_step_mode.change(
|
| 461 |
+
fn=update_skew_step_inputs,
|
| 462 |
+
inputs=[skew_step_mode],
|
| 463 |
+
outputs=[skew_start_step, skew_end_step, skew_start_frac, skew_end_frac]
|
| 464 |
+
)
|
| 465 |
+
|
| 466 |
+
# Переключение для STRETCH
|
| 467 |
+
def update_stretch_step_inputs(mode):
|
| 468 |
+
is_absolute = (mode == "Absolute Steps")
|
| 469 |
+
return {
|
| 470 |
+
stretch_start_step: gr.update(visible=is_absolute),
|
| 471 |
+
stretch_end_step: gr.update(visible=is_absolute),
|
| 472 |
+
stretch_start_frac: gr.update(visible=not is_absolute),
|
| 473 |
+
stretch_end_frac: gr.update(visible=not is_absolute)
|
| 474 |
+
}
|
| 475 |
+
|
| 476 |
+
stretch_step_mode.change(
|
| 477 |
+
fn=update_stretch_step_inputs,
|
| 478 |
+
inputs=[stretch_step_mode],
|
| 479 |
+
outputs=[stretch_start_step, stretch_end_step, stretch_start_frac, stretch_end_frac]
|
| 480 |
+
)
|
| 481 |
+
|
| 482 |
+
# Переключение для SQUASH
|
| 483 |
+
def update_squash_step_inputs(mode):
|
| 484 |
+
is_absolute = (mode == "Absolute Steps")
|
| 485 |
+
return {
|
| 486 |
+
squash_start_step: gr.update(visible=is_absolute),
|
| 487 |
+
squash_end_step: gr.update(visible=is_absolute),
|
| 488 |
+
squash_start_frac: gr.update(visible=not is_absolute),
|
| 489 |
+
squash_end_frac: gr.update(visible=not is_absolute)
|
| 490 |
+
}
|
| 491 |
+
|
| 492 |
+
squash_step_mode.change(
|
| 493 |
+
fn=update_squash_step_inputs,
|
| 494 |
+
inputs=[squash_step_mode],
|
| 495 |
+
outputs=[squash_start_step, squash_end_step, squash_start_frac, squash_end_frac]
|
| 496 |
+
)
|
| 497 |
+
|
| 498 |
+
return [
|
| 499 |
+
enabled, skew, stretch, squash,
|
| 500 |
+
step_control_enabled, step_control_mode,
|
| 501 |
+
# Global
|
| 502 |
+
global_step_mode, global_start_step, global_end_step, global_start_frac, global_end_frac,
|
| 503 |
+
# Skew
|
| 504 |
+
skew_step_enabled, skew_step_mode, skew_start_step, skew_end_step, skew_start_frac, skew_end_frac,
|
| 505 |
+
# Stretch
|
| 506 |
+
stretch_step_enabled, stretch_step_mode, stretch_start_step, stretch_end_step, stretch_start_frac, stretch_end_frac,
|
| 507 |
+
# Squash
|
| 508 |
+
squash_step_enabled, squash_step_mode, squash_start_step, squash_end_step, squash_start_frac, squash_end_frac
|
| 509 |
+
]
|
| 510 |
|
| 511 |
+
def process(self, p, enabled, skew, stretch, squash,
|
| 512 |
+
step_control_enabled, step_control_mode,
|
| 513 |
+
global_step_mode, global_start_step, global_end_step, global_start_frac, global_end_frac,
|
| 514 |
+
skew_step_enabled, skew_step_mode, skew_start_step, skew_end_step, skew_start_frac, skew_end_frac,
|
| 515 |
+
stretch_step_enabled, stretch_step_mode, stretch_start_step, stretch_end_step, stretch_start_frac, stretch_end_frac,
|
| 516 |
+
squash_step_enabled, squash_step_mode, squash_start_step, squash_end_step, squash_start_frac, squash_end_frac):
|
| 517 |
+
|
| 518 |
p._nrs_enabled = enabled
|
| 519 |
p._nrs_params = (skew, stretch, squash)
|
| 520 |
+
p._nrs_step_control_enabled = step_control_enabled
|
| 521 |
+
p._nrs_step_control_mode = step_control_mode
|
| 522 |
+
|
| 523 |
+
# Сохраняем глобальные настройки
|
| 524 |
+
p._nrs_global_step_settings = {
|
| 525 |
+
'step_mode': global_step_mode,
|
| 526 |
+
'start_step': global_start_step,
|
| 527 |
+
'end_step': global_end_step,
|
| 528 |
+
'start_frac': global_start_frac,
|
| 529 |
+
'end_frac': global_end_frac
|
| 530 |
+
}
|
| 531 |
+
|
| 532 |
+
# Сохраняем индивидуальные настройки
|
| 533 |
+
p._nrs_individual_step_settings = {
|
| 534 |
+
'skew': {
|
| 535 |
+
'enabled': skew_step_enabled,
|
| 536 |
+
'step_mode': skew_step_mode,
|
| 537 |
+
'start_step': skew_start_step,
|
| 538 |
+
'end_step': skew_end_step,
|
| 539 |
+
'start_frac': skew_start_frac,
|
| 540 |
+
'end_frac': skew_end_frac
|
| 541 |
+
},
|
| 542 |
+
'stretch': {
|
| 543 |
+
'enabled': stretch_step_enabled,
|
| 544 |
+
'step_mode': stretch_step_mode,
|
| 545 |
+
'start_step': stretch_start_step,
|
| 546 |
+
'end_step': stretch_end_step,
|
| 547 |
+
'start_frac': stretch_start_frac,
|
| 548 |
+
'end_frac': stretch_end_frac
|
| 549 |
+
},
|
| 550 |
+
'squash': {
|
| 551 |
+
'enabled': squash_step_enabled,
|
| 552 |
+
'step_mode': squash_step_mode,
|
| 553 |
+
'start_step': squash_start_step,
|
| 554 |
+
'end_step': squash_end_step,
|
| 555 |
+
'start_frac': squash_start_frac,
|
| 556 |
+
'end_frac': squash_end_frac
|
| 557 |
+
}
|
| 558 |
+
}
|
| 559 |
|
| 560 |
if enabled:
|
| 561 |
sd_samplers_cfg_denoiser.CFGDenoiser.combine_denoised = hijacked_combine_denoised
|
| 562 |
+
|
| 563 |
+
# Инициализируем счетчик шагов
|
| 564 |
+
p._nrs_current_step = 0
|
| 565 |
|
| 566 |
def postprocess(self, p, processed, *args):
|
| 567 |
pass
|