小yo 博客

Back

《CharaConsist》 论文精读

前置知识与基线

FLUX.1 核心架构

CharaConsist 是首个基于 Text-to-Image DiT模型的免训练一致性生成方法。它主要基于 FLUX.1 展开。

多模态 Transformer 架构

与以往的 UNet 架构(如 SDXL)分别处理自注意力和交叉注意力不同,FLUX.1 采用了一种多模态 Transformer 架构。它将文本 Token 和图像 Token 拼接成一个单一的序列,然后进行全局注意力计算。 在原始的 DiT 中,文本信息(通常是类标签或经过 CLIP 编码的全局文本向量)和时间步信息是通过 adaLN-Zero 注入到模型中的。这种方式本质上是对图像特征进行全局的缩放和平移,文本特征并没有作为独立的 Token 参与到注意力机制的序列计算中。 FLUX.1 采用的是多模态 Transformer 架构。它使用 T5 编码器对文本进行编码,使用 VAE 对图像进行编码。它的核心区别在于序列拼接:FLUX.1 不再使用 adaLN-Zero 来注入文本信息,而是将海量的文本 Token 序列和图像 Token 序列直接首尾拼接,融合成一个超长的单一序列。在后续的自注意力计算中,这个长序列会进行全局的注意力交互。

T5 编码器: T5 是 Google 推出的大型语言模型(LLM),它是纯粹在海量文本数据上训练出来的,专精于自然语言处理。 要理解为什么最新的 DiT 模型(如 FLUX.1、SD3)纷纷转向 T5,我们需要先明白 CLIP 的强项与致命弱点。

  • CLIP的局限性: CLIP 擅长抓取“全局语义”(比如知道图片里有“猫”和“草地”),但它的语法理解能力极差。如果你输入“一个红色的方块在一个蓝色的圆球上面”,CLIP 生成的特征往往会把颜色和物体搞混(生成蓝色的方块和红色的圆球),而且它很难理解复杂的空间关系和超长提示词。
  • T5 的优势: T5 拥有极其强大的语法解析、上下文理解和长文本处理能力。它能精准理解“红色属于方块,蓝色属于圆球”这种属性绑定。 FLUX.1 采用 T5 编码器来处理文本 Token 。不同于 CLIP 试图自己完成图文对齐,FLUX.1 让 T5 专注于提取最深度的纯文本语义,然后将这些 T5 Token 与图像 Token 直接拼接。真正的图文对齐任务被交给了 Multimodal Transformer 自己。模型通过在海量数据上计算这两段序列的自注意力,自己学会了图像像素和文本单词之间的精准映射。

优势: 这种架构允许图像的局部 Patch 直接与文本序列中的特定单词进行细粒度的 Attention 交互(这就是为什么 CharaConsist 能够通过公式提取出精确的“前景/背景 Mask” ),而不仅仅是接受一个全局的文本条件约束。

Double Block vs. Single Block

FLUX.1 包含两种 Transformer 块,这两种 Block 承担着不同阶段的特征处理任务,并且结构上有所区别。 Double Block(双流块):

  • 位置与作用: 位于模型的前期阶段,起到类似编码器的作用,负责对输入的噪声潜变量进行初步编码。
  • 结构特点: 虽然文本和图像 Token 拼接在一起进行了全局注意力计算,但由于文本和图像属于完全不同的模态,初始特征分布差异极大。因此,在 Double Block 中,注意力计算后的文本 Token 和图像 Token 会被分开送入各自独立的 MLP和 LayerNorm 层进行处理。这种“注意力共享,MLP 分离”的设计,有助于模型在对齐模态的同时,保留各自模态的独特特征。 Single Block(单流块):
  • 位置与作用: 位于模型的后期阶段,起到类似解码器的作用,负责将融合后的特征解码为最终输出。
  • 结构特点: 经过前面多层 Double Block 的处理,文本和图像模态已经高度对齐。因此在 Single Block 中,文本和图像 Token 不仅共享注意力机制,还共享同一个 MLP 网络。它们被完全视作同一种东西(统一的特征序列)进行处理。 与 CharaConsist 的联系: 作者发现,只需要对后期的 Single Block进行操作,就能提供足够的一致性,如果强行修改所有 Block,反而会导致图像质量下降或出现重影等伪影。

RoPE 机制

传统正余弦位置编码(绝对位置编码): 像最早的 Transformer 那样,传统的正余弦位置编码是在网络最开始,将位置向量直接相加到 Token 的特征向量上(即 Input=Feature+PositionInput = Feature + Position)。

  • 痛点: 随着网络层数的加深,经过无数次的线性映射和非线性激活,这种相加进去的绝对位置信息会被语义特征“稀释”和破坏。在深层网络中,模型很难再精准感知两个 Token 之间的精确相对距离。 RoPE(旋转位置编码): RoPE 的核心思想是用绝对位置的旋转操作,来隐式地表达相对位置。它不再是加法,而是乘法(旋转矩阵)。在 FLUX.1 中,RoPE 不是只在第一层加一次,而是在每一个注意力层的 Query (Q) 和 Key (K) 上应用。
  • 数学机制: 当给定一个 Token 的绝对位置 mm 时,RoPE 会通过乘以一个由 mm 决定的旋转矩阵,在多维空间中将该 Token 的特征向量“旋转”一个特定的角度。
  • 相对位置: 当计算 Query 和 Key 的注意力得分(即点积 Q⋅KTQ \cdot K^T)时,奇妙的数学特性出现了:两个经过 RoPE 旋转的向量的点积,最终化简后仅依赖于它们相对位置的差值 (m−n)(m - n),而与它们的绝对位置无关。

ConsiStory

在论文中,ConsiStory 经常被拿来作为直接对比的免训练基线方法 。

  • 核心机制: 像 ConsiStory 和 StoryDiffusion 这样的方法,主要是通过在生成一批图像时,将相邻图像的 Key 和 Value 拼接到当前图像的注意力机制中,实现跨图像的信息共享。
  • DIFT 匹配的失效: ConsiStory 为了增强特征,依赖于一种叫做 DIFT 的相似度特征注入技术。DIFT 能够通过比较 UNet 在特定时间步的中间层特征,来找到图像间的语义对应关系。
  • 为什么在 DiT 上行不通? 作者在实验中发现,把这种套路直接搬到 FLUX.1上会失效。FLUX.1 中间 Transformer 块的输出只能匹配到相同空间位置的点(缺乏语义对应),而注意力层的输出波动又极其剧烈,根本无法提供稳定的匹配。这迫使 CharaConsist 必须设计一套全新的跨层平均匹配策略。

