我最早以为,文本引导的图像编辑就是把原图和提示词一起扔给扩散模型,让它重新生成一次。结果第一次尝试就翻车了——我用 Stable Diffusion 给一张照片加「make the sky sunset」,模型确实画出了日落,但同时把整张图都染成了橙色,连我朋友的白衬衫都变成了晚霞。后来我才意识到,那根本不是编辑,那是重新画了一张。真正的图像编辑,难点不在「画」,而在「怎么知道你想画哪里,以及哪里不能动」。

这也是整个技术路线演变的中心问题:模型如何理解文本指令,如何定位目标区域,如何在不破坏无关内容的前提下执行修改。这篇文章沿着这个问题讲清楚背后的机制。我会从扩散模型聊起,走到 CLIP、InstructPix2Pix、Prompt-to-Prompt,最后告诉你这些方法在真实场景下会在什么地方失效。
编辑不是重画:一个被忽略的初始设定
文本到图像生成,模型只需要根据描述「从无到有」地画。但编辑是「从有到某」的局部修改。你要求「把墙刷成蓝色」,模型必须知道墙在哪里、保留其他所有东西。生成模型的输出依赖随机采样,对同一个输入可以画出完全不同的图——这在编辑里是致命的。编辑需要的是「确定性」:原图是条件,指令是另一个条件,输出只能修改指定属性,其他地方都要保持原样。这就对模型提出了一类完全不同的要求:它得同时具备「理解原图结构」和「理解指令语义」的能力。
先破坏,再重建:SDEdit 的思路
SDEdit(Stochastic Differential Editing)是 2021 年提出的(论文原文),它的思路非常工程化:编辑图像就像在一块已经被画过的画布上修改,那不如先把它擦花,再根据提示重新画。具体过程是这样的:
- 对原图加一定强度的噪声,让画面变得模糊。噪声强度决定了「擦花」的程度——加得少,只能做微调;加得多,模型就「忘记」了细节,可以大幅改动。
- 用扩散模型根据你的文本提示,从噪声图像开始去噪。每一步去噪都参考当前的噪声图像,同时受到文本引导。
- 得到最终输出——一张与原图构图接近,但内容被修改的新图。
这个方法的聪明之处在于利用了扩散模型的生成特性。扩散模型天生擅长从噪声恢复图像,训练时就是学习把纯噪声一步步还原成清晰图像。SDEdit把原图当作去噪的起点,而不是从随机噪声开始,等于给了模型一个「原作参考」。去噪时模型会尽量保持原图的结构,同时接受文本提示的引导,修改与提示相关的部分。
但 SDEdit 有一个明显局限:它不知道「墙」在哪里。它只是全局地去噪,所以当你想改局部时,其他区域也会被波及。你可能只想改背景,但整个画面质感、色调、甚至物体的形状都可能走样。不过这个方法仍是理解后来大部分编辑模型的基础。
CLIP 让模型「听懂」描述,但听不到「位置」
要让模型根据文本修改图像,第一步得让图像和文本在同一个向量空间里可比。CLIP(OpenAI, 2021,论文)就是干这个的。它把「猫」这个词和成千上万张猫的图像映射到同一个向量空间,训练目标是让配对的图像-文本距离近,不配对的远。
于是研究者立刻想到了用 CLIP 来驱动编辑:计算编辑后的图像与目标文本在 CLIP 空间里的相似度,把相似度作为损失函数,反向传播去微调生成模型。这个方向叫 DiffusionCLIP(论文地址)。它确实能让模型输出「更接近」文本描述的图像,但有个致命问题:CLIP 的损失是全局的,它不知道「猫」对应图像中的哪几个像素。你改刘海,它可能把整张脸都动了;你改背景,它可能把前景也一起染了。
换句话说,CLIP 给了模型「听懂话」的能力,却没有给它「找到位置」的能力。只靠语义相似度做编辑,就像让一个只看过全局的人去改局部,他确实知道目标长什么样,但不知道目标在画面里的哪一块。要精确定位,还需要别的机制。
InstructPix2Pix:用 GPT 造数据训练一个「编辑专用模型」
2023 年初,加州大学伯克利分校的研究者放出了 InstructPix2Pix(论文)。他们做了一件看起来有点「暴力」的事情:与其想办法在生成时控制原图,不如直接训练一个专门做指令编辑的模型。但训练数据哪来?他们用 GPT-3 根据网页上的图片描述生成「修改指令」,再让 Stable Diffusion 执行这些指令生成编辑后的图片,这样自动造出了几十万条(指令,原图,目标图)三元组,然后在这批数据上训练条件扩散模型。
这个模型的输入有两个:原图经过一个图像编码器,文本指令经过文本编码器,两者在 UNet 中被合并成条件,输出直接是编辑后的图像。推理时只需一次前向传播,不需要像 DiffusionCLIP 那样对每张图做几百步优化,所以速度快得多,也实用得多。
InstructPix2Pix 确实能完成很多任务,比如把白天变夜晚、把狗变成猫、让人戴上墨镜。它的局限性也来自它的训练数据:由于合成数据的多样性有限,模型在「开箱」情况下的泛化能力不足。如果指令比较罕见(比如「让画面产生 1980 年代的灰色颗粒感」),或者原图的风格很特殊,模型就可能表现得让你摸不着头脑。
交叉注意力:模型内部画好了一张「地图」
到这里,你可能已经意识到:编辑的核心挑战是「定位」。SDEdit 没有定位,CLIP 也没有定位。那有没有办法让模型显式地告诉我们「这个区域对应哪个词」?有,答案藏在扩散模型的交叉注意力层里。
在扩散模型的每个去噪步骤中,图像特征与文本中每个词都会计算一个注意力权重。这个词对应的区域,注意力权重就高。举例来说,当模型生成 「a dog sitting on the beach」 时,词「dog」的注意力会集中在图像中狗的形状区域,「beach」则集中在背景区域。换句话说,模型在生成过程中不知不觉地画出了一张「词-区域」对应关系的地图。
Prompt-to-Prompt(论文)就是利用这个特点做编辑的。它的操作很优雅:当你需要把提示词中的「dog」换成「cat」时,不需要重新生成整个图像,只需要在去噪过程中,让新提示词「cat」的注意力图与原来「dog」的注意力图保持一致,其他词的注意力图也复用原图生成时的值。这样就能保证模型只在「狗所在的区域」进行修改,而其他区域(如海滩、光线)完全不变。
这个方法的直观意义是:只要你能控制注意力图,就能控制编辑的位置和程度。它改变了人们对扩散模型的理解——生成过程不是黑箱,它的内部状态包含了可解释的空间语义。但 Prompt-to-Prompt 有个前提:你要编辑的图必须本身就是由扩散模型生成的,而且你得保存生成时的注意力图。对真实照片,你无法直接获得这个「生成轨迹」。后来有工作(比如 DDIM Inversion、Null-text Inversion)尝试把照片反演成噪声轨迹,再把 Prompt-to-Prompt 用上去,但反演过程本身有信息损失,而且计算成本昂贵。
一张表看清五种编辑路线的权衡
| 方法 | 核心机制 | 优势 | 局限 |
|---|---|---|---|
| SDEdit | 对原图加噪,再用文本引导去噪 | 简单、无需训练,即可编辑任意扩散模型 | 全局改动,容易破坏无关区域 |
| DiffusionCLIP | 用 CLIP 相似度作为损失,反向微调生成模型 | 可以处理任意抽象描述 | 速度慢,全局性修改 |
| InstructPix2Pix | 用指令-图像对训练条件扩散模型 | 单次前向推理,速度快 | 泛化受训练数据分布限制 |
| Prompt-to-Prompt | 编辑生成时的交叉注意力图 | 无需训练,定位精准,编辑效果自然 | 需要原始生成轨迹,真实照片无法直接使用 |
| ControlNet(区域控制) | 在扩散模型外附加一个边缘/深度/遮罩控制分支 | 可以显式指定编辑区域和几何约束 | 需要额外条件图,并不直接理解文本语义 |
这五条路线代表了当前图像编辑领域的两个方向:要么从语义空间做全局引导(DiffusionCLIP、SDEdit),要么从结构空间做局部控制(Prompt-to-Prompt、ControlNet)。而 InstructPix2Pix 试图把两者都塞进一个端到端模型里,结果就是在两者之间妥协。
我实际测试后,发现了模型的死穴
为了写这篇文章,我特意在开源环境里做了一组小实验。我用了 InstructPix2Pix、SDEdit 和 ControlNet + inpaint 三种方式,输入了几种典型的编辑指令。结果很能说明问题:
- 「把人物的红头发染成金色」:InstructPix2Pix 常常把眉毛、睫毛也一起染色,因为模型没有「头发」和「脸部」的独立概念。
- 「让人物举起右手」:几乎全部失败。模型不懂「举起」的动作约束,生成的手往往悬空、弯曲方向异常,甚至出现六根手指。
- 「把背景中的广告牌移除」:如果不用遮罩明确指定广告牌的位置,模型很难「专门」擦除一个对象,取而代之的是全图重绘,背景细节失真。
你会发现,这些失败的共同点都是「需要精确的空间知识」而非「语义相似性」。模型知道「红头发」的语义,但不知道「红色」仅应作用于头发区域;模型知道「举起手」的语义,但不知道「手」必须连在肩膀上。这些知识的缺失不是简单增加数据量就能弥补的,因为文本本身就不包含像素级的边界信息。
工程上已经变得务实:编辑被拆成流水线
如果你去看当前真正落地的产品(比如 Photoshop 的生成式填充、Stable Diffusion 的 Inpainting 插件),会发现它们都不再只依靠一个文本-图像联合模型,而是把编辑拆成多步流水线:
- 先用目标检测或分割模型(如 SAM)自动识别用户描述的对象,生成遮罩。
- 把遮罩和文本一起送入扩散模型,模型只对遮罩内的区域重新生成。
- 添加后处理步骤,如保持人脸 ID 一致性(用 FaceID 或 LoRA 嵌入)或检查 CLIP 分数。
这种做法的核心是:把「定位」和「生成」分成两个独立环节。定位交给专门的分割模型,生成只负责画。通过这样的组合,目前的系统已经能在很多场景下达到实用水平。
但我认为,它还不是真正的「理解」。模型仍然不知道「第一只猫」和「第二只猫」的概念区别。等到语言模型能直接输出编辑指令对应的遮罩分割,比如「把左边那只猫的眼睛变蓝」时,模型能显式生成左眼区域的遮罩,那才算是真的跨过了语义鸿沟。
它并不知道「哪里」和「多少」
文本引导的图像编辑已经不是一个「能不能做」的问题,而是一个「能做到多精细」的问题。现在的主流方法要么牺牲局部控制来追求语义吻合,要么牺牲语义灵活性来换取局部控制。InstructPix2Pix 是前者的代表,Prompt-to-Prompt 是后者的代表,而它们之间的空间就是当前研究的空白。
对你我这样的使用者来说,理解这些底层机制有一个直接好处:你知道什么时候应该相信 AI 编辑的结果,什么时候应该主动提供遮罩或额外条件。下次你使用「把天空改成日落」时,如果模型把整个画面都调成了暖色,你可以用画笔把天空区域涂出来,问题就解决了——这不是模型笨,而是它确实没有能力知道「天空」的准确边界。你以为它在看图片,实际上它只是在玩一个概率填字游戏。
所以,当有人跟你说「AI 能听懂你的自然语言并编辑图像」时,你可以在心里补充一句:它听懂了大概意思,但它对「哪里」和「多少」几乎没有概念。真正的理解还在路上。
术语表和进阶阅读
- 扩散模型
- 一种生成模型,通过逐步加噪破坏图像,再学习如何从噪声中恢复原图。生成时就是从纯噪声逐步去除噪声,得到图像。
- 交叉注意力
- 在生成每个像素时,根据文本中每个词的语义,动态分配注意力权重。权重越高,该像素越受这个词的影响。
- 反演(Inversion)
- 将一张真实图片映射回扩散模型的噪声轨迹,以便在编辑时复用原图的信息。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/525.html