AI图像生成模型Stable Diffusion完全教程

教程简介

本教程深入讲解Stable Diffusion图像生成模型的架构原理与实战应用,涵盖UNet/VAE/Text Encoder架构详解、SD 1.5/SDXL/SD 3.x/Flux版本对比、ComfyUI部署、Prompt工程、ControlNet精确控制、LoRA模型训练、图生图Inpainting、批量生成工作流等核心内容。

AI图像生成模型 Stable Diffusion 完全教程

1. Stable Diffusion 架构详解

Stable Diffusion 是一种潜在扩散模型(Latent Diffusion Model, LDM),其核心由三个关键组件构成:UNetVAEText Encoder。理解这三者的协作关系是掌握整个生成流程的基础。

1.1 VAE(变分自编码器)

VAE 的作用是将像素空间压缩到低维潜在空间(latent space),并在生成完成后将潜在表示解码回像素图像。原始图像(如 512×512×3)被编码为 64×64×4 的潜在表示,计算量大幅降低。

from diffusers import AutoencoderKL

# 加载预训练 VAE
vae = AutoencoderKL.from_pretrained(
    "stabilityai/sd-vae-ft-mse",
    torch_dtype=torch.float16
)

# 编码:像素空间 → 潜在空间
with torch.no_grad():
    latent = vae.encode(pixel_values).latent_dist.sample()
    latent = latent * 0.18215  # 缩放因子

# 解码:潜在空间 → 像素空间
with torch.no_grad():
    image = vae.decode(latent / 0.18215).sample

1.2 UNet(噪声预测网络)

UNet 是扩散模型的核心,负责在每个去噪步骤中预测噪声残差。它接收带噪的潜在表示、时间步嵌入和文本条件嵌入,输出预测的噪声。

from diffusers import UNet2DConditionModel

unet = UNet2DConditionModel.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    subfolder="unet",
    torch_dtype=torch.float16
)

# UNet 前向推理
noise_pred = unet(
    latent_model_input,      # 带噪潜在表示
    timestep,                # 当前去噪步数
    encoder_hidden_states=text_embeddings  # 文本条件
).sample

1.3 Text Encoder(文本编码器)

SD 1.x/2.x 使用 CLIP 文本编码器,将 prompt 文本转换为 77×768(SD 1.x)或 77×1024(SD 2.x)的嵌入向量。SDXL 则同时使用 CLIP 和 OpenCLIP 两个编码器拼接。

from transformers import CLIPTextModel, CLIPTokenizer

tokenizer = CLIPTokenizer.from_pretrained(
    "runwayml/stable-diffusion-v1-5", subfolder="tokenizer"
)
text_encoder = CLIPTextModel.from_pretrained(
    "runwayml/stable-diffusion-v1-5", subfolder="text_encoder"
)

# 文本编码
tokens = tokenizer(
    "a photo of a cat",
    padding="max_length",
    max_length=77,
    return_tensors="pt"
)
text_embeddings = text_encoder(tokens.input_ids)[0]

1.4 完整去噪循环

整个生成过程是一个迭代去噪循环:

from diffusers import PNDMScheduler

scheduler = PNDMScheduler.from_pretrained(
    "runwayml/stable-diffusion-v1-5", subfolder="scheduler"
)
scheduler.set_timesteps(50)

# 从纯高斯噪声开始
latents = torch.randn((1, 4, 64, 64)).half()

for t in scheduler.timesteps:
    latent_input = scheduler.scale_model_input(latents, t)
    noise_pred = unet(latent_input, t, text_embeddings).sample
    latents = scheduler.step(noise_pred, t, latents).prev_sample

# 解码最终潜在表示
image = vae.decode(latents / 0.18215).sample

2. 主流版本对比

SD 1.5

  • 发布:2022年10月,Runway ML 发布
  • 分辨率:默认 512×512
  • 文本编码器:CLIP ViT-L/14(768维)
  • 优势:生态最成熟,社区模型、LoRA、ControlNet 资源最丰富
  • 劣势:分辨率低,复杂语义理解能力有限