DIFT

DIFT(Emergent Correspondence from Image Diffusion)是 2023 年 NeurIPS 的一篇重量级工作 。它在 ConsiStory 等免训练一致性方法中扮演了核心角色 。

  • 核心发现: DIFT 揭示了一个令人惊叹的现象:预训练的文本到图像扩散模型(如 Stable Diffusion)本身就是一个极其强大的、零样本(Zero-shot)的特征提取器。即使不进行任何微调,它中间层的特征图也包含了极其丰富的语义对应关系。
  • 技术原理:
    1. 给定两张不同的图片(比如一张实拍的猫,一张手绘的狗)。
    2. 给它们加上特定时间步 tt 的噪声。
    3. 把加噪后的图像送入预训练的 UNet。
    4. 提取 UNet 解码器中特定层的特征图。
    5. 计算两张图片特征图之间的余弦相似度。 结果是:模型能极其精准地把猫的左眼和狗的左眼在像素级别上匹配起来。
  • 为什么能做到? 扩散模型在训练去噪的过程中,为了还原图像,被迫在网络的不同深度学习了不同层级的特征。高噪声阶段学到了高级的全局语义;低噪声阶段学到了低级的边缘和纹理。DIFT 就是把这些隐藏的语义特征直接“白嫖”出来用了。

PhotoMaker

了解 PhotoMaker,是为了看清 CharaConsist 这种免训练方法在整个技术生态里的位置。

  • 技术路线: PhotoMaker 属于基于参考图的身份保持方法。它需要引入预训练的图像编码器,并训练额外的投影模块,硬生生地把身份信息嵌入到生成过程中。
  • 优缺点对比: 这类方法通过庞大的数据集训练,能很好地维持人脸的固定特征。但是,它会“过拟合”到这张脸上,根本无法保证角色的衣服、背景场景的一致性。
  • CharaConsist 的互补性: CharaConsist 作为免训练方法,优势在于精细的背景和服装控制。正如作者在论文局限性中所探讨的,最理想的状态是将 PhotoMaker 等训练模型的“面部保持能力”与 CharaConsist 的“背景服装一致性能力”结合起来。

局部性偏见

