AI 图片与视频处理 — 从原理到实践

摘要:AI 图片/视频处理与文本 LLM 分属两种技术范式------前者处理"像素空间的生成与变换",后者处理"语义空间的推理与补全"。图片模型的额外复杂度不在于"是否本地部署",而在于推理过程是多个子模型协作的管线。


一、能力全景:AI 在图片与视频领域的边界

在深入技术细节之前,首先建立对 AI 图片/视频处理能力的整体认知------它能做什么、不能做什么,以及整个工具生态的分层结构。

1.1 六类图片任务

复制代码
                    输入             输出              典型用例
─────────────────────────────────────────────────────────────
① 文生图         一段文字          一张新图           根据描述生成全新图片
② 图生图         一张图+文字      一张变体图          将照片转换为特定艺术风格
③ Inpainting     一张图+遮罩      一张修复图          移除画面中的多余物体
④ Outpainting    一张图          一张扩展图          扩展画幅,AI 补全新增区域
⑤ 超分放大       一张小图        一张大图            提升分辨率并保持清晰度
⑥ 图片理解       一张图          一段文字            识别内容、提取结构化信息

上述六类任务并非各自对应独立的模型------其底层共享同一套扩散模型架构,区别仅在于输入条件的不同组合。

1.2 视频任务

任务 输入 → 输出
文生视频 一段文字 → 一段数秒的视频
图生视频 一张静态图片 → 动态视频
视频编辑 一段视频 + 文字指令 → 修改后的视频
视频超分 低分辨率视频 → 高分辨率视频
风格迁移 视频 → 应用特定风格的视频

1.3 当前技术的局限性

  • ❌ 在保留真实背景的前提下移除大面积物体------生成式模型倾向于"虚构"背景内容,而非"延续"原有场景
  • ❌ 生成图片中的文字准确渲染(2026 年刚取得突破,仍未完全解决)
  • ❌ 长视频(超过 2 分钟)中保持角色外貌和场景风格的一致性
  • ❌ 精确控制人体细节部位(手指数量、牙齿形态等常见问题)
  • ❌ 在消费级显卡(8GB VRAM)上进行 4K 视频生成

1.4 五层生态结构

AI 图片/视频处理的工具链可划分为五个层次。理解这一分层结构,有助于在接触新工具时快速定位其所属层级和依赖关系。

复制代码
┌─────────────────────────────────────────────────────────┐
│  第 5 层:用户界面                                       │
│  ComfyUI(节点式编排) / WebUI(图形界面) / 代码直接调用   │
├─────────────────────────────────────────────────────────┤
│  第 4 层:模型权重(.safetensors / .ckpt 文件)           │
│  FLUX.1 / SD 3.5 / Qwen-Image / Wan 2.7 / Kling ...    │
│  训练得到的参数文件,日常所说的"下载模型"即指此层           │
├─────────────────────────────────────────────────────────┤
│  第 3 层:工具库(Python 包)                             │
│  diffusers / transformers / opencv / onnxruntime        │
│  将第 2 层的底层操作封装为高层 API                        │
├─────────────────────────────────────────────────────────┤
│  第 2 层:深度学习框架                                    │
│  PyTorch / ONNX Runtime / llama.cpp                     │
│  AI 模型的运行时环境,类比 Java 程序的 JVM                │
│                                                        │
│  注:文本 LLM 还有另一条技术路线------llama.cpp(C++ 实现),  │
│  完全不依赖 PyTorch,直接被 Ollama 用作底层推理引擎。      │
│  图片模型当前以 PyTorch + diffusers 路线为主,暂无          │
│  llama.cpp 等价物(多组件管线难以用统一 C++ 引擎覆盖)。    │
├─────────────────────────────────────────────────────────┤
│  第 1 层:硬件与驱动                                      │
│  NVIDIA GPU + CUDA + cuDNN                              │
│  AI 推理的物理计算基础;无 GPU 时可使用 CPU,但速度大幅下降  │
└─────────────────────────────────────────────────────────┘

关键认知

  • 日常所说的"下载一个模型",实际下载的是第 4 层的 .safetensors 权重文件。但该文件必须依赖第 1~3 层的完整环境才能运行------下面三层缺一不可。
  • Ollama 的特殊性:Ollama 的管理层(Go 编写)负责模型下载和 API 暴露,但其底层推理引擎是 llama.cpp(C++),这个引擎绕过了 PyTorch(第 2 层)直接从 CUDA/CPU 执行推理。因此 Ollama 在技术栈上跨越了第 2-3 层------它用一个统一的可执行文件同时替代了"框架+库"的角色。图片模型领域暂无此类统一工具。

1.5 远程 API 与本地部署

一个常见误解是"图片模型必须下载到本地才能使用"。实际上,图片模型与文本 LLM 一样,同时支持远程 API 调用和本地部署两种模式。

python 复制代码
# 文本 LLM 的 API 调用(常见模式)
from openai import OpenAI
client = OpenAI(base_url="https://api.deepseek.com", api_key="sk-xxx")
response = client.chat.completions.create(model="deepseek-chat", messages=[...])

# 图片模型的 API 调用------调用方式完全一致,仅端点不同
from openai import OpenAI
client = OpenAI(base_url="https://api.siliconflow.cn/v1", api_key="sk-xxx")
response = client.images.generate(model="FLUX.1-dev", prompt="一只猫")
复制代码
                    文本 LLM                        图片模型
                    ────────                       ────────
远程 API 模式      调用 DeepSeek API               调用 Kling / SiliconFlow API
                   → 模型运行在服务端                → 模型运行在服务端
                   → 本地无需 GPU                    → 本地无需 GPU
                   → 按 Token 量计费                → 按张数或时长计费

