Stable Diffusion的文本转图像过程是一个复杂的流程,文本提示(prompt)会被转换成嵌入向量,然后通过条件扩散模型引导图像生成。以下是完整的流程:
当您输入文本提示时,首先会经过以下处理:
文本首先被分解成标记(tokens),这是由CLIP文本编码器完成的:
python展开代码# modules/sd_hijack_clip.py
def tokenize(self, texts):
    # 将文本转换成token标记ID列表
    tokenized = self.wrapped.tokenizer(texts, truncation=False, add_special_tokens=False)["input_ids"]
    return tokenized
例如,"a photo of a cat"会被分解成["a", "photo", "of", "a", "cat"]等标记,然后转换为数字ID。
标记化后的文本会通过CLIP的文本编码器转换为嵌入向量:
python展开代码# modules/sd_hijack_clip.py
def encode_with_transformers(self, tokens):
    # 对标记进行编码,生成隐藏状态
    outputs = self.wrapped.transformer(input_ids=tokens, output_hidden_states=-opts.CLIP_stop_at_last_layers)
    
    if opts.CLIP_stop_at_last_layers > 1:
        z = outputs.hidden_states[-opts.CLIP_stop_at_last_layers]
        z = self.wrapped.transformer.text_model.final_layer_norm(z)
    else:
        z = outputs.last_hidden_state
        
    return z
这将每个标记转换为一个高维向量(SD1.5是768维,SDXL是1024维)。
处理类StableDiffusionProcessing中的get_conds方法获取条件向量:
python展开代码# modules/processing.py
def get_conds(self):
    # 返回文本条件向量(c)和无条件向量(uc)
    return self.c, self.uc
这里会返回两个关键的条件向量:
在采样过程开始时,文本条件被传递给采样器:
python展开代码# modules/sd_samplers_kdiffusion.py
self.sampler_extra_args = {
    'cond': conditioning,           # 正面提示的条件向量
    'image_cond': image_conditioning,
    'uncond': unconditional_conditioning,  # 负面提示的无条件向量
    'cond_scale': p.cfg_scale,      # CFG缩放比例
    's_min_uncond': self.s_min_uncond
}
CFG缩放在CFGDenoiser.forward方法中实现,这是文本条件实际影响图像生成的关键部分:
python展开代码# modules/sd_samplers_cfg_denoiser.py
def forward(self, x, sigma, uncond, cond, cond_scale, s_min_uncond, image_cond):
    # ... [代码省略]
    
    # 对噪声图像应用模型,获取噪声预测
    x_out = self.inner_model(x_in, sigma_in, cond=make_condition_dict(cond_in, image_cond_in))
    
    # ... [代码省略]
    
    # 关键公式:结合条件和无条件预测
    denoised = self.combine_denoised(x_out, conds_list, uncond, cond_scale)
    
    # ... [代码省略]
    
    return denoised
文本提示通过以下公式直接影响每一步的去噪过程:
python展开代码# modules/sd_samplers_cfg_denoiser.py
def combine_denoised(self, x_out, conds_list, uncond, cond_scale):
    denoised_uncond = x_out[-uncond.shape[0]:]  # 无条件预测结果
    denoised = torch.clone(denoised_uncond)     # 从无条件结果开始
    # 应用条件预测的影响,加权以cond_scale(也就是CFG Scale)
    for i, conds in enumerate(conds_list):
        for cond_index, weight in conds:
            denoised[i] += (x_out[cond_index] - denoised_uncond[i]) * (weight * cond_scale)
    return denoised
这个公式的简化版本是:
最终预测 = 无条件预测 + CFG_Scale × (条件预测 - 无条件预测)
以数学形式表示:
其中:
当您提供一个文本提示如"一只漂亮的黑猫"时:
提示被标记化并通过CLIP文本编码器转换成嵌入向量
同样,负面提示也被编码成嵌入向量
采样过程开始,执行多步去噪
在每个去噪步骤:
经过多次迭代后,最终的潜在表示被解码成像素图像
CFG Scale参数直接控制了文本提示的影响程度:
当您使用提示"一只漂亮的黑猫"时:
文本提示通过CLIP文本编码器转换为条件向量,然后在每个采样步骤中通过CFG机制引导去噪过程。CFG Scale参数控制文本提示对生成过程的影响程度,使Stable Diffusion能够根据用户的文本描述生成相应的图像。整个过程是一个精妙的平衡,既保持了生成的多样性,又确保了与文本提示的相关性。


本文作者:Dong
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!