SDXL

  • 发布:2023年7月,Stability AI 发布
  • 分辨率:默认 1024×1024
  • 文本编码器:CLIP ViT-L/14 + OpenCLIP ViT-bigG/14(拼接 2048维)
  • 新增:Refiner 模型(二次精修)、Conditioner 架构改进
  • 优势:画质显著提升,语义理解更强
  • 劣势:显存需求更高(至少 8GB),推理速度较慢

SD 3.x / SD3.5

  • 发布:2024年
  • 架构变革:采用 MMDiT(多模态扩散 Transformer)替代 UNet,文本和图像在 Transformer 内深度融合
  • 文本编码器:CLIP × 2 + T5-XXL(4096维)
  • 优势:文字渲染能力大幅提升,构图和细节质量更高
  • 劣势:T5-XXL 占用大量显存,社区生态尚未完全跟上

Flux

  • 发布:2024年8月,Black Forest Labs(Stability AI 核心团队出走后创建)
  • 代表模型:Flux.1 Dev / Flux.1 Schnell
  • 架构:基于 DiT(Diffusion Transformer),采用 Flow Matching 训练
  • 分辨率:原生支持 1024×1024 及更高
  • 优势:图像质量极佳,人体结构、手部细节处理出色,提示词遵循度高
  • 劣势:模型体积大(12B 参数),推理速度较慢,社区微调生态初期

3. 环境搭建与本地部署

3.1 硬件要求

组件 最低配置 推荐配置
GPU NVIDIA 6GB VRAM NVIDIA 12GB+ VRAM
内存 16GB 32GB
硬盘 20GB SSD 100GB+ NVMe SSD

3.2 ComfyUI 部署

ComfyUI 采用节点式工作流,灵活性极高,适合进阶用户。

# 克隆仓库
git clone https://github.com/comfyanonymous/ComfyUI.git
cd ComfyUI

# 创建虚拟环境
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate   # Windows

# 安装依赖
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
pip install -r requirements.txt

# 启动
python main.py --listen 0.0.0.0 --port 8188

模型文件放置目录约定:

ComfyUI/
├── models/
│   ├── checkpoints/      # 主模型 (.safetensors)
│   ├── loras/            # LoRA 权重
│   ├── vae/              # VAE 模型
│   ├── controlnet/       # ControlNet 模型
│   └── clip/             # CLIP 模型

3.3 Automatic1111 (WebUI) 部署

git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
cd stable-diffusion-webui

# Linux/Mac 一键启动(自动创建 venv 并安装依赖)
./webui.sh --listen --port 7860

# Windows
webui-user.bat

常用启动参数:

./webui.sh \
  --xformers \              # 启用 xformers 加速
  --medvram \               # 中等显存优化
  --api \                   # 启用 API 模式
  --enable-insecure-extension-access  # 允许安装扩展

4. Prompt Engineering 进阶技巧

4.1 权重语法

(beautiful sunset:1.3), over (calm ocean:1.1), 
(photorealistic:1.2), (sharp focus:0.9)
  • (keyword:1.3) — 增加权重至 1.3 倍
  • (keyword:0.7) — 降低权重至 0.7 倍
  • (keyword) — 等同于 (keyword:1.1)
  • [keyword] — 等同于 (keyword:0.91)

4.2 Prompt 结构模板

高质量 prompt 通常遵循以下结构:

[主体描述], [环境/背景], [风格/媒介], [光照], [构图], [质量标签]

示例:

A young woman reading a book in a cozy cafe, 
warm ambient lighting, golden hour rays through window,
oil painting style, impressionist brushstrokes,
soft bokeh background, rule of thirds composition,
masterpiece, best quality, highly detailed

4.3 Negative Prompt 策略

# 通用负面提示词
(worst quality:1.4), (low quality:1.4), (normal quality:1.4),
lowres, blurry, bad anatomy, bad hands, extra fingers,
missing fingers, cropped, watermark, text, signature,
deformed, ugly, duplicate, morbid, mutilated

4.4 交替提示词(Alternating Prompts)

在 ComfyUI 或 A1111 中,可以在采样过程中交替使用不同提示词:

[cow|horse]  → 第一步用 cow,第二步用 horse,交替进行