本地部署模式       Ollama + Qwen 本地运行           diffusers + FLUX 本地运行
                   → 模型权重下载至本地              → 模型权重下载至本地
                   → 免费,需配备 GPU               → 免费,需配备 GPU
                   → 单一模型推理                    → 多子模型管线(额外复杂度来源)

远程 API 与本地部署并非互斥选择,而是两种按需切换的使用模式。 学习阶段建议走本地路线以理解管线原理,生产环境则按场景灵活选择。


二、环境地基:五层生态的逐层解析

第一章介绍了五层生态结构的全貌,本章自底向上逐层展开------说明每层是什么、为什么需要、以及如何验证安装正确。

2.1 第 1 层:CUDA --- AI 推理的物理引擎

复制代码
Python 代码
    ↓
PyTorch("执行矩阵乘法运算")
    ↓
CUDA(将运算指令翻译为 GPU 可执行的指令)
    ↓
GPU 硬件(数千计算核心并行处理)
    ↓
返回计算结果
  • 无 NVIDIA 显卡 → 只能使用 CPU 进行推理 → 速度下降 10-100 倍,但推理仍可进行
  • 有 NVIDIA 显卡但未安装 CUDA → PyTorch 检测不到 GPU → 自动回退至 CPU 模式
  • CUDA 版本与 PyTorch 版本必须匹配------约 80% 的环境问题源于此二者版本不兼容

2.2 第 2 层:PyTorch --- AI 模型的运行时

PyTorch 是所有 AI 模型推理的运行时环境。类比:运行 Java 程序需要 JVM,运行 AI 模型需要 PyTorch。

提供的两项核心能力:

  1. 张量运算 :numpy 的 GPU 加速等价物(torch.Tensor 的数据模型与 numpy.ndarray 类似,但可在 GPU 上执行)
  2. 自动求导:训练阶段使用,推理阶段不需要,但模型的网络结构定义依赖此机制

Python 3.14 无法安装 PyTorch 的原因:PyTorch 底层包含大量 C++ 扩展代码(CUDA 交互层、算子优化等),需针对各 Python 版本分别编译。每当新的 Python 版本发布,PyTorch 团队需要适配周期。截至 2026 年 7 月,PyTorch 最高支持 Python 3.12。

2.3 第 3 层:工具库 --- 各 Python 包的功能定位

PyTorch 仅提供"张量运算"这一基础能力,不具备"加载模型并完成推理全流程"的高层功能:

python 复制代码
# 仅使用 PyTorch 时,需手动实现以下全部步骤:
# - 从二进制文件解析模型权重
# - 按模型结构逐层构建网络(通常需要数百行代码定义 UNet)
# - 实现去噪循环(Scheduler 的完整数学公式)
# - 处理 Tokenizer 与 Text Encoder 的调用逻辑
# - VAE 编解码的前后处理
# 工作量约 500+ 行代码,且更换模型后大部分代码需重写

# 使用 diffusers 之后的等价代码:
from diffusers import StableDiffusionPipeline
pipe = StableDiffusionPipeline.from_pretrained("model-name")
image = pipe("a cat").images[0]
# 3 行代码。diffusers 封装了上述所有步骤。
库名 功能定位 若不使用的后果
torch GPU 加速的张量计算(GPU 上的 numpy) 无法运行任何 AI 模型
diffusers 扩散模型的管线工厂,一行加载、一行推理 需手写数百行管线编排代码
transformers 文本编码器的管线工厂(diffusers 内部依赖其处理 Prompt) diffusers 会自动安装
opencv-contrib-python-headless 经典图像处理操作 + DNN 模型推理 + 超分辨率模块 图片读写、缩放、超分均需另寻替代方案
accelerate 自动处理模型在 GPU/多 GPU/混合精度上的分配 需手动编写 .to("cuda") 及显存管理逻辑
Pillow (PIL) Python 最基础的图片读写库 无法打开/保存 jpg、png 等常见格式(同时也是 OpenCV 中文路径问题的兼容方案)
huggingface_hub 从 HuggingFace 自动下载模型权重文件 需手动从网页下载并指定本地路径
onnxruntime 使模型脱离 PyTorch 环境独立运行(用于部署场景) 部署包体积大、冷启动慢
ultralytics YOLO 目标检测("识别图中所有人物位置") 无法执行目标检测任务
xformers 优化注意力机制的计算效率与显存占用(可节省约 30% 显存) 同等条件下显存更紧张、推理更慢
bitsandbytes 8-bit/4-bit 量化推理("将 23GB 模型压缩至 6GB") 大模型在消费级显卡上无法运行

2.4 第 4 层:模型权重 --- .safetensors 文件的本质

bash 复制代码
# FLUX.1-dev 模型权重文件的目录结构
~/.cache/huggingface/hub/models--black-forest-labs--FLUX.1-dev/
├── model_index.json       # 记录该模型由哪些子模型组件构成
├── transformer/           # 主去噪网络(UNet/DiT)的权重 → 约 23GB
│   └── diffusion_pytorch_model.safetensors
├── vae/                   # VAE 编解码器的权重 → 约 300MB
│   └── diffusion_pytorch_model.safetensors
├── text_encoder/          # 文本编码器的权重 → 约 3GB
│   └── model.safetensors
└── scheduler/             # 去噪策略的配置(不包含权重,仅数学公式参数)
    └── scheduler_config.json

模型权重文件不包含原始训练数据

复制代码
常见误解:下载 FLUX 模型(约 12GB)= 下载了模型训练时见过的所有图片的压缩版本
实际情况:原始训练数据(数十亿张图片,PB 级存储规模)
          → 经过训练过程(GPU 集群运行数周至数月)
          → 产出一个 .safetensors 权重文件(约 12GB 的浮点参数矩阵)

类比:一个人看过几千张猫的照片后,大脑中并未存储这几千张照片的副本,
      但形成了"猫的外貌特征"这一抽象认知。
