当前位置: 首页 > news >正文

PhotoDoodle: Learning Artistic Image Editing from Few-Shot Examples 论文解读

目录

一、概述

二、PhotoDoodle

1、OmniEditor的预训练 

2、DiT重点

3、无噪声条件范式与CFM

4、EditLoRA

4.1关于LoRA

4.2关于EditLoRA

三、相关工作


一、概述

        风格化图像编辑的论文!

        介绍了PhotoDoodle,一个基于扩散模型的图像编辑框架,旨在通过少量示例学习艺术家的风格,实现照片的创意涂鸦(如添加装饰元素、艺术化处理),同时保持背景的完整性和一致性。

        该论文的动机:将普通图片转换成富有创意的艺术作品(比如添加手绘线条,几何图案,3D效果等),但以往的传统方法依赖于艺术家的手动操作,耗时且门槛高。

        现有方法不足之处:

  • 全局风格迁移​(如风格迁移模型)会全局修改图像纹理和颜色,导致背景内容被破坏,如人脸变成油画风格而失去真实感。
  • 局部修复方法​(如Inpainting)依赖精确遮罩标注,无法自动生成复杂元素,或者生成结果可能与背景透视或语义不匹配。
  • 难以从小样本学习:艺术家的独特风格需要从少量示例(30-50对图像)中高效捕捉,但现有的方法容易产生过拟合或欠拟合。

        PhotoDoodle提出的创新点:

  • 提出PhotoDoodle框架:一个基于DiT的少样本学习模型,并实现保证背景完整性同时进行特有的风格编辑
  • 噪音无关的条件范式:保留原图像的高频细节
  • EditLoRA:参数高效的风格微调方法,避免过拟合
  • 位置编码克隆:确保生成元素与背景的空间对齐
  • 高质量数据集:6种艺术风格、300+ pairs的photoDoodle数据集

二、PhotoDoodle

        PhotoDoodle分为两个部分,OmniEditor的预训练,EditorLoRA的微调。

The overall architecture and training paradigm of photodoodle

1、OmniEditor的预训练 

        对于内部DiT的优化在第二点进行展开介绍。

        看上面的图训练过程。

输入:

  - 源图像(I_src) → VAE编码 → 源图像隐变量 z_src
  - 目标图像(I_tar) → VAE编码 → 隐变量 z_0(真实目标隐变量)
  - 文本指令(T) → CLIP编码 → 文本嵌入 c_text

  - 前向扩散 对z_0添加随机噪声得到z_t(带噪声的隐变量)

  - 将源图像隐变量 z_src、带噪声的隐变量z_t、c_text三者concat输入到DiT中

输出:

 - 扩散模型(DiT)预测噪声 ε_θ,监督目标是让预测噪声逼近真实噪声 ε。

损失函数:(传统的去噪方式)

        最小化预测噪声ε_θ与真实噪声ε之间的MSE:

                        L=\mathbb{E}_{t,z_0,\varepsilon }[||\varepsilon -\varepsilon _\theta(z_t,t,z_{src},c_{text})||^2]

推理过程:(传统的去噪方式)

  - 源图像(I_src) → VAE编码 → 源图像隐变量 z_src
  - 文本指令(T) → CLIP编码 → 文本嵌入 c_text

  - 将源图像隐变量 z_src、文本嵌入c_text和高斯噪声z_T三者concat输入到DiT中进行多轮去噪,也就是说DiT预测出噪声ε_θ就要从z_T中去除这一部分,然后重新concat,输入到DiT中,反复去噪,最终将高斯噪声那一部分分离开得到z_0'

  - 解码生成图像I_tar'=VAEdecoder(z_0')

2、DiT重点

(1)位置编码克隆(PE Cloning)

        将源图像隐变量z_src的位置编码(空间坐标信息)复制到带噪声的隐变量z_t上,确保生成内容与源图像对齐。

        这一步在哪里做呢?当然是在DiT的自注意力机制后,先接RoPE编码后得到位置编码,再进行位置编码克隆。

(2)交叉注意力机制

        就是文中提到的MM attention,也就是在DiT的cross-attention中c_text作为Query,上一部分图像隐变量作为key/value。

        我的疑惑?为什么在DiT之前将z_src,z_tar,c_text拼接在一起输入,交叉注意力时是再次引入c_text,还是拆开c_text部分。

        后续理解:首先所谓的拼接,应该是均作为DiT的输入的意思(z_src,z_tar拼接在一起,c_text作为交叉注意力部分的输入),而且c_text应该是一维的,z_src和z_tar是二维的本身不能拼接。

