在SD中,如何通过cutoff插件控制latent来给指定部分颜色(给人换衣服)

机器学习  收藏
0 / 142

过去,很难通过 Stable Diffusion 等图像生成 AI 指定详细的颜色。

因此,不可能在提示中包含太多颜色名称。

这似乎是因为指定颜色的词也会影响其他词。例如,即使你指定“Pink skirt, blue hair”,似乎Pink这个词不仅限于裙子,还会影响到头发的颜色。

如何指定偏色?

使用 CutOff(切断提示效果)。

新的WebUI扩展CutOff(Cutting Off Prompt Effect),提高了部分颜色指定的成功率。

什么是CutOff(切断提示效果)?

Cutoff 似乎已经成功地使用一种称为填充标记的机制将颜色影响范围限制在特定单词上。

技术机制在 Cutoff 的自述文件中的工作原理中进行了描述。

image.png

参考:CutOff(切断提示效果)库

如何安装CutOff(切断提示效果)?

通过 [如何指定 URL ]从 WebUI 安装 CutOff 。

以下是 Cutoff 的 Github 存储库 URL。

https://github.com/hnmr293/sd-webui-cutoff.git

请在 WebUI 的扩展选项卡中的“从 URL 安装”中输入此 URL进行安装。

[初学者] 如何安装和卸载 WebUI 扩展![如何安装WebUI 扩展] Stable diffusion 创建的图像 安装方法主要有两种。如何从 WebUI 存储库的扩展列表安装...

安装完成后,重新加载WebUI以启用扩展“切断提示效果”。

如何使用CutOff(切断提示效果)

Cutoff 的基本用法是以下四个步骤。

  1. 启用截止
  2. 指定目标令牌
  3. 截止选项设置
  4. 产生

1. 启用截止

如何使用 WebUI 截断▲启动WebUI后,点击Txt2img标签画面下方的“Cutoff”,展开Cutoff设置区域。

然后,有一个名为 Enable 的复选框,因此选中它以启用 Cutoff。

2. 输入目标词。

如何使用 WebUI 截断如果你这样写你的提示:

cute girl, white shirt with green tie, red shoes, blue hair, yellow eyes, pink skirt, simple simple background,

将提示中出现的颜色词写成如下:

white,green,red,blue,yellow,pink,

目标令牌是您想要限制影响范围的词。

通常,您指定提示中使用的颜色名称,以逗号分隔。

3. 设置截止选项。

基本上,
似乎您可以在不触摸选项设置的情况下运行并通过查看结果来调整 Weight 和 Interpolation 方法。

设置 设置
启用 启用截止
目标标记(逗号分隔) 列出你想限制影响范围的词。在许多情况下,它似乎是一个颜色名称。示例:红色、蓝色、白色
重量 截止强度(值越高越强)
禁用否定提示 是否将 CutOff 应用于否定提示。默认开启
强烈截止 强截止
填充令牌(ID 或单个令牌) 我认为这里的值通常是空白的。使用哪个令牌代替目标令牌。默认为 _(下划线)
插值法 Lerp/SLerp(默认:Lerp)如果它不起作用,请尝试 SLerp。
调试日志 是否将调试日志输出到命令提示符。如果在效果不佳时打开它,您可能会看到提示。

截止选项#### 什么是强烈截止?

Cutoff 强烈在 Cutoff 的自述文件中有以下描述。

顺便说一句,我觉得一个可爱的女孩可能会或可能不会受到粉发和红鞋的影响。所以在这个扩展中,对于这种中立的提示,

一个可爱的女孩,粉红色的头发,红色的鞋子
一个可爱的女孩,_头发,_鞋子

您可以选择应用哪一个。Details中的Cutoff strong设置为关闭时选择1,打开时选择2。关闭时会显示最接近原始图片的内容。默认值也在这里。

https://github.com/hnmr293/sd-webui-cutoff

4. 输入提示执行图像生成

设置好Cutoff后,照常输入提示符和否定提示符即可生成图像。

实验

white shirt with green tie, red shoes, blue hair, yellow eyes, pink skirt


←无截断 有截断→

对于那些没有剪裁的人,领带的颜色绿色延伸到裙子。我的头发变红了。

启用 Cutoff 后,我几乎可以将所有头发颜色绘制为蓝色,将领带绘制为绿色,将裙子绘制为粉红色。

cute girl, white shirt with green tie, red shoes, blue hair, yellow eyes, pink skirt, simple simple background, 
Negative prompt: (EasyNegative:1.1), extra fingers,fewer fingers, cat, animal, bad anatomy, two shot, hands, two shot
Steps: 20, Sampler: DPM++ SDE Karras, CFG scale: 7, Seed: 2083118349, Size: 504x756, Model hash: f6957e654e, Model: 1anime_7th_anime_v3_C, Script: X/Y/Z plot, X Type: Cutoff Enabled, X Values: "false, true", Y Type: Seed, Y Values: -1, Fixed Y Values: 2083118349