模型权重 = 训练得到的"识别与生成规律",而非训练数据的压缩存储。

远程 API 服务与本地部署使用的是同一份模型权重。 区别仅在于由谁的硬件执行推理------API 服务商的 A100 数据中心 GPU,还是个人的 RTX 4060 消费级显卡。在硬件性能相当的前提下,推理结果的质量没有差异。

2.5 第 5 层:用户界面 --- 两种交互范式

范式 适用场景 代表工具
编程接口 开发者、需要自动化或批量处理的场景 diffusers Python API
可视化编排 设计师、不编写代码、需要直观调节参数 ComfyUI

ComfyUI 的底层同样调用 diffusers 库。用户在 ComfyUI 中通过拖拽节点构建的工作流,本质上等价于一段 diffusers Python 脚本。掌握 diffusers 编程接口后,ComfyUI 只是换了一种交互方式,核心概念完全相通。

2.6 环境安装验证清单

以下 4 条验证命令全部通过,即说明环境已就绪:

bash 复制代码
# ① GPU 是否可用
python -c "import torch; print(torch.cuda.is_available())"  # → True

# ② CUDA 版本与 PyTorch 版本是否匹配(示例为 CUDA 12.1)
python -c "import torch; print(torch.version.cuda)"          # → 12.1
python -c "import torch; print(torch.__version__)"           # → 2.x.x+cu121

# ③ diffusers 能否正常加载模型管线
python -c "from diffusers import DiffusionPipeline; print('OK')"  # → OK

# ④ OpenCV 扩展模块(dnn_superres)是否完整安装
python -c "import cv2; cv2.dnn_superres.DnnSuperResImpl_create()"  # → 对象创建成功

三、第一张 AI 图片:从代码到理解

环境就绪后,本章从一段最小可运行代码开始------先看到结果,再逐层拆解"一行推理调用背后发生了什么",最终建立对扩散模型推理全流程的结构化认知。

3.1 最小可运行示例

python 复制代码
from diffusers import AutoPipelineForText2Image
import torch

# ① 加载管线(首次运行自动下载 FLUX.1-schnell 模型,约 12GB)
pipe = AutoPipelineForText2Image.from_pretrained(
    "black-forest-labs/FLUX.1-schnell",
    torch_dtype=torch.bfloat16
)
pipe.to("cuda")

# ② 生成图片
image = pipe(
    prompt="一只橘猫戴着墨镜坐在沙滩上,日落光线,电影质感"
).images[0]

# ③ 保存结果
image.save("my_first_ai_image.jpg")

以上共 6 行有效代码,运行后在当前目录生成一张 AI 创作的图片。

3.2 一行推理调用背后的六个步骤

pipe(prompt) 这一行看似简洁的调用,内部实际顺序执行了六个步骤:

复制代码
用户输入:prompt="一只橘猫戴着墨镜坐在沙滩上..."
    │
    ▼
┌─────────────────────────────────────────────────────────┐
│ 步骤①:Text Encoder(文本编码)                           │
│                                                         │
│  "一只橘猫戴着墨镜..." → CLIP / T5 模型 → 语义向量        │
│  将自然语言描述转换为模型可理解的数值条件信号               │
│  输出:4096 维(FLUX)向量,编码了"猫""墨镜""沙滩"等语义   │
├─────────────────────────────────────────────────────────┤
│ 步骤②:随机种子 → 初始噪声                               │
│                                                         │
│  torch.randn(...) → 在潜空间中生成纯随机噪声              │
│  512×512 像素空间经 VAE 压缩后,在潜空间仅 64×64          │
│  随机种子固定 → 噪声固定 → 生成结果可精确复现              │
├─────────────────────────────────────────────────────────┤
│ 步骤③:Scheduler 初始化                                  │
│                                                         │
│  设定去噪总步数,建立从纯噪声到清晰图像的"调度计划"         │
│  FLUX-schnell(蒸馏版):仅需 1-4 步                      │
│  SD 3.5(标准版):需要 20-50 步                          │
├─────────────────────────────────────────────────────────┤
│ 步骤④:去噪循环(推理核心)------重复 N 次                    │
│                                                         │
│  循环每一步:当前噪声图 + 文本条件向量 + 当前步数编号        │
│  → UNet/DiT 预测"哪些像素更可能是噪声"                    │
│  → Scheduler 按预定公式减去预测的噪声分量                  │
│  → 噪声略微减少,图像略微清晰,进入下一步                  │
│                                                         │
│  第 1 步:完全随机噪点,无任何可辨识内容                    │
│  第 5 步:隐约出现色块轮廓(沙滩、天空区域)                │
│  第 10 步:可辨识出猫的色块与墨镜的大致形状                │
│  第 20 步:细节全部完成------毛发纹理、镜片反光、日落光感      │
├─────────────────────────────────────────────────────────┤
│ 步骤⑤:VAE Decoder(潜空间 → 像素空间)                   │
│                                                         │
│  潜空间中 64×64×16 的张量 → VAE 解码 → 512×512×3 像素图  │
│  类比:解压压缩文件------潜空间是压缩态,像素空间是展开态        │
├─────────────────────────────────────────────────────────┤
│ 步骤⑥:后处理                                           │
│                                                         │
│  值域裁剪([-1,1] → [0,255])→ 转换为 PIL Image 对象     │
│  → 返回给调用方                                         │
└─────────────────────────────────────────────────────────┘

3.3 四个核心组件的职责

组件 在管线中的职责 类比
Text Encoder 将 Prompt 自然语言编码为语义条件向量------告知模型"用户期望的内容" 需求翻译
UNet / DiT 去噪循环的核心计算模块------从含噪图像中预测噪声分量 雕刻:每次削去多余的石料
Scheduler 控制去噪的节奏------每一步移除多少噪声、采用何种算法策略 节拍器:控制每次下刀的深度与频率
VAE 像素空间与潜空间的双向转换------压缩与还原 打包与拆包:运输时压缩,使用前恢复