5. ControlNet 精确控制生成

ControlNet 通过附加条件图(边缘图、深度图、姿态图等)精确控制生成结果的结构。

5.1 常用预处理器

预处理器 用途 适用场景
Canny 边缘检测 保留轮廓线条
Depth (MiDaS/Zoe) 深度估计 控制空间关系
OpenPose 人体姿态 控制人物动作
Scribble 涂鸦线稿 草图转成品
SoftEdge 柔和边缘 更自然的轮廓
Lineart 线稿提取 动漫/插画风格

5.2 代码调用 ControlNet

from diffusers import (
    StableDiffusionControlNetPipeline,
    ControlNetModel,
    UniPCMultistepScheduler
)
from controlnet_aux import CannyDetector
from PIL import Image

# 加载 ControlNet
controlnet = ControlNetModel.from_pretrained(
    "lllyasviel/sd-controlnet-canny",
    torch_dtype=torch.float16
)

# 构建管线
pipe = StableDiffusionControlNetPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    controlnet=controlnet,
    torch_dtype=torch.float16
).to("cuda")
pipe.scheduler = UniPCMultistepScheduler.from_config(pipe.scheduler.config)

# 预处理:提取 Canny 边缘
canny = CannyDetector()
source_image = Image.open("input.jpg")
control_image = canny(source_image, low_threshold=100, high_threshold=200)

# 生成
result = pipe(
    prompt="a beautiful anime girl, masterpiece",
    negative_prompt="low quality, bad anatomy",
    image=control_image,
    num_inference_steps=30,
    controlnet_conditioning_scale=0.8,  # ControlNet 影响强度
    guidance_scale=7.5
).images[0]

result.save("output.png")

5.3 多 ControlNet 叠加

可以同时使用多个 ControlNet 进行多维度控制:

from diffusers import StableDiffusionControlNetPipeline, MultiControlNetModel

controlnet_canny = ControlNetModel.from_pretrained("lllyasviel/sd-controlnet-canny")
controlnet_depth = ControlNetModel.from_pretrained("lllyasviel/sd-controlnet-depth")

multi_controlnet = MultiControlNetModel([controlnet_canny, controlnet_depth])

pipe = StableDiffusionControlNetPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    controlnet=multi_controlnet,
    torch_dtype=torch.float16
).to("cuda")

result = pipe(
    prompt="a futuristic cityscape",
    image=[canny_image, depth_image],
    controlnet_conditioning_scale=[0.6, 0.4]  # 分别控制两个条件的强度
).images[0]

6. LoRA 模型训练实战

LoRA(Low-Rank Adaptation)通过在注意力层注入低秩矩阵,以极小的参数量实现模型微调。

6.1 数据集准备

dataset/
├── 10_my_style/          # 文件夹名前缀数字 = 重复次数
│   ├── image01.png
│   ├── image01.txt       # 对应的 caption 文本
│   ├── image02.png
│   ├── image02.txt
│   └── ...

caption 文件内容示例:

a painting in my_style, abstract oil painting, vibrant colors, bold brushstrokes

6.2 使用 kohya-ss 训练

# 安装 kohya-ss
git clone https://github.com/kohya-ss/sd-scripts.git
cd sd-scripts
pip install -r requirements.txt

# 启动训练(SD 1.5 LoRA 示例)
accelerate launch train_network.py \
  --pretrained_model_name_or_path="runwayml/stable-diffusion-v1-5" \
  --train_data_dir="./dataset" \
  --output_dir="./output_lora" \
  --output_name="my_style_lora" \
  --resolution=512 \
  --train_batch_size=1 \
  --max_train_epochs=10 \
  --learning_rate=1e-4 \
  --network_module=networks.lora \
  --network_dim=32 \
  --network_alpha=16 \
  --mixed_precision="fp16" \
  --save_every_n_epochs=2 \
  --seed=42

关键参数说明:

  • network_dim:LoRA 秩(rank),越大拟合能力越强,通常 4-128
  • network_alpha:缩放因子,通常设为 dim 的一半
  • learning_rate:学习率,1e-4 是常用起点

