Compare commits

...
29 Commits
Author SHA1 Message Date
scraed 75a91710f2 Update pyproject.toml 2025-04-16 23:50:17 +08:00
scraed f8eea61264 Update README.md 2025-04-16 23:48:58 +08:00
scraed e42d3b0426 Update README.md 2025-04-16 23:32:46 +08:00
scraed ee567b14e8 Update Example for Hidream 2025-04-16 23:21:55 +08:00
scraed 10a790974c Merge branch 'master' of https://github.com/scraed/LanPaint 2025-04-16 23:12:18 +08:00
scraed 00d2eb9885 Update hidream example 2025-04-16 23:12:13 +08:00
scraed b1139f285a Update Citationn 2025-04-16 22:58:40 +08:00
scraed eb69a21cf2 Update README.md for hidream support 2025-04-16 22:26:05 +08:00
scraed c863ade839 update version 2025-04-16 22:25:05 +08:00
scraed b07ed256c7 Primary support for Hidream 2025-04-16 22:24:18 +08:00
scraed 612cfb51f2 Merge pull request #19 from ComfyNodePRs/update-publish-yaml
Update Github Action for Publishing to Comfy Registry
2025-04-11 20:42:47 +08:00
scraed aa9319f7cf Update README.md 2025-03-22 21:26:08 +08:00
scraed a92d19d4f8 Updates dates 2025-03-22 21:23:12 +08:00
scraed 478b077c69 Update pyproject.toml 2025-03-22 21:18:12 +08:00
scraed 3015d6f0ef Update README.md 2025-03-22 21:17:17 +08:00
scraed 55cd84be93 Update README.md for flux and tease mode 2025-03-22 21:16:40 +08:00
scraed 758eae62c3 add flux example 2025-03-22 21:08:23 +08:00
scraed 58f8d01acf Merge branch 'master' of https://github.com/scraed/LanPaint 2025-03-22 20:14:27 +08:00
scraed 1684b616f1 Merge pull request #16 from charrywhite/master
Add preview hood in KSamplerX0Inpaint
2025-03-22 20:10:07 +08:00
scraed 65f98f7c48 disable CFG BIG for Flux 2025-03-22 20:05:30 +08:00
charrywhite 5d8e40a669 Add preview hood in KSamplerX0Inpaint 2025-03-22 19:57:59 +08:00
scraed ff1fb62d1a Merge branch 'master' of https://github.com/scraed/LanPaint 2025-03-22 19:46:42 +08:00
scraed b7d37ef121 flux support and parameter change
add flux support and eliminate parameters a and b
2025-03-22 19:46:40 +08:00
scraed 29c9d877be Update ToDo 2025-03-19 23:10:21 +08:00
scraed 6c1375c35f update control net support in readme 2025-03-13 23:10:49 +08:00
scraed 8c04ba410b More intuitive how it works 2025-03-13 22:29:46 +08:00
scraed a5c08aa0a4 Update how it works 2025-03-13 17:45:32 +08:00
scraed cefc2c43d3 add version requirement in README.md 2025-03-13 10:15:36 +08:00
snomiao 34d36e3c93 chore(publish): update workflow for node publishing
- Add permissions for issue writing in the workflow
- Set condition to run job only for 'scraed' repository owner
- Update action version from 'main' to 'v1' for stability and consistency
2025-03-04 04:12:56 +00:00
12 changed files with 158 additions and 47 deletions
+5 -1
View File
@@ -7,14 +7,18 @@ on:
paths:
- "pyproject.toml"
permissions:
issues: write
jobs:
publish-node:
name: Publish Custom Node to registry
runs-on: ubuntu-latest
if: ${{ github.repository_owner == 'scraed' }}
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:
personal_access_token: ${{ secrets.REGISTRY_ACCESS_TOKEN }} ## Add your own personal access token to your Github Repository secrets and reference it here.
+57 -13
View File
@@ -7,25 +7,44 @@ We encourage you to try it out and share your feedback through issues or discuss
## Features
- 🎨 **Zero-Training Inpainting** - Works immediately with ANY SD model, even custom models you've trained yourself
- 🎨 **Zero-Training Inpainting** - Works immediately with ANY SD model (with/without ControlNet), and Flux model! even custom models you've trained yourself
- 🛠️ **Simple Integration** - Same workflow as standard ComfyUI KSampler
- 🎯 **True Blank-Slate Generation** - No need to set default denoise at 0.7 (preserving 30% original pixels in masks) used in conventional methods: 100% **new content creation**, No "painting over" existing content.
- 🌈 **Not only inpaint**: You can even use it as a simple way to generate consistent characters.
## How It Works?
- 🤝 **Bidirectional Context Control**
- Creates **two-way alignment** between masked/unmaksed areas
- Unlike single-direction approaches, our system continuously checks:
*"Does the new content make sense with existing elements?"*
*"Do existing elements support the new creation?"*
## How It Works
LanPaint introduces **two-way alignment** between masked and unmasked areas. It continuously evaluates:
- *"Does the new content make sense with the existing elements?"*
- *"Do the existing elements support the new creation?"*
Based on this evaluation, LanPaint iteratively updates the noise in both the masked and unmasked regions.
## Updates
LanPaint has received a major update! All examples now use the LanPaint K Sampler, offering a simplified interface with enhanced performance and stability.
- 2025/04/16
- Added Primary HiDream support
- 2025/03/22
- Added Primary Flux support
- Added Tease Mode
- 2025/03/10
- LanPaint has received a major update! All examples now use the LanPaint K Sampler, offering a simplified interface with enhanced performance and stability.
## Example Results
All examples use a random seed 0 to generate batch of 4 images for fair comparison. (Warning: Generating 4 images may exceed your GPU memory; adjust batch size as needed.)
### Example HiDream: InPaint(LanPaint K Sampler, 5 steps of thinking)
![Inpainting Result 8](https://github.com/scraed/LanPaint/blob/master/examples/InpaintChara_11.jpg)
[View Workflow & Masks](https://github.com/scraed/LanPaint/tree/master/examples/Example_8)
You need to install [ComfyUI GGUF](https://github.com/city96/ComfyUI-GGUF) in order to load the models. Make sure you have the latest (nightly at 2025/04/16) comfyui installed. The following models are needed for Hidream:
- [clip_g_hidream.safetensors](https://huggingface.co/Comfy-Org/HiDream-I1_ComfyUI/blob/main/split_files/text_encoders/clip_g_hidream.safetensors)
- [clip_l_hidream.safetensors](https://huggingface.co/Comfy-Org/HiDream-I1_ComfyUI/blob/main/split_files/text_encoders/clip_l_hidream.safetensors)
- [T5 GGUF](https://huggingface.co/city96/t5-v1_1-xxl-encoder-gguf/tree/main)
- [Llama 3.1](https://huggingface.co/bartowski/Meta-Llama-3.1-8B-Instruct-GGUF/tree/main)
- [Flux VAE](https://huggingface.co/StableDiffusionVN/Flux/blob/main/Vae/flux_vae.safetensors)
### Example 1: Basket to Basket Ball (LanPaint K Sampler, 2 steps of thinking).
![Inpainting Result 1](https://github.com/scraed/LanPaint/blob/master/examples/InpaintChara_04.jpg)
[View Workflow & Masks](https://github.com/scraed/LanPaint/tree/master/examples/Example_1)
@@ -55,7 +74,18 @@ All examples use a random seed 0 to generate batch of 4 images for fair comparis
(Tricks 2: Use prompts like multiple views, multiple angles, clone, turnaround.)
**How to Use These Examples:**
(Tricks 3: Remeber LanPaint can in-paint: Mask non-consistent regions and try again!)
### Example 7: Flux Model InPaint(LanPaint K Sampler, 5 steps of thinking)
![Inpainting Result 7](https://github.com/scraed/LanPaint/blob/master/examples/InpaintChara_10.jpg)
[View Workflow & Masks](https://github.com/scraed/LanPaint/tree/master/examples/Example_7)
[Model Used in This Example](https://huggingface.co/Comfy-Org/flux1-dev/blob/main/flux1-dev-fp8.safetensors)
(Note: Use CFG scale 1.0 for Flux as it don't use CFG. LanPaint_cfg_BIG is also disabled on Flux)
## **How to Use These Examples:**
1. Navigate to the **example** folder (i.e example_1) by clicking **View Workflow & Masks**, download all pictures.
2. Drag **InPainted_Drag_Me_to_ComfyUI.png** into ComfyUI to load the workflow.
3. Download the required model from Civitai by clicking **Model Used in This Example**.
@@ -73,7 +103,7 @@ Compare and explore the results from each method!
## Quickstart
1. **Install ComfyUI**: Follow the official [ComfyUI installation guide](https://docs.comfy.org/get_started) to set up ComfyUI on your system.
1. **Install ComfyUI**: Follow the official [ComfyUI installation guide](https://docs.comfy.org/get_started) to set up ComfyUI on your system. Or ensure your ComfyUI version > 0.3.11.
2. **Install ComfyUI-Manager**: Add the [ComfyUI-Manager](https://github.com/ltdrdata/ComfyUI-Manager) for easy extension management.
3. **Install LanPaint Nodes**:
- **Via ComfyUI-Manager**: Search for "[LanPaint](https://registry.comfy.org/publishers/scraed/nodes/LanPaint)" in the manager and install it directly.
@@ -144,8 +174,9 @@ For challenging inpainting tasks:
- Optimal parameters vary depending on the **model** and the **size of the inpainting area**.
- For effective tuning, **fix the seed** and adjust parameters incrementally while observing the results. This helps isolate the impact of each setting. Better to do it with a batche of images to avoid overfitting on a single image.
## Know Issues (ToDo)
- Flux is not supported yet.
## ToDo
- SD 3.5 also have problems
- Try Implement Detailer
## Contribute
@@ -153,6 +184,19 @@ For challenging inpainting tasks:
Help us improve LanPaint! 🚀 **Report bugs**, share **example cases**, or contribute your **personal parameter settings** to benefit the community.
## Citation
```
@misc{zheng2025lanpainttrainingfreediffusioninpainting,
title={Lanpaint: Training-Free Diffusion Inpainting with Exact and Fast Conditional Inference},
author={Candi Zheng and Yuan Lan and Yang Wang},
year={2025},
eprint={2502.03491},
archivePrefix={arXiv},
primaryClass={eess.IV},
url={https://arxiv.org/abs/2502.03491},
}
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 539 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "LanPaint"
version = "0.1.0"
version = "0.2.2"
description = "Achieve seamless inpainting results without needing a specialized inpainting model."
authors = [
{name = "LanPaint", email = "czhengac@connect.ust.hk"}
+95 -32
View File
@@ -8,6 +8,7 @@ import latent_preview
from functools import partial
from comfy.utils import repeat_to_batch_size
from comfy.samplers import *
from comfy.model_base import ModelType
# Monkey patch comfy.samplers module by importing with absolute package path
#exec(inspect.getsource(comfy.samplers).replace("from .", "from comfy."))
@@ -76,10 +77,23 @@ class KSamplerX0Inpaint:
self.sigmas = sigmas
self.model_sigmas = torch.cat( (torch.tensor([0.], device = sigmas.device) , torch.tensor( self.inner_model.model_patcher.get_model_object("model_sampling").sigmas, device = sigmas.device) ) )
self.model_sigmas = torch.tensor( self.model_sigmas, dtype = self.sigmas.dtype )
def __call__(self, x, sigma, denoise_mask, model_options={}, seed=None):
def __call__(self, x, sigma, denoise_mask, model_options={}, seed=None,**kwargs):
### For 1.5 and XL model
# x is x_t in the notation of variance exploding diffusion model, x_t = x_0 + sigma * noise
# sigma is the noise level
# print what is inside model_options
### For flux model
# x is rectified flow x_t = sigma * noise + (1.0 - sigma) * x_0
IS_FLUX = self.inner_model.inner_model.model_type == ModelType.FLUX
IS_FLOW = self.inner_model.inner_model.model_type == ModelType.FLOW
# unify the notations into variance exploding diffusion model
if IS_FLUX or IS_FLOW:
LanPaint_Sigma = sigma / ( torch.maximum( 1 - sigma , sigma*0 + 5e-2 ))
self.LanPaint_Sigmas = self.sigmas / ( torch.maximum( 1 - self.sigmas , self.sigmas*0 + 5e-2 ))
else:
LanPaint_Sigma = sigma
if denoise_mask is not None:
if "denoise_mask_function" in model_options:
denoise_mask = model_options["denoise_mask_function"](sigma, denoise_mask, extra_options={"model": self.inner_model, "sigmas": self.sigmas})
@@ -88,53 +102,76 @@ class KSamplerX0Inpaint:
latent_mask = 1 - denoise_mask
abt = 1/( 1+sigma**2 )
abt = 1/( 1+LanPaint_Sigma**2 )
print("sigma", LanPaint_Sigma, "abt", abt)
if self.step_time_schedule == "dual_shrink":
step_size = self.step_size * (1 - abt) ** 0.5 * abt ** 0.5
elif self.step_time_schedule == "follow_sampler":
time_ind = torch.argmin(torch.abs(self.sigmas - sigma))
times = torch.log( 1+ self.sigmas**2)
time_ind = torch.argmin(torch.abs(self.LanPaint_Sigmas - LanPaint_Sigma))
times = torch.log( 1+ self.LanPaint_Sigmas**2)
time_intervals = times[1:] - times[:-1]
time_intervals = time_intervals / time_intervals[0]
step_size = time_intervals[time_ind] * self.step_size
else:
step_size = self.step_size * (1 - abt) ** 0.5
a = self.LanPaint_a
b = self.LanPaint_b
#step_size = self.step_size * (1 - abt) ** b * abt ** a / ( ((a/(a+b))**a*(b/(a+b))**b) )
abt_end = 1/( 1+self.end_sigma**2 )
step_size = self.step_size * (1 - torch.minimum(abt/abt_end, abt**0) ) ** 0.5
step_size = step_size[:, None, None, None]
current_times = (sigma, abt)
current_times = (LanPaint_Sigma, abt)
# self.inner_model.inner_model.scale_latent_inpaint returns variance exploding x_t values
x = x * (1 - latent_mask) + self.inner_model.inner_model.scale_latent_inpaint(x=x, sigma=sigma, noise=self.noise, latent_image=self.latent_image)* latent_mask
x_t = x #/ ( 1+sigma**2 )**0.5 # switch to variance perserving x_t values
if IS_FLUX or IS_FLOW:
x_t = x * ( 1 + LanPaint_Sigma[:, None,None,None])
else:
x_t = x #/ ( 1+sigma**2 )**0.5 # switch to variance perserving x_t values
# after noise_scaling, noise = latent_image + noise * sigma, which is x_t in the variance exploding diffusion model notation for the known region.
args = None
for i in range(self.n_steps):
if torch.mean(sigma) > self.start_sigma or torch.mean(sigma) < self.end_sigma:
if torch.mean(LanPaint_Sigma) > self.start_sigma or torch.mean(LanPaint_Sigma) < self.end_sigma:
break
score_func = partial( self.score_model, y = self.latent_image, mask = latent_mask, abt = abt[:, None,None,None], sigma = sigma[:, None,None,None], model_options = model_options, seed = seed )
score_func = partial( self.score_model, y = self.latent_image, mask = latent_mask, abt = abt[:, None,None,None], sigma = LanPaint_Sigma[:, None,None,None], model_options = model_options, seed = seed )
if self.step_size_schedule == "linear":
step_size_i = step_size * (1 - i/(self.n_steps) )
else:
step_size_i = step_size
x_t, args = self.langevin_dynamics(x_t, score_func , latent_mask, step_size_i , current_times, sigma_x = self.sigma_x(abt)[:, None,None,None], sigma_y = self.sigma_y(abt)[:, None,None,None], args = args)
x = x_t #* ( 1+sigma**2 )**0.5
if IS_FLUX or IS_FLOW:
x = x_t / ( 1 + LanPaint_Sigma[:, None,None,None] )
else:
x = x_t #/ ( 1+sigma**2 )**0.5 # switch to variance perserving x_t values
# out is x_0
out, _ = self.inner_model(x, sigma, model_options=model_options, seed=seed)
out = out * denoise_mask + self.latent_image * latent_mask
else:
out, _ = self.inner_model(x, sigma, model_options=model_options, seed=seed)
# Add TAESD preview support - directly use the latent_preview module
current_step = model_options.get("i", kwargs.get("i", 0))
total_steps = model_options.get("total_steps", 0)
# Only show preview every few steps to improve performance
if current_step % 2 == 0:
# Directly call the preview callback if it exists
callback = model_options.get("callback", None)
if callback is not None:
callback({"i": current_step, "denoised": out, "x": x})
return out
def mid_times(self, current_times, step_size):
sigma, abt = current_times
@@ -153,8 +190,13 @@ class KSamplerX0Inpaint:
lamb = self.chara_lamb
beta = self.chara_beta * (1-abt)**0.5
x_0, x_0_BIG = self.inner_model(x_t, sigma[:, 0,0,0], model_options=model_options, seed=seed)
print("x_0", x_0.shape, "x_0_BIG", x_0_BIG.shape, "abt" , abt.shape, "sigma", sigma.shape)
IS_FLUX = self.inner_model.inner_model.model_type == ModelType.FLUX
IS_FLOW = self.inner_model.inner_model.model_type == ModelType.FLOW
if IS_FLUX or IS_FLOW:
x_0, x_0_BIG = self.inner_model(x_t / ( 1 + sigma ), sigma[:, 0,0,0] / ( 1 + sigma[:, 0,0,0] ), model_options=model_options, seed=seed)
else:
x_0, x_0_BIG = self.inner_model(x_t, sigma[:, 0,0,0], model_options=model_options, seed=seed)
e_t = x_t / ((1 - abt) ** 0.5 * (1 + sigma**2) ** 0.5 )- (abt ** 0.5 / (1 - abt) ** 0.5) * x_0
e_t_BIG = x_t / ((1 - abt) ** 0.5 * (1 + sigma**2) ** 0.5 )- (abt ** 0.5 / (1 - abt) ** 0.5) * x_0_BIG
@@ -185,8 +227,7 @@ class KSamplerX0Inpaint:
dtx = 2 * step_size * sigma_x
dty = 2 * step_size * sigma_y
a = self.LanPaint_a
b = self.LanPaint_b
#ref_dt = 0.1 * (1 - abt) ** b * abt ** a / ( ((a/(a+b))**a*(b/(a+b))**b) )
@@ -195,7 +236,7 @@ class KSamplerX0Inpaint:
# -------------------------------------------------------------------------
# Define friction parameter Gamma_hat for each branch.
# Using dtx**0 provides a tensor of the proper device/dtype.
print("dtx", dtx.shape, "sigma_x", sigma_x.shape, "ref_dt", ref_dt.shape)
Gamma_hat_x = self.friction * dtx / (1e-4+ 2 * sigma_x * ref_dt)
Gamma_hat_y = self.friction * dty / (1e-4+ 2 * sigma_y * ref_dt)
@@ -261,8 +302,6 @@ class KSamplerX0Inpaint:
# Transform x to z using z = x * sqrt(1+sigma^2). Here we have already set x to z to avoid floating point stability issue.
z_t = x_t #* (1 + sigma**2) ** 0.5
print("eps_denoise", eps_denoise.shape, "sigma", sigma.shape, "sigma_mid_x", sigma_mid_x.shape)
# Compute the mid-point update in z-space for each branch:
z_mid_x = z_t + eps_denoise * (sigma_mid_x - sigma)
z_mid_y = z_t + eps_denoise * (sigma_mid_y - sigma)
@@ -322,7 +361,15 @@ class KSAMPLER(comfy.samplers.KSAMPLER):
model_k.noise = torch.randn(noise.shape, generator=generator, device="cpu").to(noise.dtype).to(noise.device)
else:
model_k.noise = noise
model_wrap.cfg_BIG = model_wrap.model_patcher.LanPaint_cfg_BIG
IS_FLUX = model_wrap.inner_model.model_type == ModelType.FLUX
# unify the notations into variance exploding diffusion model
if IS_FLUX:
model_wrap.cfg_BIG = 1.0
else:
model_wrap.cfg_BIG = model_wrap.model_patcher.LanPaint_cfg_BIG
model_k.step_size = model_wrap.model_patcher.LanPaint_StepSize
model_k.chara_lamb = model_wrap.model_patcher.LanPaint_Lambda
model_k.chara_beta = model_wrap.model_patcher.LanPaint_Beta
@@ -335,8 +382,6 @@ class KSAMPLER(comfy.samplers.KSAMPLER):
model_k.step_time_schedule = model_wrap.model_patcher.LanPaint_StepTimeSchedule
model_k.start_sigma = model_wrap.model_patcher.LanPaint_StartSigma
model_k.end_sigma = model_wrap.model_patcher.LanPaint_EndSigma
model_k.LanPaint_a = model_wrap.model_patcher.LanPaint_a
model_k.LanPaint_b = model_wrap.model_patcher.LanPaint_b
noise = model_wrap.inner_model.model_sampling.noise_scaling(sigmas[0], noise, latent_image, self.max_denoise(model_wrap, sigmas))
#if not inpainting, after noise_scaling, noise = noise * sigma, which is the noise added to the clean latent image in the variance exploding diffusion model notation.
@@ -345,10 +390,13 @@ class KSAMPLER(comfy.samplers.KSAMPLER):
total_steps = len(sigmas) - 1
if callback is not None:
k_callback = lambda x: callback(x["i"], x["denoised"], x["x"], total_steps)
print("LanPaint KSampler call sampler_function", self.sampler_function)
#print("LanPaint KSampler call sampler_function", self.sampler_function)
# The main loop!
#print("##########")
#print("Sampling with ", self.sampler_function)
#print("##########")
samples = self.sampler_function(model_k, noise, sigmas, extra_args=extra_args, callback=k_callback, disable=disable_pbar, **self.extra_options)
print("LanPaint KSampler end sampler_function")
#print("LanPaint KSampler end sampler_function")
samples = model_wrap.inner_model.model_sampling.inverse_noise_scaling(sigmas[-1], samples)
return samples
@@ -371,8 +419,27 @@ def override_sample_function():
comfy.samplers.CFGGuider.outer_sample = original_outer_sample
class LanPaint_UpSale_LatentNoiseMask:
@classmethod
def INPUT_TYPES(s):
return {"required": { "samples": ("LATENT",),
"scale": ("INT", {"default": 2, "min": 2, "max": 8, "step": 1}),
}}
RETURN_TYPES = ("LATENT",)
FUNCTION = "set_mask"
CATEGORY = "latent/inpaint"
def set_mask(self, samples, scale):
s = samples.copy()
samples = s['samples']
# generate a mask with every scaleth pixel set to 1
mask = torch.zeros(samples.shape[0], 1, samples.shape[2], samples.shape[3], device=samples.device) + 1
mask[:, :, ::scale, ::scale] = 0
s["noise_mask"] = mask
return (s,)
KSAMPLER_NAMES = ["euler", "dpmpp_2m", "uni_pc"]
class LanPaint_KSampler():
@@ -417,8 +484,6 @@ class LanPaint_KSampler():
model.LanPaint_StartSigma = 20.
model.LanPaint_EndSigma = LanPaint_EndSigma
model.LanPaint_cfg_BIG = -0.5
model.LanPaint_a = 0.001
model.LanPaint_b = 1.5
with override_sample_function():
return nodes.common_ksampler(model, seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise)
class LanPaint_KSamplerAdvanced:
@@ -451,8 +516,6 @@ class LanPaint_KSamplerAdvanced:
"LanPaint_StartSigma": ("FLOAT", {"default": 20., "min": 0.0001, "max": 20.0, "step": 0.1, "round": 0.1, "tooltip": "Start 'thinking' with Langevin dynamics at this sigma value."}),
"LanPaint_EndSigma": ("FLOAT", {"default": 3., "min": 0.000, "max": 20.0, "step": 0.1, "round": 0.1, "tooltip": "Stop 'thinking' with Langevin dynamics at this sigma value."}),
"LanPaint_cfg_BIG": ("FLOAT", {"default": -0.5, "min": -20, "max": 20.0, "step": 0.1, "round": 0.1, "tooltip": "The CFG scale used in the bidirectional guidance (for the known region only). Higher value results in more closely matching the known region."}),
"LanPaint_a": ("FLOAT", {"default": 0.001, "min": 0.0001, "max": 20., "step": 0.001, "round": 0.001, "tooltip": "The a parameter for the HFHR langevin dynamics, the scale of the noise added to the latent image."}),
"LanPaint_b": ("FLOAT", {"default": 0.5, "min": 0.0001, "max": 20., "step": 0.001, "round": 0.001, "tooltip": "The b parameter for the HFHR langevin dynamics, the scale of the noise added to the latent image."}),
"LanPaint_Info": ("STRING", {"default": "LanPaint KSampler Advanced. For difficult tasks, first try increasing steps, LanPaint_NumSteps, and LanPaint_cfg_BIG. Then try increase LanPaint_Lambda or LanPaint_StepSize. Decrease LanPaint_Friction if you want to obtain good results with fewer turns of thinking (LanPaint_NumSteps) at the risk of irregular behavior. Increase LanPaint_Tamed or LanPaint_Alpha can suppress irregular behavior. For more information, visit https://github.com/scraed/LanPaint", "multiline": True}),
},
}
@@ -462,7 +525,7 @@ class LanPaint_KSamplerAdvanced:
CATEGORY = "sampling"
def sample(self, model, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise=1.0, LanPaint_StepSize=0.05, LanPaint_Lambda=5, LanPaint_Beta=1, LanPaint_NumSteps=5, LanPaint_Friction=5, LanPaint_Alpha=1, LanPaint_Tamed=0., LanPaint_BetaScale="fixed", LanPaint_StepSizeSchedule = "const", LanPaint_StepTimeSchedule = "shrink", LanPaint_StartSigma=20, LanPaint_EndSigma=0, LanPaint_cfg_BIG = 5., LanPaint_a=0.001, LanPaint_b=0.5, LanPaint_Info=""):
def sample(self, model, add_noise, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, start_at_step, end_at_step, return_with_leftover_noise, denoise=1.0, LanPaint_StepSize=0.05, LanPaint_Lambda=5, LanPaint_Beta=1, LanPaint_NumSteps=5, LanPaint_Friction=5, LanPaint_Alpha=1, LanPaint_Tamed=0., LanPaint_BetaScale="fixed", LanPaint_StepSizeSchedule = "const", LanPaint_StepTimeSchedule = "shrink", LanPaint_StartSigma=20, LanPaint_EndSigma=0, LanPaint_cfg_BIG = 5., LanPaint_Info=""):
force_full_denoise = True
if return_with_leftover_noise == "enable":
force_full_denoise = False
@@ -482,8 +545,6 @@ class LanPaint_KSamplerAdvanced:
model.LanPaint_StartSigma = LanPaint_StartSigma
model.LanPaint_EndSigma = LanPaint_EndSigma
model.LanPaint_cfg_BIG = LanPaint_cfg_BIG
model.LanPaint_a = LanPaint_a
model.LanPaint_b = LanPaint_b
with override_sample_function():
return nodes.common_ksampler(model, noise_seed, steps, cfg, sampler_name, scheduler, positive, negative, latent_image, denoise=denoise, disable_noise=disable_noise, start_step=start_at_step, last_step=end_at_step, force_full_denoise=force_full_denoise)
@@ -493,10 +554,12 @@ class LanPaint_KSamplerAdvanced:
NODE_CLASS_MAPPINGS = {
"LanPaint_KSampler": LanPaint_KSampler,
"LanPaint_KSamplerAdvanced": LanPaint_KSamplerAdvanced,
# "LanPaint_UpSale_LatentNoiseMask": LanPaint_UpSale_LatentNoiseMask,
}
# A dictionary that contains the friendly/humanly readable titles for the nodes
NODE_DISPLAY_NAME_MAPPINGS = {
"LanPaint_KSampler": "LanPaint KSampler",
"LanPaint_KSamplerAdvanced": "LanPaint KSampler (Advanced)"
"LanPaint_KSamplerAdvanced": "LanPaint KSampler (Advanced)",
# "LanPaint_UpSale_LatentNoiseMask": "LanPaint UpSale Latent Noise Mask"
}