3.3.1 UNet 与 DiT:两代去噪架构

§3.3 的组件表中将去噪网络写为"UNet / DiT",两者是代际关系------当前旗舰模型(FLUX、SD 3.5)已全面转向 DiT。

UNet(2015-2023,以 Stable Diffusion 1.x/2.x/XL 为代表)

复制代码
UNet 结构(概念示意):

  输入(含噪潜空间 64×64×4)
      ↓
  ┌──────────────────────┐
  │  卷积下采样(Encoder) │  ← 逐步压缩空间分辨率,提取特征
  │  64→32→16→8          │    基于 CNN 卷积层
  │      ↓ 跳跃连接       │    跳跃连接 = 将 Encoder 的中间结果
  │  8→16→32→64          │    直接传给 Decoder 同分辨率层
  │  卷积上采样(Decoder) │  ← 逐步恢复空间分辨率
  └──────────────────────┘
      ↓
  输出(噪声预测 64×64×4)

  文本条件注入方式:Cross-Attention(在特定层将文本向量与图像特征做交叉注意力)

DiT(Diffusion Transformer,2024-至今,以 FLUX/SD 3.5/SORA 为代表)

复制代码
DiT 结构(概念示意):

  输入(含噪潜空间 latent)
      ↓
  ┌──────────────────────────────┐
  │  Patch Embedding             │  ← 将图像切成小块(类似 ViT),每块映射为 token
  │  (例如 2×2 像素 → 1 个 token)│
  ├──────────────────────────────┤
  │  Transformer Block × N 层    │  ← 无需卷积,纯 Transformer
  │  ┌────────────────────────┐  │
  │  │ Adaptive Layer Norm     │  │  ← 时间步条件注入:每个去噪步的"进度条"信号
  │  │   ↓                    │  │
  │  │ Multi-Head Self-Attention│ │  ← 图像各 patch 之间互相注意
  │  │   ↓                    │  │
  │  │ MLP(Feed-Forward)     │  │
  │  └────────────────────────┘  │
  │  文本条件注入方式:             │
  │    AdaLN(自适应归一化)或      │  ← 文本向量直接调制 Transformer 的归一化参数
  │    Joint Attention(联合注意力)│  ← 文本 token 和图像 token 一起做注意力
  └──────────────────────────────┘
      ↓
  输出(噪声预测)

为什么 DiT 取代了 UNet

维度 UNet(CNN 卷积) DiT(Transformer)
扩展性 加深加宽收益递减 随参数量增大持续提升(Scaling Law)
高分辨率 卷积感受野有限,需多层下采样 Self-Attention 天然全局视野
文本对齐 Cross-Attention 仅作用于特定层 AdaLN 逐层注入,条件信号贯穿始终
训练效率 CNN 在小规模上收敛快 Transformer 在大规模数据上收敛更好
代表模型 SD 1.5 / SDXL FLUX.1 / SD 3.5 / SORA / Wan 2.7

与文本 LLM 的殊途同归:DiT 的思路是将图片生成问题重新表述为"序列到序列"的 Transformer 任务------图像被切分成 token 序列,去噪过程就是对 token 序列的逐步变换。这与文本 LLM 的"Token → Token 自回归"在数学形式上趋于统一。理解这一点后,你会发现图片模型和文本 LLM 的差异在缩小------它们共享同一个架构范式(Transformer),区别在于输入输出的模态和生成策略(逐步去噪 vs 自回归)。

3.4 参数含义与调节方向

python 复制代码
image = pipe(
    prompt="...",                                      # 正向提示词:描述期望内容
    negative_prompt="blurry, low quality",             # 负向提示词:描述不希望出现的内容
    num_inference_steps=4,                             # 去噪步数:schnell 版用 1-4,标准版用 20-50
    guidance_scale=3.5,                                # 引导强度:越高越贴合 Prompt,但可能过饱和
    height=1024, width=1024,                           # 输出尺寸(必须是 64 的整数倍)
    generator=torch.Generator("cuda").manual_seed(42), # 固定随机种子以复现结果
).images[0]
参数 增大 减小 推荐值
num_inference_steps 质量↑、速度↓ 速度↑、质量↓ schnell: 4 / 标准: 20-30
guidance_scale 更紧密贴合 Prompt 给模型更大自由度 FLUX: 3.5 / SD: 7.5
height × width 细节丰富度提升 推理速度加快 调试: 512² / 成品: 1024²

关于 guidance_scale 的机制 :该参数背后是 Classifier-Free Guidance(CFG,无分类器引导) 算法。每一步去噪时,模型实际上执行两次预测------一次带上 Prompt 条件("一只猫"),一次不带条件(空文本),然后按公式合成最终预测:

复制代码
最终噪声预测 = 无条件预测 + guidance_scale × (有条件预测 − 无条件预测)

直观理解:有条件预测 − 无条件预测 是"Prompt 给模型额外注入了多少信息"。guidance_scale 控制这个额外信息的放大倍数------越大越贴合 Prompt,但也可能放大伪影和过饱和。FLUX 推荐 3.5、SD 推荐 7.5 是经验值,与各自的训练策略和 Text Encoder 强度有关。

3.5 远程调用:三家国内服务商

除本地部署外,文生图同样可以通过远程 API 调用实现,调用方式与文本 LLM 的 API 一致,仅端点和模型名不同:

python 复制代码
# SiliconFlow(OpenAI 兼容接口,可用模型种类最多)
from openai import OpenAI
client = OpenAI(base_url="https://api.siliconflow.cn/v1", api_key="sk-xxx")
resp = client.images.generate(model="black-forest-labs/FLUX.1-dev",
                               prompt="一只猫", size="1024x1024")