6.3 推理时加载 LoRA

from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16
).to("cuda")

# 加载 LoRA 权重
pipe.load_lora_weights("./output_lora", weight_name="my_style_lora.safetensors")

# 触发词 + LoRA 权重
image = pipe(
    prompt="a landscape in my_style, mountain and lake, sunset",
    num_inference_steps=30
).images[0]

7. 图生图与 Inpainting

7.1 图生图(Image-to-Image)

基于已有图像进行风格转换或细节调整,通过 strength 参数控制偏离原图的程度:

from diffusers import StableDiffusionImg2ImgPipeline

pipe = StableDiffusionImg2ImgPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16
).to("cuda")

init_image = Image.open("photo.jpg").resize((512, 512))

result = pipe(
    prompt="oil painting of a landscape, impressionist style",
    image=init_image,
    strength=0.75,          # 0=完全保留原图, 1=完全重新生成
    guidance_scale=7.5,
    num_inference_steps=50
).images[0]

7.2 Inpainting(局部重绘)

仅修改图像的指定区域,其余部分保持不变:

from diffusers import StableDiffusionInpaintPipeline

pipe = StableDiffusionInpaintPipeline.from_pretrained(
    "runwayml/stable-diffusion-inpainting",
    torch_dtype=torch.float16
).to("cuda")

image = Image.open("photo.jpg").resize((512, 512))
mask = Image.open("mask.png").resize((512, 512))  # 白色区域=需要重绘

result = pipe(
    prompt="a cute puppy sitting on the grass",
    image=image,
    mask_image=mask,
    num_inference_steps=30,
    guidance_scale=7.5
).images[0]

8. 批量生成工作流

8.1 基础批量生成脚本

import os
import csv
from diffusers import StableDiffusionPipeline

pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16
).to("cuda")
pipe.enable_attention_slicing()  # 降低显存占用

# 从 CSV 读取 prompt 列表
prompts = []
with open("prompts.csv", "r") as f:
    reader = csv.DictReader(f)
    for row in reader:
        prompts.append({
            "prompt": row["prompt"],
            "negative": row.get("negative", ""),
            "seed": int(row.get("seed", 42))
        })

output_dir = "batch_output"
os.makedirs(output_dir, exist_ok=True)

for i, item in enumerate(prompts):
    generator = torch.Generator("cuda").manual_seed(item["seed"])
    image = pipe(
        prompt=item["prompt"],
        negative_prompt=item["negative"],
        generator=generator,
        num_inference_steps=30,
        guidance_scale=7.5
    ).images[0]
    image.save(f"{output_dir}/output_{i:04d}.png")
    print(f"[{i+1}/{len(prompts)}] Done")

8.2 ComfyUI 批量工作流

在 ComfyUI 中,可以通过 API 模式批量提交工作流:

import json
import requests

# 加载工作流模板
with open("workflow_api.json", "r") as f:
    workflow = json.load(f)

prompt_variants = [
    "a cat sitting on a windowsill",
    "a dog playing in the park",
    "a bird perched on a branch"
]

for i, prompt_text in enumerate(prompt_variants):
    # 替换工作流中的 prompt 节点
    workflow["6"]["inputs"]["text"] = prompt_text
    workflow["3"]["inputs"]["seed"] = 42 + i

    # 提交到 ComfyUI API
    response = requests.post(
        "http://127.0.0.1:8188/prompt",
        json={"prompt": workflow}
    )
    print(f"Submitted job {i}: {response.json()['prompt_id']}")

9. 模型微调与自训练

9.1 DreamBooth 全量微调

DreamBooth 使用少量(5-30张)特定主题图片,教会模型新的概念:

accelerate launch train_dreambooth.py \
  --pretrained_model_name_or_path="runwayml/stable-diffusion-v1-5" \
  --instance_data_dir="./my_dog_photos" \
  --instance_prompt="a photo of sks dog" \
  --class_data_dir="./regularization" \
  --class_prompt="a photo of dog" \
  --output_dir="./dreambooth_output" \
  --resolution=512 \
  --train_batch_size=1 \
  --gradient_accumulation_steps=1 \
  --learning_rate=5e-6 \
  --lr_scheduler="constant" \
  --max_train_steps=800 \
  --prior_loss_weight=1.0 \
  --mixed_precision="fp16"