您可以使用 PNGInfo 检查 Cutoff 设置。

您可以使用 PNGInfo 检查 Cutoff 设置。

您可以通过简短的提示感受到效果。

简短的提示成功的概率很高。

但是,我的印象是,当提示很长时,成功的可能性很低。

如果 Cutoff 不起作用怎么办?

如果 Cutoff 不起作用怎么办?

作为 Cutoff 无法正常工作的解决方法,Github 的 ReadMe 中有以下描述。

如果生成的图像损坏或类似情况,请尝试更改权重值或将插值方法更改为 SLerp。

如果生成的图像损坏等,请尝试更改 Weight 值或将插值方法更改为 SLerp。请参阅插值方法的详细信息。

https://github.com/hnmr293/sd-webui-cutoff

作为一种方法,似乎可以通过尝试以下方法来改进,

  • 更改权重值
  • 切换完成方法(SLERP)

除此之外,如果打开日志输出并查看日志,您可能会找到原因。

已知错误:使用超过 75 个标记的否定提示可能会失败

根据否定提示中的令牌数量,截止似乎无法正常工作。

请检查以下内容。

https://github.com/hnmr293/sd-webui-cutoff/issues/11

通过球面线性插值(slerp)在潜在空间中进行噪声插值

稳定扩散 python PyTorch

备忘录.sugyan.com

写完文章后,我很后悔自己没有对以前的案例做足够的研究。我写的,我不认为有很多人在 Latent Seed 的高斯噪声之间进行变形,但是当我搜索它时,它是正常的。

这是在 Stable Diffusion 发布之前......

并且进行这种变形的代码也发布在 gist 中

slerp正如我所读,该函数用作获取两个噪声之间的值的方法。

对于i, t in  enumerate (np.linspace( 0 , 1 , num_steps)):
            init = slerp(浮点数(t), init1, init2)

https://gist.github.com/karpathy/00103b0037c5aaea32fe1da1af553355#file-stablediffusionwalk-py-L179-L180

这个定义如下。

def  slerp (t, v0, v1, DOT_THRESHOLD= 0.9995 ):
     """ helper function to spherically interpolate two arrays v1 v2 """

    如果 不是 isinstance(v0,np.ndarray):
        inputs_are_torch = True
        input_device = v0.device
        v0 = v0.cpu().numpy()
        v1 = v1.cpu().numpy()

    点 = np.sum(v0 * v1 / (np.linalg.norm(v0) * np.linalg.norm(v1)))
    如果np.abs(点)> DOT_THRESHOLD:
        v2 = ( 1 - t) * v0 + t * v1
    其他:
        theta_0 = np.arccos(点)
        sin_theta_0 = np.sin(theta_0)
        theta_t = theta_0 * t
        sin_theta_t = np.sin(theta_t)
        s0 = np.sin(theta_0 - theta_t) / sin_theta_0
        s1 = sin_theta_t / sin_theta_0
        v2 = s0 * v0 + s1 * v1

    如果inputs_are_torch:
        v2 = torch.from_numpy(v2).to(输入设备)

    返回v2

https://gist.github.com/karpathy/00103b0037c5aaea32fe1da1af553355#file-stablediffusionwalk-py-L101-L125

因为没学好所以不知道,不过这个方法在日文里叫做“球面线性插值”,在3DCG的世界里经常被当作四元数插值来使用。好像是这样的

en.wikipedia.org

正如所写,它最初是在四元数插值的背景下引入的,但似乎无论维度数如何都可以应用考虑从原点到空间中两点的向量,我们可以使用点积和范数找到两者之间的角度。感觉就像在连接两点的圆弧上从起点移动到终点,同时线性改变角度。欧姆Ω00欧姆Ω

S.l r p ( _p0,p1个; t ) =罪[ ( 1 − t ) Ω ]罪欧姆p0+罪[ tΩ ] _罪欧姆p1个Slerp(p0,p1;t)=sin⁡[(1−t)Ω]sin⁡Ωp0+sin⁡[tΩ]sin⁡Ωp1

它似乎是在 2016 年左右提出的,作为图像生成模型中潜在空间的插值。现在想起来,我感觉我在玩 GAN 的时候听到过类似的话……

arxiv.org

但这是否意味着可以在保持色散的同时改变高斯噪声呢?我对数学了解不多。好吧,如果你认为它只是通过改变球面上的角度来移动,那么范数不会改变,这样可以吗??这只是一种感觉...