# 智谱(CogView-4,支持对话式迭代编辑)
from zhipuai import ZhipuAI
client = ZhipuAI(api_key="xxx")
resp = client.images.generations(model="cogview-4", prompt="一只猫")

# 阿里百炼(Qwen-Image,中文字符渲染能力领先,同时提供编辑 API)
import dashscope
from dashscope import ImageSynthesis
resp = ImageSynthesis.call(api_key="sk-xxx", model="qwen-image-max",
                            prompt="一只猫", n=1, size="1024*1024")
SiliconFlow 智谱 阿里百炼
主要模型 FLUX.1, SD 3.5, SANA CogView-4 Qwen-Image 2.0, 通义万相
接口风格 OpenAI 兼容 自有 SDK + OpenAI 兼容 自有 SDK + OpenAI 兼容
差异化优势 可用模型种类最多 对话式迭代编辑 + 成本最低 中文文字渲染 + 图片编辑 API

四、噪声与遮罩:扩散模型的两个基础概念

在进入图生图、Inpainting 等具体操作之前,需要先理解两个贯穿全部图片编辑任务的基础概念------噪声和遮罩。它们是扩散模型实现"可控生成"的核心机制。

4.1 噪声的本质

噪声是一张与目标图片尺寸相同的纯随机像素矩阵,其中每个像素的值独立随机生成,不携带任何有意义的信息。

复制代码
真实图片(256×256)                    纯噪声(256×256)
┌────────────────────┐                 ┌────────────────────┐
│  🐱 清晰可见的猫     │                 │  ░▒▓█▒░▓▒▓█░▓▒▓█  │
│  具有毛发、眼睛、轮廓 │                 │  ▓▒░▓█▓▒░▓█▒░▓█░  │
│  这是"信号"(有意义) │                 │  这是"噪声"(无意义)│
└────────────────────┘                 └────────────────────┘

扩散模型采用噪声作为起点的原因:噪声不包含任何预设信息,因此可以向任意方向演化。从同一份随机噪声出发,配合不同的 Prompt 条件,可以生成内容完全不同的图片------噪声是最公平的初始状态。

4.2 噪声对图片的影响

扩散模型的训练过程即为学习在不同噪声强度下如何恢复原始信号。噪声比例直接决定了图像的可见程度:

复制代码
原图                    加 25% 噪声            加 50% 噪声            加 100% 噪声
┌────────────┐          ┌────────────┐          ┌────────────┐          ┌────────────┐
│ 🐱 清晰     │   →      │ 🐱 轻微模糊  │   →      │ 🐱 严重模糊  │   →      │ ░▒▓ 纯噪声  │
│ 细节完整    │          │ 细节开始丢失 │          │ 仅剩轮廓    │          │ 完全不可辨认 │
└────────────┘          └────────────┘          └────────────┘          └────────────┘

噪声 0%  --- 原图,全部细节完好
噪声 30% --- 轮廓与颜色仍可辨识,细节已丢失
噪声 50% --- 仅能分辨大致的形状与色彩分布
噪声 100% --- 完全随机的像素,不含任何原始图像信息

图生图中的 strength 参数即对应"加噪比例":strength=0 不加噪声,图片不变;strength=1 加 100% 噪声,等价于文生图。

4.3 遮罩的本质

遮罩是一张与原图尺寸相同的黑白二值图像,其每个像素的值仅表达一个含义:该位置是否允许模型修改。

复制代码
原图                                遮罩
┌──────────────────────┐          ┌──────────────────────┐
│                      │          │████████    ████████   │
│  👤围观  🧑主角  👤围观│          │████████    ████████   │
│                      │   →      │████████    ████████   │
│  👤围观  👧主角  👤围观│          │████████    ████████   │
│                      │          │████████    ████████   │
└──────────────────────┘          └──────────────────────┘
                                   白色 = 允许模型自由修改
                                   黑色 = 保持原始像素不变

4.4 遮罩与噪声在 Inpainting 中的协作机制

Inpainting 的每一步去噪过程,都是遮罩引导下的"局部生成 + 全局锁定"操作:

复制代码
去噪步骤 i(总步数 20,当前为第 5 步):

1. UNet 对整张图执行去噪预测(遮罩内外区域均参与计算)
2. 将遮罩外部区域强制覆盖为原图像素------"锁定不变区域"
3. 遮罩内部保留去噪结果------"AI 在此区域内自由生成"
4. 进入下一步迭代

每一步均需执行覆盖操作的原因:
→ UNet 的卷积运算会导致遮罩内外区域的信息相互渗透
→ 必须在每一步去噪后将遮罩外部重置为原图,确保只有遮罩内部发生修改

类比:装修施工中的成品保护
  整张图 = 整个房间,遮罩内部 = 施工区域
  遮罩 = 覆盖在不动区域上的保护层
  每一步施工结束后检查保护层是否完整,确保无污损扩散至非施工区域

噪声决定"修改的程度",遮罩决定"修改的位置"。 两者的组合构成了所有图片编辑任务的参数空间。


五、图片编辑的四种模式:同一管线,不同参数组合

核心认知:图生图、Inpainting、超分、Outpainting 并非四种独立技术------它们是同一套扩散管线,仅通过改变"起点噪声比例"和"遮罩范围"切换为不同模式。

5.1 四种模式的本质差异

复制代码
                起点噪声比例    遮罩约束              本质操作
                ───────────    ────────              ────────
文生图          100%           无(整图参与生成)     从零创造
图生图          30%~80%        无(整图参与生成)     基于原图重新演绎
Inpainting      遮罩内 100%    遮罩外锁定为原图       局部重新生成
                遮罩外 0%
超分            10%~20%        无(整图微调)         细节增强

5.2 图生图 --- 以 strength 控制修改幅度

python 复制代码
from diffusers import AutoPipelineForImage2Image
import torch
from PIL import Image