9.2 Textual Inversion

只训练新的文本嵌入向量,不修改模型权重,文件体积小(几十 KB):

accelerate launch textual_inversion.py \
  --pretrained_model_name_or_path="runwayml/stable-diffusion-v1-5" \
  --train_data_dir="./dataset" \
  --learnable_property="object" \
  --placeholder_token="<my-cat>" \
  --initializer_token="cat" \
  --output_dir="./textual_inversion_output" \
  --resolution=512 \
  --train_batch_size=1 \
  --max_train_steps=3000 \
  --learning_rate=5e-4 \
  --mixed_precision="fp16"

10. 商业应用场景

10.1 电商产品图

场景:自动生成产品展示图、场景图、模特穿搭图

Prompt 模板:
"a [product] on a minimalist white surface, 
soft studio lighting, commercial photography, 
8k, hyper-realistic, professional product shot"

工作流

  1. 拍摄白底产品图 → ControlNet Canny 提取轮廓
  2. 生成多种场景背景 → Inpainting 融合产品
  3. 批量生成不同角度/场景

10.2 广告创意

利用 SDXL/Flux 的高质量输出快速生成广告素材初稿,再由设计师精修。结合 ControlNet 保证品牌视觉一致性(固定构图、色彩方案)。

10.3 游戏与影视概念设计

"concept art, [character description], 
fantasy illustration, artstation trending, 
detailed environment, cinematic lighting, 
by Greg Rutkowski and Alphonse Mucha"

批量生成角色/场景变体,大幅缩短前期概念设计周期。


11. API 集成与自动化

11.1 调用 Stability AI 官方 API

import requests

API_KEY = "your-stability-api-key"

response = requests.post(
    "https://api.stability.ai/v1/generation/stable-diffusion-xl-1024-v1-0/text-to-image",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
        "Accept": "application/json"
    },
    json={
        "text_prompts": [
            {"text": "a serene Japanese garden, autumn leaves", "weight": 1},
            {"text": "blurry, low quality", "weight": -1}
        ],
        "cfg_scale": 7,
        "height": 1024,
        "width": 1024,
        "samples": 1,
        "steps": 30
    }
)

import base64
data = response.json()
for i, image_data in enumerate(data["artifacts"]):
    with open(f"api_output_{i}.png", "wb") as f:
        f.write(base64.b64decode(image_data["base64"]))

11.2 本地 Diffusers API 服务

使用 diffusers 自建 REST API:

from fastapi import FastAPI
from pydantic import BaseModel
from diffusers import StableDiffusionPipeline
import torch, base64, io

app = FastAPI()

pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype=torch.float16
).to("cuda")

class GenerateRequest(BaseModel):
    prompt: str
    negative_prompt: str = ""
    steps: int = 30
    guidance_scale: float = 7.5
    width: int = 512
    height: int = 512
    seed: int = 42

@app.post("/generate")
def generate(req: GenerateRequest):
    generator = torch.Generator("cuda").manual_seed(req.seed)
    image = pipe(
        prompt=req.prompt,
        negative_prompt=req.negative_prompt,
        num_inference_steps=req.steps,
        guidance_scale=req.guidance_scale,
        width=req.width,
        height=req.height,
        generator=generator
    ).images[0]

    buffer = io.BytesIO()
    image.save(buffer, format="PNG")
    return {"image": base64.b64encode(buffer.getvalue()).decode()}

启动服务后,任何语言都可以通过 HTTP 调用生成图像,实现与现有业务系统的无缝集成。


掌握 Stable Diffusion 的关键在于理解其三大组件的协作机制,再通过 ControlNet、LoRA 等工具精确控制输出。从本地实验到 API 自动化部署,这套工具链能够覆盖从个人创作到企业级批量生产的全部需求。

内容声明

本文内容为AI技术学习教程,仅供学习参考。如涉及技术问题,欢迎通过 xurj005@163.com 与我们交流。

目录