Read file: modules/processing.py
Read file: modules/sd_samplers.py
Read file: modules/sd_samplers_kdiffusion.py
StableDiffusionProcessingTxt2Img 是 stable-diffusion-webui 中实现文本到图像生成的核心类。整个生成过程是一个复杂的管道,下面我将分步骤详细解析这个过程。
文本到图像生成的整个流程由 process_images 函数统筹,主要包括以下几个大的阶段:
StableDiffusionProcessingTxt2Img 类继承自 StableDiffusionProcessing,包含了多种参数:
python展开代码def __post_init__(self):
    super().__post_init__()
    
    # 如果指定了首阶段宽高,将其设为预处理尺寸,最终尺寸保存为目标尺寸
    if self.firstphase_width != 0 or self.firstphase_height != 0:
        self.hr_upscale_to_x = self.width
        self.hr_upscale_to_y = self.height
        self.width = self.firstphase_width
        self.height = self.firstphase_height
初始化阶段会设置生成过程中使用的尺寸。如果指定了首阶段尺寸,则先以小尺寸生成图像,随后放大。
python展开代码def setup_prompts(self):
    # 处理主提示词和负面提示词
    self.all_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_prompts]
    self.all_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_negative_prompts]
    
    # 处理高分辨率修复的提示词
    if self.enable_hr:
        self.all_hr_prompts = [shared.prompt_styles.apply_styles_to_prompt(x, self.styles) for x in self.all_hr_prompts]
        self.all_hr_negative_prompts = [shared.prompt_styles.apply_negative_styles_to_prompt(x, self.styles) for x in self.all_hr_negative_prompts]
提示词处理包括应用风格、解析额外网络标记(如LoRA、Textual Inversion),并转换为模型能理解的条件向量。
python展开代码def setup_conds(self):
    # 计算主提示和负面提示的条件向量
    self.uc = self.get_conds_with_caching(prompt_parser.get_learned_conditioning, 
                                         self.negative_prompts, self.steps, 
                                         [self.cached_uc, None], self.extra_network_data)
    
    self.c = self.get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, 
                                        self.prompts, self.steps, 
                                        [self.cached_c, None], self.extra_network_data)
每个提示词都被转换为条件向量,用于在生成过程中指导扩散模型。负面提示同样会被转换为条件向量,用于告诉模型应避免生成什么内容。
python展开代码def sample(self, conditioning, unconditional_conditioning, seeds, subseeds, subseed_strength, prompts):
    # 创建采样器
    self.sampler = sd_samplers.create_sampler(self.sampler_name, self.sd_model)
    
    # 获取随机噪声
    x = self.rng.next()
    
    # 执行采样(去噪)过程
    samples = self.sampler.sample(self, x, conditioning, unconditional_conditioning, 
                                  image_conditioning=self.txt2img_image_conditioning(x))
    
    # 如果不启用高分辨率修复,直接返回结果
    if not self.enable_hr:
        return samples
        
    # 否则进入高分辨率修复流程...
采样是整个生成过程的核心,主要步骤包括:
采样器(如 DPM++ 2M、Euler a 等)使用不同的数学方法进行去噪过程,影响最终图像的质量和风格。
python展开代码def sample_hr_pass(self, samples, decoded_samples, seeds, subseeds, subseed_strength, prompts):
    # 设置目标分辨率
    target_width = self.hr_upscale_to_x
    target_height = self.hr_upscale_to_y
    
    # 使用潜在空间上采样或图像上采样
    if self.latent_scale_mode is not None:
        # 潜在空间上采样
        samples = torch.nn.functional.interpolate(samples, 
                                                  size=(target_height // opt_f, target_width // opt_f), 
                                                  mode=self.latent_scale_mode["mode"], 
                                                  antialias=self.latent_scale_mode["antialias"])
    else:
        # 图像空间上采样
        batch_images = []
        for x_sample in lowres_samples:
            image = Image.fromarray(x_sample)
            image = images.resize_image(0, image, target_width, target_height, upscaler_name=self.hr_upscaler)
            batch_images.append(np.array(image))
        decoded_samples = torch.from_numpy(np.array(batch_images))
        samples = images_tensor_to_samples(decoded_samples)
    
    # 第二次采样(高分辨率修复)
    self.rng = rng.ImageRNG(samples.shape[1:], self.seeds)
    noise = self.rng.next()
    samples = self.sampler.sample_img2img(self, samples, noise, self.hr_c, self.hr_uc, 
                                         steps=self.hr_second_pass_steps or self.steps)
    
    return samples
高分辨率修复流程(当 enable_hr=True 时)包括:
denoising_strength 控制保留原始内容的程度这个过程允许生成分辨率远高于模型原始训练分辨率的图像,同时保持细节质量。
python展开代码# process_images_inner 函数中的片段
x_samples_ddim = decode_latent_batch(p.sd_model, samples_ddim, target_device=devices.cpu)
x_samples_ddim = torch.stack(x_samples_ddim).float()
x_samples_ddim = torch.clamp((x_samples_ddim + 1.0) / 2.0, min=0.0, max=1.0)
最后一步是将潜在空间的表示解码为实际图像:
采样器是生成过程的关键部分,直接影响图像质量和生成特性。以 KDiffusionSampler 为例:
python展开代码def sample(self, p, x, conditioning, unconditional_conditioning, steps=None, image_conditioning=None):
    steps = steps or p.steps
    sigmas = self.get_sigmas(p, steps)  # 计算噪声调度
    
    # 创建初始噪声
    x = x * sigmas[0]
    
    # 准备去噪参数
    self.model_wrap_cfg.init_latent = x
    self.sampler_extra_args = {
        'cond': conditioning,  # 条件向量(正面提示)
        'image_cond': image_conditioning,  # 图像条件(用于img2img)
        'uncond': unconditional_conditioning,  # 无条件向量(负面提示)
        'cond_scale': p.cfg_scale,  # 条件引导比例
    }
    
    # 执行采样算法
    samples = self.func(self.model_wrap_cfg, x, extra_args=self.sampler_extra_args, ...)
    
    return samples
采样器负责执行如 DDIM、DPM++、Euler 等去噪算法,通过噪声调度(sigmas)控制去噪过程,并使用条件向量(提示词编码)引导生成内容。
文本到图像的完整生成流程可以总结为:
这个过程涉及多个关键组件的协同工作,包括文本编码器、扩散模型、VAE解码器以及各种采样算法,最终实现从文本描述到高质量图像的转换。
通过理解这个过程,可以更好地调整参数以获得理想的生成结果,例如通过增加步数提高质量,通过调整 CFG scale 控制创意性与准确性的平衡,或通过高分辨率修复获得更高分辨率的输出。


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