在 FLUX.1 中,RoPE 是在每一个注意力层直接应用的。当同一个角色在两张图片中的位置发生大幅变动时,模型会表现出明显的“局部性偏见”——它倾向于把注意力分配给空间上相近的区域,而不是语义上对应的区域。 既然 RoPE 是在注意力计算时才加上去的,作者巧妙地提取了没有任何位置编码的原始 Key(K0K^0),然后强制用新图像中的目标坐标对其重新进行 RoPE 编码(Kfg,id′=RoPE(Kfg,id0,Cfg,frm)K'_{fg,id} = RoPE(K^0_{fg,id}, C_{fg,frm})) 。这直接在底层拉平了位置偏移带来的影响。


核心数学机制推导

流程设定与数学符号

两阶段生成

为了实现前后一致的生成,CharaConsist 将整个生成任务明确划分为了两个阶段:

  • 第一阶段:身份图像生成
    • 做法: 这一步就是完全使用原生的 FLUX.1 模型生成一张基准图(也就是要保持一致的那个“角色”或“场景”),不加任何修改。
    • 暗箱操作: 虽然生成过程没变,但模型在后台悄悄保存了特定时间步和特定层的中间变量。这些变量主要包括注意力机制中的键(Keys, KK)、值(Values, VV)以及注意力输出。
  • 第二阶段:帧图像生成
    • 做法: 当需要生成这个角色的新动作或新场景时(即“帧图像”),模型会去“读取”第一步保存的那些中间变量,强行干预当前的生成过程,从而实现一致性。 核心优势: 之前的免训练方法(比如 StoryDiffusion 或 ConsiStory)通常需要把 2 到 4 张图片放在一个 Batch 里并行生成,让它们互相参考,这极其消耗显存。而 CharaConsist 凭借强大的追踪机制,只需要单张身份图像作为参考,彻底摆脱了并行生成的显存噩梦。

数学符号

因为 FLUX.1 的架构比较复杂,为了方便用公式表达,作者在 3.1 节对注意力机制做了一个极其精简的“统一数学抽象”。 序列拼接 : 无论什么 Block,核心都是把文本 Token 和图像 Token 拼在一起。- 设文本 Token 的长度为 ll 。

  • 设图像的特征分辨率为 h×wh\times w(在 FLUX.1 中,这是原图分辨率的 1/16)。
  • 那么多模态拼接后的总输入序列 XmmX_{mm} 就被定义为:Xmm=cat[Xt,Xi]X_{mm}=cat[X_t,X_i] 。这里的 catcat 代表拼接,tt 代表文本,ii 代表图像,mmmm 代表多模态 标准注意力计算: 接着,通过线性映射得到用来算注意力的三个核心矩阵:Q,K,VQ,K,V(Query, Key, Value)。
  • 计算注意力权重矩阵 WmmW_{mm} : Wmm=Qmm⋅KmmTdW_{mm}=\frac{Q_{mm}\cdot K_{mm}^{T}}{\sqrt{d}} (dd 是注意力头的维度 )
  • 最后,经过 Softmax 激活并乘以 VmmV_{mm},得到统一的注意力输出 HmmH_{mm},这个输出又可以拆分回文本特征 HtH_t 和图像特征 HiH_i : Hmm=Softmax(Wmm)⋅Vmm=cat[Ht,Hi]H_{mm}=Softmax(W_{mm})\cdot V_{mm}=cat[H_t,H_i] 下标维度:在 CharaConsist(以及 FLUX.1 的官方实现)中,变量的下标严格对应了它的序列长度:
  • 带有 mm 下标(Multimodal,多模态):
    • 序列长度:l+hwl + hw (文本和图像拼在一起)
    • 代表变量:XmmX_{mm}, QmmQ_{mm}, KmmK_{mm}, WmmW_{mm}, HmmH_{mm}
    • 出现场景:只要是在 Transformer Block 内部做全局 Attention 计算的输入和输出,都是这个完整的超长序列。
  • 带有 i 下标(Image,图像):
    • 序列长度:hwhw (纯图像 Token)
    • 代表变量:XiX_i, HiH_i, Ai2tA_{i2t}
    • 出现场景:当我们算完 Attention 后,把前面的 ll 个文本 Token 砍掉,只保留后面的图像特征时。
  • 带有 fg 或 bg 下标(Foreground / Background,前景 / 背景):
    • 序列长度:NfgN_{fg} 或 NbgN_{bg} (仅包含掩码抠出来的那部分像素)
    • 代表变量:HfgH_{fg}, KfgK_{fg}, CfgC_{fg}
    • 出现场景:进一步用坐标索引(比如 CfgC_{fg})从 hwhw 里面切片取出来的时候

跨层点匹配

背景

CharaConsist 的计划是,把“身份图像”生成时算出来的 KK、VV 和 HiH_i 偷偷存下来。在生成“帧图像”时,把帧图像的 QQ 拿去和存下来的 KK 算注意力,从而把身份图像里的细节“搬运”过来。 但这里有一个巨大的鸿沟,也是这篇论文要解决的核心数学问题:如果帧图像里的人举起了手,或者跑到屏幕左边去了,原坐标就对不上了(这就是前面提到的 RoPE 带来的局部性偏见)。 所以,在进行上面说的“搬运”之前,模型必须先解决两件事:

  1. 点匹配: 找出帧图像里的“手”对应身份图像里的哪个位置。
  2. 掩码提取: 把前景(人物)和背景(环境)剥离开来,分别控制。

相似度矩阵

接下来我们首先讨论点匹配的实现。 目标: 对于当前生成的“帧图像”中的每一个点,我们需要在“身份图像”中找到与其语义上最对应的点。比如,新图里人物的手,得精准对应到原图里人物的手。挑战: 作者在 FLUX.1 上测试发现,如果直接取注意力层的输出算相似度,匹配点会在不同层、不同时间步甚至不同样本之间发生极其剧烈的波动,根本无法稳定匹配。 破局点(公式 4 与 5): 既然单层的数据在“跳舞”,但整体的相似度分布特征是相对一致的,作者就简单粗暴但极其有效地对同一个时间步下的所有层的余弦相似度求了平均 : S∗=1N∑nHi,frm,n⋅Hi,id,nT∣∣Hi,frm,n∣∣2⋅∣∣Hi,id,n∣∣2S^{*}=\frac{1}{N}\sum_{n}\frac{H_{i,frm,n}\cdot H_{i,id,n}^{T}}{||H_{i,frm,n}||_{2}\cdot||H_{i,id,n}||_{2}}

  • Hi,frm,nH_{i,frm,n} 和 Hi,id,nH_{i,id,n} 分别代表帧图像和身份图像在第 nn 层的图像注意力输出 。
  • NN 是总层数 。
  • 这个公式计算了图像之间 Token 的余弦相似度,并进行了跨层累加平均,得到了稳定的相似度矩阵 S∗S^{*} 。

最大值

有了这个稳定的矩阵,接下来就是找最大值了: map∗,Smax∗=arg⁡max⁡(S∗),max⁡(S∗)map^{*}, S_{max}^{*}=\arg\max(S^{*}), \max(S^{*})

  • map∗(j)=kmap^{*}(j)=k 的物理意义非常明确:它告诉你帧图像里的第 jj 个点,死死锁定在了身份图像的第 kk 个点上 。
  • Smax∗S_{max}^{*} 则是这对匹配点之间的平均余弦相似度得分,它反映了这次匹配的“置信度” (这个得分在后面的 Token 融合中会起到大作用)。
公式详解

我们先看 S∗S^{*} 是什么。假设帧图像有 hwhw 个 Token,身份图像也有 hwhw 个 Token。那么经过前面公式的计算,S∗S^{*} 就是一个大小为 hw×hwhw \times hw 的二维矩阵 。

  • 矩阵的行: 代表帧图像中的第 jj 个 Token。
  • 矩阵的列 : 代表身份图像中的第 kk 个 Token。
  • 矩阵里的每一个值,就是这两个 Token 之间的平均余弦相似度。 现在,我们要为帧图像里的每一个 Token jj,在身份图像里找一个最匹配的 Token kk:
  • map∗=arg⁡max⁡(S∗)map^{*} = \arg\max(S^{*}): 这是在做索引定位。它顺着 S∗S^{*} 的每一行,去找最大值所在的列号 kk。得到的 map∗map^{*} 就像一本字典(或者说是一个长度为 hwhw 的一维数组),比如 map∗(j)=kmap^{*}(j) = k,意思是:帧图像里的第 jj 号点,对应着身份图像里的第 kk 号点。
  • Smax∗=max⁡(S∗)S_{max}^{*} = \max(S^{*}): 这是在提取置信度得分。光知道“谁匹配谁”还不够,还得知道匹配得有多像。它把刚才找到的最大相似度数值给抽出来。得到的 Smax∗S_{max}^{*} 也是一个长度为 hwhw 的一维数组,里面的值介于 [−1,1][-1, 1] 之间,代表这对匹配点的可信度。在后续的自适应 Token 融合时,如果匹配得分太低,这个权重就会把那些“强行匹配但其实不像”的噪点给压制住。

掩码提取

目标: 在实际应用中,我们有时候只换动作不换背景,有时候又要换背景。为了实现前背景的解耦控制,模型必须自动把人物(前景)的 Mask 抠出来 。 技巧: 这个提取策略非常巧妙,它纯粹依赖于图像 Token 对不同文本 Token 的注意力权重差异。 前置设定: 作者要求写提示词时必须按套路出牌:先写背景,再写前景。比如:“In a modern gym(背景),a muscular man…(前景)” 。这样我们就知道了背景文本的长度 lbgl_{bg} 和前景文本的长度 lfgl_{fg} 。

提取图文注意力权重

Ai2t=Softmax(Wmm[l:,:lbg+lfg])A_{i2t}=Softmax(W_{mm}[l:, :l_{bg}+l_{fg}])

  • 模型只截取了图像作为 Query、文本作为 Key 的那部分注意力权重 WmmW_{mm} 。
  • 注意,这里只在实际文本序列长度内做 Softmax 操作,这是为了排除掉图像 Key 以及特殊文本 Key <s> 带来的干扰。

为什么必须是 l:? 因为在 FLUX.1 的多模态拼接机制中,完整的输入序列是先把长度为 ll 的文本 Token 放在前面,再把长度为 hwhw 的图像 Token 紧接着拼在后面。

  • 当我们计算整个大注意力矩阵 WmmW_{mm} 时,它的尺寸是 (l+hw)×(l+hw)(l+hw) \times (l+hw) 。
  • 我们现在只关心图像 Token 作为 Query,去关注文本 Token (Key) 的情况。
  • 图像 Token 在序列的后半段,所以行的索引必须从 ll 开始,也就是 l: 。
  • 文本 Token 在序列的前半段,所以列的索引是 :l_{bg}+l_{fg} 。

抑制波动,双重平均

和点匹配一样,图文注意力权重在不同层之间也波动剧烈。因此,作者分别在背景文本段和前景文本段内求平均,同时也在所有层 NN 之间求平均:

  • 图像对背景的平均注意力: Ai2bg∗=1N×lbg∑n∑j=0lbg−1Ai2t,n[:,j]A_{i2bg}^{*}=\frac{1}{N\times l_{bg}}\sum_{n}\sum_{j=0}^{l_{bg}-1}A_{i2t,n}[:,j]
  • 图像对前景的平均注意力: Ai2fg∗=1N×lfg∑n∑j=lbglbg+lfg−1Ai2t,n[:,j]A_{i2fg}^{*}=\frac{1}{N\times l_{fg}}\sum_{n}\sum_{j=l_{bg}}^{l_{bg}+l_{fg}-1}A_{i2t,n}[:,j]

二值化掩码

有了这两个平均得分,生成 Mask 就变成了极其简单的大小比较: M=Ai2fg∗>Ai2bg∗∈{0,1}hwM=A_{i2fg}^{*}>A_{i2bg}^{*}\in\{0,1\}^{hw}

  • 对于图像上的每一个像素 Token,如果它对前景文字的关注度大于对背景文字的关注度,我们就认为它是前景(值为 11),否则就是背景(值为 00)。 在附录中作者提到,提取出来的原始 Mask 可能会有一些孤立的噪点或空洞。为了解决这个问题,他们在原始掩码上应用了形态学操作:先用 3×33\times3 的核进行腐蚀,接着用 5×55\times5 的核进行膨胀。使用更大的膨胀参数是为了防止丢失前景的边缘信息。

腐蚀:做减法,去噪点

  • 操作机制:定义一个滑动窗口(也就是核,Kernel),比如论文里用的 3×33\times3 核。让这个小窗口在整张 Mask 上逐像素滑动。
  • 严苛的规则:只有当这个 3×33\times3 窗口覆盖的 9 个像素全部都是白色时,中心像素才保持白色;只要窗口里混进了一个黑色像素,中心像素就立刻变成黑色。
  • 直观效果:所有的白色区域都会“瘦一圈”。那些原本就极其微小的白色孤立噪点,因为填不满整个 3×33\times3 的窗口,会被这个规则瞬间“抹杀”掉。这样背景就干净了。 膨胀:做加法,补空洞
  • 操作机制:同样是用一个核在图像上滑动,论文里作者换了一个更大的 5×55\times5 核。
  • 宽容的规则:只要这个 5×55\times5 窗口覆盖的 25 个像素中有任何一个是白色,中心像素就变成白色。只有全黑才保持黑色。
  • 直观效果:所有的白色区域都会向外扩张。这不仅能填补人物内部那些细小的黑色空洞,还能把人物的轮廓放大。 这种“先腐蚀后膨胀”的连招,在图像处理中有一个专门的名字,叫做开运算(Opening Operation)。作者这里的参数设计非常巧妙:
  1. 先用 3×33\times3 腐蚀:无情地干掉背景里那些烦人的孤立噪点。但代价是,我们想要保留的真实人物前景,也被硬生生“刮掉了一层皮”,变瘦了。
  2. 再用更大的 5×55\times5 膨胀:不仅要把刚才人物“瘦掉”的那圈肉补回来,还要让它再多胖一点!
  3. 为什么核要变大? 论文解释得很清楚,使用更大的膨胀参数,是为了防止丢失前景的边缘信息。因为人的头发丝、衣服的毛边往往很细微,如果在腐蚀阶段被擦掉,用同样大小的核膨胀可能补不回来。用 5×55\times5 的大核,能确保生成一个比实际人物稍微大一圈的“安全保护罩”,把所有属于人物的特征都死死地框在前景里。

AA 矩阵维度的全景梳理

为了不被绕晕,我们把每一个 AA 的形状单独拿出来看。假设文本总长度 l=512l=512,图像 Token 数量 hw=1024hw=1024。背景词长度 lbg=10l_{bg}=10,前景词长度 lfg=5l_{fg}=5。

  • Ai2tA_{i2t} (图像对文本的原始注意力):
    • 维度:hw×(lbg+lfg)hw \times (l_{bg}+l_{fg})
    • 它是一个 1024×151024 \times 15 的矩阵。每一行代表图像上的一个点,每一列代表它对这 15 个具体单词的关注程度。
  • Ai2bg∗A_{i2bg}^{*} (图像对背景的平均关注度):
    • 操作:我们把 Ai2tA_{i2t} 的前 lbgl_{bg} 列(也就是前 10 列)拿出来,在列方向上求个平均 。
    • 维度:变成了一个长度为 hwhw 的 1 D 向量(尺寸:10241024)。
    • 图像上的每个点,对整个“背景描述”的综合关注度得分。
  • Ai2fg∗A_{i2fg}^{*} (图像对前景的平均关注度):
    • 操作:我们把 Ai2tA_{i2t} 剩下的 lfgl_{fg} 列(后 5 列)拿出来,同样在列方向上求平均 。
    • 维度:也是一个长度为 hwhw 的 1 D 向量(尺寸:10241024)。
    • 图像上的每个点,对整个“前景描述”的综合关注度得分。
  • MM (最终的前景掩码):
    • 操作:直接拿两个 1D 向量做逐元素的逻辑比较(大于号 >)。
    • 维度:依然是一个长度为 hwhw 的 1D 向量(尺寸:10241024),只不过里面的值全变成了 00 或 11 。

点追踪注意力

核心痛点: 之前我们提到过,FLUX.1 里的 RoPE(旋转位置编码)会带来局部性偏见。如果同一张脸在第一张图的左边,在第二张图的右边,模型就会觉得它们相距甚远,拒绝给足注意力权重。 绝妙的破解之法(公式 10 到 17): 首先,我们要拿出前面算好的两样东西:前景掩码 MM 和匹配字典 map∗map^{*}。

提取索引

我们要知道帧图像(新图)里的前景都在哪些位置,记作 Cfg,frmC_{fg,frm} 。 Cfg,frm=nonzero(Mfrm)C_{fg,frm}=nonzero(M_{frm})

  • 具体过程: 前面我们算出 MM 是一个长度为 hwhw 的一维数组,里面的值只有 00(背景)和 11(前景)。nonzero() 是深度学习框架(如 PyTorch)中的一个标准函数,它的作用就是把数组中所有不为 00 的元素的位置下标挑出来。
  • 物理意义: 假设特征图有 1024 个点,其中第 5、8、12 个点是人物(值为 1),那么 Cfg,frmC_{fg,frm} 就是一个列表 [5, 8, 12]。它相当于一份“坐标白名单”,告诉模型:“只管这几个位置,其他的别动”。 然后顺着字典查出,这些点在身份图像(原图)里对应的位置是哪些,记作 Cfg,idC_{fg,id}。 Cfg,id=map∗(Cfg,frm)C_{fg,id}=map^{*}(C_{fg,frm})

获取纯粹的语义信息

根据查到的位置 Cfg,idC_{fg,id},我们把身份图像里对应的 Key (KK) 和 Value (VV) 抽取出来。最关键的是,我们抽取的 Key 是没有任何位置编码的原始版本,记作 K0K^{0} 。它只包含“长什么样”的语义,不包含“在哪儿”的信息。 如何抽取 K0K^{0}:

  • 传统模型 vs. FLUX.1: 在以前的模型(比如早期的 ViT 或 SD 1.5 的 UNet)中,绝对位置编码是在网络的最输入端直接加到图像特征上的。一旦加进去,就“融为一体”了,后续很难再把位置信息干净地剥离出来。
  • FLUX.1 的 RoPE 机制: FLUX.1 使用的是旋转位置编码(RoPE)。最关键的是,RoPE 是在每一个注意力层内部、在进行点积之前才“临时”应用上去的。
  • 截取过程: 在注意力层的最开始,输入的特征 XX 会先经过一个线性层映射成 QQ、KK、VV。在这个瞬间,映射出来的 KK 是纯粹的语义特征,完全没有位置信息,这就是我们要找的 K0K^{0} 。代码实现上,只需要在 K0K^{0} 被送进 RoPE 函数进行旋转变换之前,把它拦截并克隆一份存下来即可。

为什么当前的 K0K^{0} 不会带有之前层注入的 RoPE 位置信息? 这是 Transformer 架构设计中一个非常隐蔽但极其巧妙的细节。要理解这个,我们必须把注意力机制的内部数据流拆开来看。 在 FLUX.1 的某一个注意力层内部,数据先后经历:

  1. 线性映射产生 Q、K、V:上一层的输出特征(纯语义特征)进入当前层后,首先经过线性映射层,生成了 QQ(Query)、K0K^{0}(纯语义 Key)和 VV(纯语义 Value)。
  2. RoPE 只作用于 Q 和 K:接下来,RoPE 函数仅仅对 QQ 和 K0K^{0} 进行了旋转矩阵乘法,得到了带有位置信息的 Q′Q^{\prime} 和 K′K^{\prime}
  3. 计算注意力得分:模型用带有位置信息的 Q′Q^{\prime} 和 K′K^{\prime} 进行点积(Q′⋅(K′)TQ^{\prime} \cdot (K^{\prime})^T),算出注意力权重矩阵。
  4. 与 V 相乘产生输出:这个算出来的注意力权重矩阵,最终是乘在了 VV 上面的,而 VV 是从来没有经过 RoPE 旋转的。
  5. 进入下一层:注意力机制的输出(本质上是 VV 的加权求和)经过前馈网络(MLP)和残差连接后,传递给下一层。 因为 RoPE 只参与了 QQ 和 KK 的点积,而没有参与与 VV 的相乘,所以被搬运到下一层的潜变量里,并没有被硬编码进上一层的旋转位置矩阵。当下一层再次对这个潜变量进行线性映射时,提取出来的 K0K^{0} 不会带有之前层注入的位置信息。

重新编码 RoPE

我们把刚刚抽出来的纯语义 Key (Kfg,id0K_{fg,id}^{0}),强行用新图的空间坐标 (Cfg,frmC_{fg,frm}) 给它打上新的 RoPE 烙印。 Kfg,id′=RoPE(Kfg,id0,Cfg,frm)K_{fg,id}^{\prime}=RoPE(K_{fg,id}^{0},C_{fg,frm}) 这一招直接欺骗了注意力机制:模型以为这个特征本来就在新位置上,彻底消除了距离带来的注意力衰减。

组装与注意力计算

接着,我们把新图自己的特征、重现编码的身份特征、以及背景特征拼接在一起,作为最终的 Key 和 Value 。在算注意力时,再用一个对角线掩码 M∗M^{*} 限制一下:只让前景看前景,背景看背景。

信息拼接

假设每个注意力头的特征维度是 dd。当前图像总共有 l+hwl + hw 个 Token(包含了文本和图像的长度),其中前景抠出来了 NfgN_{fg} 个 Token,背景抠出来了 NbgN_{bg} 个 Token。 Kfrm∗=cat[Kmm,frm,Kfg,id′,Kbg,id]K_{frm}^{*}=cat[K_{mm,frm}, K_{fg,id}^{\prime}, K_{bg,id}]

  • 这里的 cat 是在序列长度这个维度上进行的拼接。
  • Kmm,frmK_{mm,frm}:这是当前帧图像(新图)原原本本的 Key。它的维度是 (l+hw)×d(l + hw) \times d。
  • Kfg,id′K_{fg,id}^{\prime}:这是我们刚才从身份图像(旧图)里抽出来的纯语义前景 Key,并且已经用新图的坐标重新做过 RoPE 旋转了。它的维度是 Nfg×dN_{fg} \times d。
  • Kbg,idK_{bg,id}:这是从身份图像里抽出来的背景 Key。这部分是可选的,取决于用户是否想要保持背景不变 。它的维度是 Nbg×dN_{bg} \times d。
  • 拼接后的 Kfrm∗K_{frm}^{*} 的维度变成了 (l+hw+Nfg+Nbg)×d(l + hw + N_{fg} + N_{bg}) \times d。
计算注意力得分矩阵

Wfrm∗=Qmm,frm⋅Kfrm∗Td+log⁡(M∗)W_{frm}^{*}=\frac{Q_{mm,frm}\cdot K_{frm}^{*T}}{\sqrt{d}}+\log(M^{*})

  • Qmm,frmQ_{mm,frm}:当前帧图像正在生成的内容(Query)。
  • Kfrm∗TK_{frm}^{*T}:这是作者精心拼接的新 Key 矩阵 。里面包含了当前帧自己的 Key、刚才重新编码过位置的 K′K^{\prime}、还有背景的 Key。
  • 前半部分 Q⋅KTd\frac{Q \cdot K^T}{\sqrt{d}}:这是常规的相似度计算。分数越高,说明 Query 越应该关注这个 Key。
  • 后半部分 +log⁡(M∗)+\log(M^{*}) (掩码):这是深度学习里非常经典的 Attention Mask 技巧。
    • M∗M^{*} 是一个矩阵,规定了谁能看谁(比如强制要求:新图的前景只能看旧图的前景,不能看背景 )。
    • 如果允许看,对应的 M∗M^{*} 值为 11,那么 log⁡(1)=0\log(1) = 0,得分不变。
    • 如果不允许看(禁止连接),对应的 M∗M^{*} 值为 00,那么 log⁡(0)→−∞\log(0) \to -\infty。
    • 结果就是,不该有关联的区域,其注意力得分变成了负无穷大。
  • 得到的注意力得分矩阵 Wfrm∗W_{frm}^{*} 的维度是 (l+hw)×(l+hw+Nfg+Nbg)(l + hw) \times (l + hw + N_{fg} + N_{bg}) 。
生成最终的追踪特征

Hmm,frm∗=Softmax(Wfrm∗)⋅Vfrm∗H_{mm,frm}^{*}=Softmax(W_{frm}^{*})\cdot V_{frm}^{*}

  • Softmax(Wfrm∗)Softmax(W_{frm}^{*}):把刚才的得分矩阵变成概率分布(加起来等于 1)。刚才那些被标为 −∞-\infty 的地方,经过 Softmax 后会直接变成 e−∞=0e^{-\infty} = 0。这就彻底切断了前景和背景之间错误的特征流动。
  • ⋅Vfrm∗\cdot V_{frm}^{*}:最后,把算好的概率权重乘以上下文信息(Value 矩阵)。
  • Hmm,frm∗H_{mm,frm}^{*} 的维度是 (l+hw)×d(l+hw) \times d 经过这两步,输出的 Hmm,frm∗H_{mm,frm}^{*} 里,新图的前景区域就完美、干净地填满了来自旧图对应前景的高保真语义信息。

自适应 Token 融合

重新编码虽然解决了长距离注意力衰减的问题,但它粗暴地打乱了像素原本的排列,会破坏局部的几何结构。而且,前面的点匹配 map∗map^{*} 毕竟是用余弦相似度估算的,肯定有匹配不准的噪点。 为了把丢失的信息补回来,作者直接对注意力层的输出(HH)进行了插值融合。 Hfg,frm∗∗=(1−αSmax∗)Hfg,frm∗+αSmax∗Hfg,id′H_{fg,frm}^{**}=(1-\alpha S_{max}^{*})H_{fg,frm}^{*}+\alpha S_{max}^{*}H_{fg,id}^{\prime}

  • 时间衰减参数 α\alpha: 它随着时间步的推进而逐渐减小。因为生成前期(去噪刚开始)定的是大框架和身份特征,需要多参考身份图像;生成后期主要是在画衣服纹理和背景细节,就不需要过多干预了。

α\alpha 与 tt (时间步) 的函数关系是什么? 论文正文中并没有给出一个极其严密的数学方程式,而是给出了它的变化原则和作用范围: 定性衰减关系: 论文明确指出,α\alpha 是一个在 [0,1][0, 1] 之间的超参数,并且随着生成过程中的时间步推移而衰减。 具体实施区间: 在附录的实现细节中,作者提到,FLUX.1 默认采样 50 步。他们从第 1 步就开始引入这个自适应融合模块,一直用到第 40 步。最后 10 步直接停用了这个模块(α\alpha 相当于降为 0),因为最后阶段对一致性没有显著影响,只专注画质。

  • 置信度守门员 Smax∗S_{max}^{*}:这就是我们之前在匹配时求出的“最大余弦相似度得分” 。如果某个点匹配得非常勉强(得分很低),那么 αSmax∗\alpha S_{max}^{*} 就会趋近于 0,模型就会拒绝融合这个不可靠的特征,防止把错误的特征引进来。

详解维度变化

Hfg,frm∗∗=(1−αSmax∗)Hfg,frm∗+αSmax∗Hfg,id′H_{fg,frm}^{**}=(1-\alpha S_{max}^{*})H_{fg,frm}^{*}+\alpha S_{max}^{*}H_{fg,id}^{\prime} 这里的各种 HH 确实容易看花眼,但只要我们带入维度,它们就会变得非常清晰。 假设当前图像依然有 hwhw 个像素 Token(例如 1024),每个 Token 的特征维度是 dd。前景抠出来了 NfgN_{fg} 个点(例如 300 个点)。 第一步:提取当前帧(新图)的前景特征 Hfg,frm∗H_{fg,frm}^{*} Hmm,frm∗→拆分cat[Ht,frm∗,Hi,frm∗]H_{mm,frm}^{*} \xrightarrow{\text{拆分}} cat[H_{t,frm}^{*}, H_{i,frm}^{*}]

  • 网络把这个大杂烩从中间切开。我们丢掉前面的文本部分 Ht,frm∗H_{t,frm}^{*},只保留后面的图像部分 Hi,frm∗H_{i,frm}^{*}。
  • 此时,Hi,frm∗H_{i,frm}^{*} 的维度就变成了干净的 hw×dhw \times d 。这代表整张新图(包含前景和背景)的所有像素特征 Hfg,frm∗=Hi,frm∗[Cfg,frm]H_{fg,frm}^{*}=H_{i,frm}^{*}[C_{fg,frm}]
  • 我们并不想动背景,所以我们根据前景坐标 Cfg,frmC_{fg,frm}(长度为 NfgN_{fg}),把属于前景的那部分特征切片单独提取出来,这就是 Hfg,frm∗H_{fg,frm}^{*} 。
  • 维度是 Nfg×dN_{fg} \times d(即 300×d300 \times d)。它代表新图里人物经历过注意力机制后,当下的特征状态。 第二步:提取身份图像(旧图)的对应前景特征 Hfg,id′H_{fg,id}^{\prime}
  • 在第一阶段生成身份图时,我们存下了一个原始的注意力输出 Hi,idH_{i,id} 。它的维度也是 hw×dhw \times d。
  • 重排与提取(公式 18): 这是极其关键的一步。我们不能直接把旧图的前景切下来,因为人的动作变了,点对不上。我们必须根据字典 map∗map^{*} 查到的对应坐标 Cfg,idC_{fg,id},去旧图的输出里把对应点的特征抓过来,并按照新图的顺序排好。提取和重排后得到的矩阵,在论文公式 (18) 中记为 Hfg,idH_{fg,id},而在融合公式 (20) 中为了区分加上了撇,记作 Hfg,id′H_{fg,id}^{\prime} 。
  • 维度也是 Nfg×dN_{fg} \times d。它代表了旧图中最纯正的参考特征,并且已经被像拼图一样,拼成了新图人物现在的姿势。 第三步:置信度 Smax∗S_{max}^{*}
  • 它是我们在点匹配时算出的“最大余弦相似度”,维度是 **Nfg×1N_{fg} \times 1。
  • 如果某个点匹配得非常完美,得分接近 1,那么 αSmax∗\alpha S_{max}^{*} 就会比较大,模型就会大胆地把旧图特征 Hfg,id′H_{fg,id}^{\prime} 融入进来 。如果某个点匹配得分很低(比如旧图里根本没有新图里的手),分数接近 0,那么权重就变成了 00,模型就会彻底抛弃旧图特征,保留新图自己的特征 (1−0)Hfg,frm∗(1-0)H_{fg,frm}^{*} 。这就完美防止了错误特征的污染。 第四步:终极融合 Hfg,frm∗∗H_{fg,frm}^{**}
  • 把上面两个 Nfg×dN_{fg} \times d 的矩阵,用 (1−权重)(1 - 权重) 和 权重权重 进行逐元素相加 。
  • 得到的 Hfg,frm∗∗H_{fg,frm}^{**}(维度依然是 Nfg×dN_{fg} \times d)就是一个既包容了新动作、又完美继承了旧身份和旧纹理的“完美潜变量”。
  • 最后,用这个融合后的完美前景特征,替换掉原来的 Hi,frm∗H_{i,frm}^{*} 中的对应位置,继续往下传给后续的神经网络层。

实验评估与对比

实验设置

评估数据集

现有的基准测试缺乏适合评估角色和环境一致性的特征。因此,作者使用 GPT-4 生成了一系列专门针对这种应用场景的文本到图像(T2I)提示词。 提示词格式:所有的提示词都遵循 “[环境], [角色], [动作].” (“[Environment], [Character], [Action].”) 的固定格式。 数据量:每组包含 5-8 个提示词,总共为这两个任务生成了超过 200 个 T2I 提示词。

两大评估任务

  • 背景保持任务 (Background maintaining):在这一组提示词中,“[环境]” 和 “[角色]” 保持一致,只有 “[动作]” 发生变化 。这用来测试模型在人物乱动时,能不能稳住背景。
  • 背景切换任务 (Background switching):在这一组中,只有 “[角色]” 保持不变(环境和动作都变) 。这用来测试模型能不能在完全不同的场景下,依然认出并画出同一个人。

对比方法

作者挑选了两类最具代表性的基线方法来进行擂台比拼 :

  • 免训练一致性方法:StoryDiffusion 和 ConsiStory 。这是同赛道的直接竞争对手。
  • 依赖训练的身份参考方法 :IP-Adapter 和 PhotoMaker 。为了让这类方法能跑起来,作者先用提示词里的 “[角色]” 部分生成头部照片,然后用 RetinaFace 裁剪出面部区域,作为这些方法的输入参考图。

评估指标

为了准确衡量什么是“细粒度(Fine-grained)”的一致性,作者除了使用常规指标,还引入了非常巧妙的解耦指标。

常规指标

使用 CLIP 文本-图像相似度 (CLIP-T) 来衡量生成的图像和文本提示词是否对齐,使用成对的 CLIP 图像相似度 (CLIP-I) 来衡量全图的整体一致性。

CLIP-T
  • 物理意义:衡量生成的图像与你输入的文本提示词(Prompt)有多契合 。
  • 计算本质:利用 OpenAI 预训练的 CLIP 模型,分别提取文本特征和图像特征,然后计算这两个高维向量在同一特征空间中的余弦相似度。
  • 数学抽象: 假设 CLIP 的文本编码器提取的向量为 EtextE_{text},图像编码器提取的向量为 EimageE_{image},则: CLIP-T=Etext⋅Eimage∣∣Etext∣∣2×∣∣Eimage∣∣2CLIP\text{-}T = \frac{E_{text} \cdot E_{image}}{||E_{text}||_{2} \times ||E_{image}||_{2}} 得分越接近 11,说明图文越匹配。
CLIP-I
  • 物理意义:衡量生成的一批图像(比如同一组 prompt 生成的 5 张图)之间的全图一致性 。
  • 计算本质:只使用 CLIP 的图像编码器。将同一组内生成的图像两两配对,计算它们图像特征向量的余弦相似度,最后求整个组的平均值。
  • 数学抽象: 对于一组生成的 MM 张图像,计算所有互异对 (i,j)(i, j) 的相似度平均: CLIP-I=2M(M−1)∑i=1M−1∑j=i+1MEimg_i⋅Eimg_j∣∣Eimg_i∣∣2×∣∣Eimg_j∣∣2CLIP\text{-}I = \frac{2}{M(M-1)} \sum_{i=1}^{M-1} \sum_{j=i+1}^{M} \frac{E_{img\_i} \cdot E_{img\_j}}{||E_{img\_i}||_{2} \times ||E_{img\_j}||_{2}}

解耦的 CLIP-I

这是评估体系的一大亮点。为了分别评估前景和背景的一致性,作者引入了 CLIP-I-fg(前景)和 CLIP-I-bg(背景) 。他们使用 SAM (Segment Anything) 模型对每张生成的图像进行前景分割,然后对遮罩后的前景和背景图像分别计算 CLIP 相似度。 计算流程 :

  1. 先用 SAM (Segment Anything) 大模型把生成的每张图的前景人物精确地抠出来,得到一个二值掩码(Mask,MfgM_{fg})。
  2. 用原始图像乘以掩码(Image⊙MfgImage \odot M_{fg})得到只有前景的纯净图像(背景全黑);用原始图像乘以反向掩码(Image⊙(1−Mfg)Image \odot (1 - M_{fg}))得到只有背景的图像。
  3. 把这些抠好的纯前景图和纯背景图分别送入 CLIP 算图像特征。
  4. 对纯前景特征算一遍公式 2,就是 CLIP-I-fg;对纯背景算一遍,就是 CLIP-I-bg。

身份相似度

为了评估面部身份的一致性,使用 RetinaFace 和 FaceNet 计算面部嵌入的相似度。

  • 物理意义:专门用来“刷脸”,测试人物的面孔是不是同一个人 。因为 CLIP 模型看全身比较准,但对极细微的面部特征不敏感。
  • 计算流程 :
    1. 使用 RetinaFace 检测出图像中的人脸边界框并裁剪。
    2. 送入专门做人脸识别的预训练模型 FaceNet,提取专门的人脸特征嵌入(Facial Embedding)。
    3. 同样使用余弦相似度公式,计算同一组图像中人脸特征的成对相似度平均值。

图像质量指标

使用 Q-Align 计算图像质量得分 (IQS) 和图像美学得分 (IAS)。

  • 物理意义:衡量生成的图像画质好不好(IQS,有没有模糊、噪点)以及美不美(IAS,构图、色彩分布) 。
  • 计算本质:这不是一个简单的数学公式可以算出来的。论文使用了 Q-Align 模型。这通常是一个大型的多模态大语言模型(VLM),它被训练成像人类考官一样,直接“看”图并给出一个连续的评分。

对比实验

在表 1 中,作者展示了在“背景保持”和“背景切换”两大任务下的得分 。

  • 对比免训练同行 (StoryDiffusion, ConsiStory): CharaConsist 在绝大多数一致性指标上都取得了最优成绩,尤其是在解耦的 CLIP-I-bg (0.916) 和 ID Sim (0.647) 上遥遥领先。这证明了依靠精确的 Mask 和点追踪,它不仅能稳住人物,还能完美锁定背景细节。
  • 对比需要训练的方法 (IP-Adapter, PhotoMaker): 在 CLIP-I-fg 和 CLIP-I-bg 上,CharaConsist 显著优于这些依赖训练的方法。原因很简单,PhotoMaker 它们眼里只有那张“脸”,根本不管衣服和背景是不是变了。 合理的劣势:在 ID Sim (身份相似度) 上,CharaConsist 没有超过 PhotoMaker (0.647 vs 0.891) 。但作者坦言,这并不矛盾。人家是拿成千上万张人脸专门训练出来的,而咱们是免训练的即插即用方法。

审稿人看这篇论文时肯定会问一个极其尖锐的问题:“你用了最新的 FLUX.1,别人用的是老旧的 SDXL,你的效果好,是不是纯粹因为 FLUX.1 画质好?” 作者在表 2 中用“增量对比 (Consistency increments comparison)”完美反击 :

  • 作者直接测试了未经任何修改的 FLUX.1 原生模型的生成一致性。结果发现,FLUX.1 的原生一致性得分(比如 CLIP-I)其实比基于 SDXL 的基线模型还要低。
  • 但是,一旦加上了 CharaConsist 的魔法,它的增量是所有方法中最大的。比如 ID Sim 直接提升了 +0.171(相比之下 ConsiStory 只提升了 +0.130) 。这铁证如山地表明:优异的效果源于作者提出的点追踪和自适应融合算法,而不是抱了 FLUX.1 的大腿。

消融实验

为了证明自己没有写一句废代码,作者把系统一层层剥开:

  • Baseline (纯 T2I):没有任何一致性保护。
    • (a) 点追踪注意力:加上这一步后,CLIP-I 和 ID-Sim 都有了显著提升(ID-Sim 从 0.476 飙升到 0.572) 。这证明了打破 RoPE 局部性偏见是极其有效的。
    • (a, b) 叠加自适应 Token 融合:指标进一步攀升(ID-Sim 达到 0.645) 。这说明插值融合成功兜底了点追踪带来的几何破坏和匹配噪点。
    • (a, b, c) 叠加前背景 Mask:此时 CLIP-I-bg 达到了最高的 0.916 。这证明了解耦控制对稳定背景起到了决定性作用。
  • 同时,加入这些模块后,IAS 和 IQS (图像质量得分) 几乎没有下降,稳定在 0.985 左右,证明这套方法是无损的。

视觉定性对比

跳出冷冰冰的数据,作者在图 2、图 10-13 中展示了生成的效果图。

  • 摆脱“复制粘贴”:其他免训练方法为了保持一致性,经常会把人物“卡死”在一个姿势,完全忽略了文本里要求的动作变化(比如要求“拿手机”、“拍照”,模型根本不理会)。
  • 细粒度之王:CharaConsist 不仅能让人物做出大幅度的新动作(比如举手、跑步),还能极其变态地保持细微背景的一致(比如图 11 中咖啡馆背景里黑板上的粉笔字,都做到了惊人的保持)。

局限性与未来探索

核心局限

  • 论文的自白:作为一个专注于“免训练(Training-free)”的一致性生成方法,CharaConsist 的强项在于根据文本提示词(Prompt)凭空捏造出一个前后一致的角色和场景,但它无法接受外部输入的真实身份图片作为参考。
  • 本质原因:因为整个系统没有引入任何额外的图像编码器(如 CLIP Image Encoder)或投影层,所有的特征都来源于第一阶段原生 FLUX.1 生成的“身份图”。如果你想输入一张你自己的真实自拍照,让模型生成你打篮球的动作,CharaConsist 是做不到的。

破局思路

在论文的最后,作者非常坦诚地指出了一个极具潜力的未来探索方向:将训练驱动的“身份参考模型”与 CharaConsist 结合起来。

  • Identity-reference 方法(如 PhotoMaker, IP-Adapter)的优势:它们擅长接受外部输入,能牢牢抓住人脸的特征(Facial similarity),保持极高的面部逼真度。
  • CharaConsist 的优势:能够精准控制背景环境(Background environments)和人物服装(Character clothing)的一致性,且不受大动作偏移的影响。
  • 完美互补:如果让 IP-Adapter 负责“画脸”,让 CharaConsist 负责“画衣服和背景”,就能在保持真实身份的同时,实现高保真的细粒度场景控制。
《CharaConsist》 论文精读
https://smallyo.top/blog/papers-CharaConsist
Author小yo
Published atMarch 10, 2026