3、无噪声条件范式与CFM

(1)CFM

        在PhotoDoodle中并没有使用扩散模型的方式,而是条件流的方式。

构建一个线性插值概率路径(从z_src到z_tar):

                ​​​​​​​        ​​​​​​​        z_t=(1-t)z_{src}+tz_{tar},t\in[0,1]

向量场预测(速度场预测):

        目的是预测z_t到z_tar的速度场v_\theta(z_t,t,c)

真实的速度场:(概率路径对t求导):

        v_{true}(z_t,t)=z_{tar}-z_{src}

损失函数(使用CFM后的损失函数):

        L_{CFM}=\mathbb{E}_{t,z_{src},z_{tar}}[||v_\theta(z_t,t,c_{text},z_{src})-(z_{tar}-z_{src})||^2]

(2)无噪声条件

        定义一个C_I与z_src相同表达对齐论文符号,也就是源图像经过VAE后的隐变量。

        无噪声条件就是指,相比于扩散模型引入了高斯噪声作为隐变量,CFM方法并不需要引入高斯噪声,这样可以确保生成内容与源图像的背景和结构严格对齐,完全依靠z_src和c_text来驱动,或者说是输入图像I_src和文本T的数据引导。

4、EditLoRA

        EditLoRA目标是通过少量示例(30-50 pairs)来学习艺术家风格,原理就是LoRA。

4.1关于LoRA

        LoRA的位置是并联在原模型某一部分的预训练权重处,在训练过程中冻结左侧原模型预训练权重,训练右侧LoRA,推理过程冻结所有参数,对模型结构不进行修改,不去除预训练模型进行推理。

        LoRA的核心思想是,通过在原始权重矩阵旁并联一个低秩的适配矩阵,来对原来模型进行微调,另一个是在SD模型中,可以对A场景下训练一个LoRA,之后将A LoRA植入B模型,可以使B模型学习到A模型的信息。

        什么是低秩适配矩阵?

        对于一个训练二维图像相关的预训练权重,我们可以看做是一个二维矩阵,比如100*100维,那么我们可以利用一个100*rank的A矩阵和rank*100的矩阵的乘积来代替这个100*100维的矩阵。其中在训练过程中A矩阵作kaiming均匀分布初始化,避免梯度消失或爆炸。B矩阵初始化为0矩阵,确保训练开始时低秩矩阵贡献为0,逐步学习。scale作为这个LoRA与原预训练权重merge时的比例,过大会覆盖原有的权重。

        LoRA公式:

        ​​​​​​​        ​​​​​​​        ​​​​​​​        W'=W+\Delta W=W +B \cdot A \cdot scale

        一个简单的LoraLInear示例,在这个类中已经把预训练模型(线性层)的结构写入了,但冻结了该部分的权重。