pipe = AutoPipelineForImage2Image.from_pretrained(
    "black-forest-labs/FLUX.1-schnell",
    torch_dtype=torch.bfloat16
).to("cuda")

original = Image.open("my_photo.jpg")

result = pipe(
    prompt="水彩画风格,柔和的色彩",
    image=original,
    strength=0.5,         # 核心参数:0=保持原图不变,1=完全重新生成
    num_inference_steps=4,
).images[0]

strength 参数效果对照

复制代码
strength = 0.1   几乎无可见变化,仅轻微调整色调与纹理
strength = 0.3   保留原图构图与结构,风格开始转变
strength = 0.5   可辨认原图内容,但风格发生显著变化(如照片 → 水彩画)
strength = 0.8   仅保留大致空间布局,内容变化幅度大
strength = 1.0   等价于文生图,与原始图像再无关联

5.3 Inpainting --- 以遮罩控制修改位置

python 复制代码
from diffusers import AutoPipelineForInpainting

pipe = AutoPipelineForInpainting.from_pretrained(
    "black-forest-labs/FLUX.1-schnell",
    torch_dtype=torch.bfloat16
).to("cuda")

original = Image.open("my_photo.jpg")
mask = Image.open("mask.png")       # 白色=允许修改,黑色=保持原样

result = pipe(
    prompt="干净的街道背景,自然的建筑外墙",
    image=original,
    mask_image=mask,
    num_inference_steps=4,
).images[0]

遮罩占比与成功率的关系

复制代码
遮罩占比    <10%              10~30%               >30%
成功率     高                 中等                 低
原因分析   模型有充足的周边    模型勉强可推断       模型"虚构"的概率显著上升
           上下文作为参考      周边上下文           (实际使用中已验证的局限)

两种技术路线的适用场景

  • 移除路人、保持原始场景真实感 → 内容感知填充(Photoshop / OpenCV inpaint),利用原图纹理
  • 将门改为窗、需要创造全新内容 → 扩散模型 Inpainting,由模型生成新内容

5.4 超分辨率 --- CNN 方法与扩散方法的对比

方案 A:CNN 超分(不编造内容,推荐用于保真场景)

python 复制代码
import cv2
from PIL import Image
import numpy as np

sr = cv2.dnn_superres.DnnSuperResImpl_create()
sr.readModel("LapSRN_x4.pb")
sr.setModel("lapsrn", 4)

pil_img = Image.open("small.jpg")
cv_img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
result = sr.upsample(cv_img)
模型 放大倍数 文件大小 速度 质量 适用场景
LapSRN ×2,×4,×8 1.3MB 良好 通用推荐
EDSR ×2,×3,×4 37MB 最优 追求极致质量
ESPCN ×2,×3,×4 100KB 最快 中等 实时应用
FSRCNN ×2,×3,×4 40KB 中等 移动端部署

方案 B:扩散超分(视觉效果更好,但可能引入虚构细节)

python 复制代码
result = pipe_img2img(
    prompt="high resolution, sharp details, 4K quality",
    image=original,
    strength=0.15,        # 极低值,仅在纹理层面增强,不改变内容
).images[0]

选择依据:要求"严格保真"(证件照、文档扫描件)→ CNN 超分;追求"视觉观感"(风景照、艺术作品)→ 扩散超分。

5.5 Outpainting --- 扩展画面边界

Outpainting 的核心逻辑是 Inpainting 的变体:将原图放置于更大画布的中央,四周空白区域作为遮罩,由模型在遮罩区域生成与原图风格一致的延续内容。