我看了一下连接两个随机点的轨迹和sqrt用我上篇写的那个和用上面的那个,看看你真正用这个插值的时候会发生什么样的变化。slerp在二维和三维空间中绘制时,观察到以下差异。

不仅间距不同,而且轨迹显然也会不同。

执行

你引用的代码没问题,但是我会在PyTorch的前提下自己写Slerp。看起来它可以在不转换为 NumPy 的情况下进行计算。

def myslerp(
t: float, v0: torch.Tensor, v1: torch.Tensor, DOT_THRESHOLD: float = 0.9995
) -> torch.Tensor:
u0 = v0 / v0.norm()
u1 = v1 / v1.norm()
dot = (u0 * u1).sum()
if dot.abs() > DOT_THRESHOLD:
return (1 - t) * v0 + t * v1
omega = dot.acos()
return (((1.0 - t) * omega).sin() * v0 + (t * omega).sin() * v1) / omega.sin()

虽然只是按照上面公式中的定义来实现,但是还是要注意特殊情况。1理论上,当两个点从原点指向完全相同或相反的方向时,单位向量的点积是平坦的-1。但是,使用浮点值的多维数组进行计算时可能会出现一些错误。


for _ in range(10):
v0 = np.random.normal([1, 4, 64, 64])
v1 = 1.0 * v0
print((v0 * v1 / (np.linalg.norm(v0) * np.linalg.norm(v1))).sum())

<pre class="code" data-lang="" data-unlink="">0.9999999999999997
1.0
1.0
0.9999999999999998
0.9999999999999999
1.0
1.0
0.9999999999999998
1.0
1.0000000000000002</pre>

for _ in range(10):
v0 = np.random.normal([1, 4, 64, 64])
v1 = -1.0 * v0
print((v0 * v1 / (np.linalg.norm(v0) * np.linalg.norm(v1))).sum())

<pre class="code" data-lang="" data-unlink="">-1.0000000000000004
-1.0
-0.9999999999999998
-1.0
-1.0
-1.0
-0.9999999999999999
-1.0
-1.0000000000000002
-1.0</pre>

slerp在 中,我们需要从这个点积的值中arccos()找到角度,但是例如,如果np.arccos()参数不适合 和,将返回-1.0。还有,由于后面有一个除以这个角度的过程,所以即使返回了点积,也会出现在后面的计算中。所以,在这种情况下,通常线性连接会更好,而不是球形连接,所以看起来这个过程是分支的。1.0``nan``sin()``1.0``inf``DOT_THRESHOLD


※后记

正如您所指出的,在完全相反的方向的情况下,线性插值并不总是正确的,而不管完全相同的方向。比如插值和二维的时候,(1, 0)最好有一个不或者不经过原点的圆形轨道。如果两个点中有一个点被适度模糊,或者有一个点应该像上图那样清楚地通过,先从两个点插值到那个点,或许可以计算出这个可能。这似乎也取决于应用程序和案例。这次在Stable Diffusion中使用的随机数中,反方向的可能性似乎不大。(-1, 0)``(0, 1)``(0, -1)


好像这个小数点误差会有要看元素个数,计算顺序numpy等等。torch什么值被认为是线性的阈值(以上)0.9995似乎取决于具体情况。至少在Stable Diffusion 中使用的[4, 64, 64]形状生成随机数的情况下torch.randn(),点积通常0.1甚至达不到 ,所以在极端情况下,即使那么低似乎也不是问题。假设两个变形点之间不可能使用相同的噪声,那么即使没有分支也没有问题。

比较

slerp那么,当您将变形更改为实际使用时,变形会发生怎样的变化呢?slerp我在我之前发布的动漫女孩中制作了一个变形版本。

更改的时间是否有所改变?我感觉不出有什么大的不同。

考虑

毕竟,Stable Diffusion 可以生成任何类型的图像,只要它是高斯噪声,并且在两个指定点之间如何过渡可能没有任何区别。然而slerp,即使从角度线性变化的角度来看,我觉得我们可以期待一个更稳定的变化作为过渡中的移动量。倒不如说是随机完成了与上一篇文章中的方法类似的事情……?非常。

另外,这次我想使用高斯噪声,但slerp我认为该方法本身可以在任何地方使用,因此值得了解。此外,如果你有机会使用 StyleGAN,你也可以在那里尝试使用它。

此外,slerp应该可以对提示的嵌入结果使用变形,但那又如何呢?我没有试验过,但是我觉得从A到B最后会经过C,这是完全不相关的,只会增加不必要的变化,所以这是线性最短距离。我认为它会更好地过渡并仅调整步长。实际上,这两种方式都可能没有太大区别,并且可能取决于提示。在进行试错时将它作为一个选项似乎很好。

(https://memo.sugyan.com/entry/2022/09/09/230645)