class LoRALinear(nn.Module):
    def __init__(self, in_features, out_features, merge, rank=16, lora_alpha=16, dropout=0.5):
        super(LoRALinear, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.merge = merge
        self.rank = rank
        self.dropout_rate = dropout
        self.lora_alpha = lora_alpha
        
        self.linear = nn.Linear(in_features, out_features)
        if rank > 0:
            # 修正维度:A (in_features, r), B (r, out_features)
            self.lora_a = nn.Parameter(torch.zeros(in_features, rank))
            self.lora_b = nn.Parameter(torch.zeros(rank, out_features))
            self.scale = self.lora_alpha / self.rank   #通过lora_alpha计算scale
            self.linear.weight.requires_grad = False   
        
        if self.dropout_rate > 0:
            self.dropout = nn.Dropout(self.dropout_rate)
        else:
            self.dropout = nn.Identity()
        
        self.initial_weights()
    
    def initial_weights(self):
        # 初始化 A 和 B
        nn.init.kaiming_uniform_(self.lora_a, a=math.sqrt(5))  #kaiming初始化lora_a
        nn.init.zeros_(self.lora_b)                            #0初始化lora_b
        
    def forward(self, x):
        if self.rank > 0 and self.merge:
            # 修正矩阵乘法和转置
            delta_w = (self.lora_a @ self.lora_b).T * self.scale
            merged_weight = self.linear.weight + delta_w
            output = F.linear(x, merged_weight, self.linear.bias)
            output = self.dropout(output)
            return output
        else:
            return self.dropout(self.linear(x))

         对于原来的fc层(也就是linear层)替换成并联lora的loralinear层。

# 示例:替换预训练模型的线性层为LoRALinear
original_layer = model.fc  # 假设原模型有一个全连接层
lora_layer = LoRALinear(
    in_features=768, 
    out_features=512, 
    merge=False, 
    rank=16, 
    lora_alpha=32
)
model.fc = lora_layer

# 训练时:仅训练LoRA参数
optimizer = torch.optim.Adam(lora_layer.parameters(), lr=1e-3)

# 推理时:合并权重
lora_layer.merge = True
output = model(input_data)
4.2关于EditLoRA

        流程:OmniEditor预训练模型冻结所有参数,在DiT部分的交叉注意力层处并联一个LoRA结构。

        重新提一遍OmniEditor的训练过程!

        首先VAE是自己训练的,text encoder肯定是预训练好的可能是clip,DIT使用的是Flux.1 Dev模型的DiT部分权重

        然后利用SeedEdit数据集在原有DiT权重下,接入一个rank=256的高秩LoRA模型,扩散过程替换成流匹配过程,开始训练。

        之后将这个rank=256的LoRA融入这个OmniEditor模块。

        EditLoRA微调部分!

        再次利用一个小规模风格化数据集(50对)来额外训练一个rank=128的低秩LoRA模块,并冻结以往OmniEditor的所有参数,仅训练低秩LoRA。

        将低秩LoRA合并到基础模型中,结束所有训练。

三、相关工作

        近期文本引导图像编辑有三个paradigms:全局描述(prompt2prompt、Imagic、EditWorld、ZONE,通过文本描述和图像区域之间跨模态对齐来实现细粒度操作,但需要对目标属性进行细致的文本规范),局部描述引导(Blended Diffusion、Imagen Editor通过显式掩码注释和区域文本提示实现像素级控制,但受到精确空间规范要求限制),instruction-guided形式(instructpix2pix、HIVE通过接受编辑命令,来消除以往详细文本描述和精确的mask依赖,提高用户可访问性)

参考项目:GitHub - showlab/PhotoDoodle: Code Implementation of "PhotoDoodle: Learning Artistic Image Editing from Few-Shot Pairwise Data" 

相关文章:

  • 两个桌面图标助手,你喜欢哪一个
  • uniapp vue3实现的一款数字动画调节器件,支持长按、单点操作,提供丝滑的增减动画效果
  • 03.04、化栈为队
  • 次日留存率——mysql计算过程
  • 【北大Deepseck】最新2份pdf(附不限速链接) 系列-提示词工程和落地场景 DeepSeek与AIGC应用
  • 【FL0087】基于SSM和微信小程序的民宿短租系统
  • Qt之3D绘制曲线:QtDataVisualization实时绘制散点图
  • 网络原理--IP协议简介
  • Git简单操作
  • EasyRTC嵌入式WebRTC技术与AI大模型结合:从ICE框架优化到AI推理
  • java练习(45)
  • 惯导(机械编排)算法(INS Mechanization)_预备知识笔记
  • 大语言模型的评测
  • server.servlet.session.timeout: 12h(HTTP 会话的超时时间为 12 小时)
  • # C# 中堆(Heap)与栈(Stack)的区别
  • 一文掌握使用深度学习识别验证码详解(包括图形验证码和滑块验证码)
  • Delphi 12.3 函数指针(函数可以当参数)
  • 7.1 线性代数进行图像处理
  • 【博资考4】网安学院-硕转博考试内容
  • 判断奇数偶数
  • 权威访谈丨国家疾控局就《世界卫生组织大流行协定》答记者问
  • 马上评|把孩子当牟利工具,这样的流量吃不得
  • 最高法:政府信息公开案件审理应避免泄露国家秘密、商业秘密
  • 新四军老战士、苏州市文联原副主席张景坤逝世
  • 王毅同丹麦外交大臣会谈,表示在格陵兰问题充分尊重丹麦主权和领土完整
  • 对话作家吉井忍:“滚石”般的生活,让我看到多种人生可能