python 复制代码
canvas = Image.new("RGB", (w * 2, h))              # 创建扩展画布(宽度加倍)
canvas.paste(original, (w // 2, 0))                # 原图居中放置

mask = Image.new("L", canvas.size, 255)             # 初始化为全白(全部允许生成)
mask.paste(Image.new("L", original.size, 0), (w // 2, 0))  # 原图位置锁定

result = pipe_inpaint(prompt="继续延伸该场景,保持一致的风格与光照",
                       image=canvas, mask_image=mask).images[0]

六、精确控制:LoRA、ControlNet 与 IP-Adapter

三者的定位:Prompt 是"建议"(语义层面),LoRA 是"训练"(身份/风格层面),ControlNet 是"命令"(空间/结构层面),IP-Adapter 是"参考"(图像风格层面)。

6.1 纯 Prompt 控制的局限性

使用 Prompt"一只猫在沙发上"时,模型在每次推理中可能生成不同的猫的品种、观察角度、动作姿态、沙发款式和光线条件------每次结果均不相同。Prompt 本质上是"语义意图",而非精确的空间或身份指令。

三种控制技术在各自维度上解决了这一问题:

技术 控制维度 功能类比 文件大小
LoRA 内容 / 角色 / 风格 "教会模型识别特定人物" 10-200MB
ControlNet 空间结构 / 构图 "向模型提供构图骨架" ~1.4GB
IP-Adapter 图像风格 / 外观参考 "以参考图的风格进行创作" ~300MB

6.2 LoRA --- 控制"外观特征"

LoRA 是一种轻量级权重补丁,使基础模型获得其原本不具备的特定概念------特定角色、特定面部特征或特定艺术风格。

复制代码
无 LoRA:Prompt "一个女孩,动漫风格" → 每次生成的面部特征均不同
加载 LoRA:相同 Prompt + "角色A.safetensors" → 每次生成均保持角色一致

工作原理

复制代码
基础 FLUX 模型(约 12GB)              LoRA 文件(约 20MB)
┌──────────────────────┐              ┌──────────────────────┐
│ 理解通用视觉概念:     │      +       │ 仅存储学习到的"偏差": │
│ "猫""狗""沙发""日落"   │              │ "该角色的眼型参数应   │
│ 无法辨识你的特定角色   │              │  向此方向偏移"       │
└──────────────────────┘              └──────────────────────┘
              ↘                          ↙
              推理时融合计算 → 基础模型通用能力 + LoRA 特化知识
python 复制代码
pipe.load_lora_weights("character_lora.safetensors")
pipe.fuse_lora()  # 将 LoRA 权重融入基础模型,加速后续推理

image = pipe("my_character in a garden, cinematic lighting").images[0]

LoRA 权重的获取途径

  • civitai.comhuggingface.co 下载社区训练的 LoRA(.safetensors 格式,10-200MB)
  • 自行训练:准备 10-30 张同一角色或风格的图片,在 8GB VRAM 的消费级显卡上训练 30 分钟至数小时

适用 :固定角色外貌、特定艺术风格、特定物体外观。不适用:精确控制构图中的空间位置。

6.3 ControlNet --- 控制"空间位置与姿态"

ControlNet 在标准扩散模型上附加一个可训练的控制分支,接收额外的条件输入(边缘检测图、深度图、骨骼姿态图等),使生成结果精确遵循指定的空间结构。

控制信号类型

控制信号 输入格式 约束内容 典型应用
Canny 边缘 线稿轮廓图 物体的边界与轮廓 将设计草图转换为照片级渲染
Depth 深度 灰度深度图 物体的前后关系与体积感 保持场景的空间层次
OpenPose 姿态 骨骼关节点图 人物的动作与姿势 指定人物的精确姿态
Scribble 涂鸦 手绘色块 构图的色彩分区 快速原型构图
Segmentation 语义分割色块 各类物体的空间分布 精确控制场景布局
python 复制代码
# 以 Canny 边缘检测为例
from diffusers import StableDiffusion3ControlNetPipeline, ControlNetModel
import cv2, numpy as np

controlnet = ControlNetModel.from_pretrained(
    "InstantX/SD3-Controlnet-Canny", torch_dtype=torch.float16
)
pipe = StableDiffusion3ControlNetPipeline.from_pretrained(
    "stabilityai/stable-diffusion-3.5-medium",
    controlnet=controlnet, torch_dtype=torch.float16
).to("cuda")

# 从参考图提取边缘作为控制图
edges = cv2.Canny(cv2.cvtColor(np.array(original), cv2.COLOR_RGB2BGR), 100, 200)
control_image = Image.fromarray(edges)

result = pipe(
    prompt="a cat sitting on the sofa, photorealistic",
    control_image=control_image,
    controlnet_conditioning_scale=0.8,  # 控制强度:0=不约束,1=严格遵循
).images[0]

6.4 IP-Adapter --- 以图像替代文字 Prompt

IP-Adapter(Image Prompt Adapter)通过将参考图像的 CLIP 视觉特征注入去噪过程,实现"以图控图"------用图片描述期望的风格与外观,而非仅依赖文字 Prompt。

复制代码
ControlNet 约束的是"结构"(线条走向、深度层次、关节位置)
IP-Adapter 约束的是"风格与质感"(色调氛围、纹理特征、物体类别)

输入水墨画参考图 → 生成结果的色彩与笔触呈现水墨质感
输入人物照片     → 生成结果具有该人物的面部特征
python 复制代码
pipe.load_ip_adapter("h94/IP-Adapter", subfolder="sd3",
                      weight_name="ip-adapter_sd3.safetensors")

result = pipe(
    prompt="a cat sitting on a windowsill",
    ip_adapter_image=reference,     # 参考图像
    ip_adapter_scale=0.6,           # 影响力:0=不使用参考图,1=完全遵循
).images[0]

6.5 LoRA 与 ControlNet 的边界辨析

这是最容易混淆的一对概念,区别在于约束的维度不同:

复制代码
LoRA 回答的问题:         "该物体长什么样?"(身份标识 / 外观特征)
ControlNet 回答的问题:    "该物体在画面中的哪里、呈现何种姿态?"(空间坐标 / 几何结构)

以角色生成为例:
LoRA → 眼睛为杏仁形,虹膜深褐色,睫毛具有特定卷曲形态("外观配方")
ControlNet → 眼部中心位于像素 (256,180),左右眼间距 64px("空间坐标")

同一角色在不同角度下:
  正面 / 侧面 / 俯视 → LoRA 保证五官的形态特征一致
                     → ControlNet 指定头部朝向与画面位置

决策标准

问题一:"关注的核心是该物体的外观特征吗?" → 是 → LoRA

问题二:"关注的核心是该物体的空间位置与姿态吗?" → 是 → ControlNet

两者均关注 → 联合使用。

6.6 三者的协同使用

复制代码
任务:生成特定角色,在樱花树下,以指定姿势站立,并参考某张图片的色调氛围

Prompt:     "樱花树下,花瓣飘落"          ← 语义场景描述
LoRA:       角色A.safetensors            ← 固定角色外貌特征
ControlNet: OpenPose 骨骼关键点图         ← 指定身体姿态
IP-Adapter: 色调参考图                   ← 引导色彩与氛围

→ 模型同时接收四种条件信号,综合生成最终图像

七、视频处理与工程落地

7.1 视频生成的本质:在图片扩散模型上增加时间维度

复制代码
图片生成:噪声 → 去噪循环 × N → 一张静态图像

视频生成:噪声 → 去噪循环 × N → 帧₁
                → 去噪循环 × N → 帧₂(须与帧₁ 保持物体位置与外观一致)
                → 去噪循环 × N → 帧₃(须与帧₂ 保持光影与背景连贯)
                ...
                → 去噪循环 × N → 帧₁₂₀(10 秒 × 24fps)

核心机制:每一帧的去噪过程均能访问相邻帧的信息------"时序注意力机制"

为实现上述机制,视频模型在图片模型架构的基础上加入了时间维度的建模:

  • 3D VAE:将图片 VAE 的 2D 卷积核(空间 H×W)升级为 3D 卷积核(空间 H×W + 时间 T),同时对多帧执行压缩和重建,保证帧间视觉一致性
  • 时空注意力(Spatio-Temporal Attention):在标准 Self-Attention(空间维度上各 patch 相互注意)之后增加一层 Temporal Attention(时间维度上同一空间位置的 patch 跨帧相互注意),使每一帧在去噪时能看到相邻帧的状态
  • RoPE 三维位置编码:将文本 LLM 中使用的旋转位置编码(RoPE)扩展到三维(空间 X/Y + 时间 T),帮助模型区分"同一帧内的相邻像素"和"相邻帧的同一位置"

Wan 2.7、CogVideoX 等主流视频模型均采用上述机制,而非简单地将 2D 卷积替换为 3D 卷积。

7.2 主流视频生成模型

远程 API(推荐入门) 本地部署(高显存需求)
顶级质量 Runway Gen-4.5, Veo 3.1 Wan 2.7(27B, Apache 2.0)
中文生态 Kling 3.0(最长 2 分钟), Jimeng Wan 2.7, CogVideoX
性价比 Kling 免费额度, Pika 2.5 SANA-1.5 视频版(8GB VRAM 可运行)
入门门槛 无硬件要求 8GB(SANA)→ 24GB+(Wan)

视频本地部署的硬件门槛远高于图片任务。入门阶段建议先通过远程 API 了解各类模型的效果与能力边界,再决定是否投入高显存硬件。

7.3 视频编辑的工程方法:逐帧处理

对于不具备专用视频编辑模型的场景,可将视频拆分为帧序列,逐帧应用图片处理管线,再合成为视频:

python 复制代码
import cv2
from PIL import Image
import numpy as np

# 1. 拆帧
cap = cv2.VideoCapture("input.mp4")
frames = []
while True:
    ret, frame = cap.read()
    if not ret: break
    frames.append(frame)

# 2. 逐帧应用图片处理管线(以风格迁移为例)
processed = []
for frame in frames:
    pil_frame = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
    result = pipe_img2img(prompt="油画风格", image=pil_frame, strength=0.4).images[0]
    processed.append(cv2.cvtColor(np.array(result), cv2.COLOR_RGB2BGR))

# 3. 合成视频并合并原始音频
# ffmpeg -i output.mp4 -i input.mp4 -c:v copy -c:a aac -map 0:v:0 -map 1:a:0 final.mp4

7.4 FastAPI 封装:将图片处理能力服务化

将前述各章的能力封装为 HTTP API,使任意客户端均可通过网络请求调用:

python 复制代码
from fastapi import FastAPI, UploadFile, File, Form
from fastapi.responses import Response
from diffusers import AutoPipelineForText2Image
from PIL import Image
import io, torch

app = FastAPI()

# 服务启动时一次性加载模型,常驻显存
@app.on_event("startup")
async def load_models():
    global pipe
    pipe = AutoPipelineForText2Image.from_pretrained(
        "black-forest-labs/FLUX.1-schnell",
        torch_dtype=torch.bfloat16
    ).to("cuda")

@app.post("/generate")
async def generate(prompt: str = Form(...)):
    image = pipe(prompt=prompt).images[0]
    buf = io.BytesIO()
    image.save(buf, format="JPEG", quality=95)
    return Response(content=buf.getvalue(), media_type="image/jpeg")

# 启动:uvicorn image_service:app --port 8000
# 调用:curl -X POST http://localhost:8000/generate -F "prompt=一只猫" -o cat.jpg

服务化前后的对比:

  • 每次编写独立脚本 → 统一 HTTP 接口调用
  • 模型重复加载(每次 5-30 秒冷启动) → 模型常驻显存,请求即时响应
  • 仅限本地使用 → 局域网内任意设备均可调用

7.5 全文回顾

复制代码
第一章:能力全景   --- AI 在图片与视频领域的边界、五层生态结构、远程与本地两种模式
第二章:环境地基   --- 自底向上逐层解析,每层的功能定位与安装验证
第三章:第一张图片 --- 扩散模型推理全流程的六步骤拆解与四个核心组件
第四章:噪声与遮罩 --- 两个贯穿全部图片编辑任务的基础概念
第五章:四种模式   --- 同一管线、不同参数组合(图生图/Inpainting/超分/Outpainting)
第六章:精确控制   --- LoRA(外观)+ ControlNet(空间)+ IP-Adapter(风格)
第七章:视频与落地 --- 视频 = 图片 × 时间维度 + FastAPI 服务化封装

配套阅读:《AI图片视频处理-工具使用手册.md》------各知识点的可执行代码、命令速查、实践经验记录与常见问题解决方案。

相关推荐
每日综合1 小时前
焊牢工业“关节”:灵科超声波凭“中国精度”成为全球品牌
人工智能
hhb_6181 小时前
云原生AI工作流分布式调度实战
人工智能·云原生
大鹏的NLP博客1 小时前
深度学习模型 ONNX 与 RKNN 数值一致性校验通用技术报告
人工智能·深度学习
雪隐2 小时前
用Flutter做背单词APP-04一个人,2周,从零撸出一个背单词App
前端·人工智能·后端
apihz2 小时前
全球域名 WHOIS 信息实时查询免费 API 接口教程,支持1000+后缀
android·网络·网络协议·tcp/ip·apache·域名·whois
Ivanqhz2 小时前
DRN(深度强化学习推荐网络)
人工智能·线性代数·机器学习·矩阵·dnn
xd1855785552 小时前
梦境解析师-基于鸿蒙的梦境心理分析应用开发实践
人工智能·华为·harmonyos·鸿蒙
147API2 小时前
ChatGPT Skills开放后,开发团队先补权限和上传检查
人工智能·chatgpt
ltqvibe2 小时前
怎么让本体语义变成可执行的智能体
java·人工智能·本体语义