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" 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/978623.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ操作实战

1.RabbitMQ安装 RabbitMQ Windows 安装、配置、使用 - 小白教程-腾讯云开发者社区-腾讯云下载erlang:http://www.erlang.org/downloads/https://cloud.tencent.com/developer/article/2192340 Windows 10安装RabbitMQ及延时消息插件rabbitmq_delayed_message_exch…

【Java项目】基于Spring Boot的校园博客系统

【Java项目】基于Spring Boot的校园博客系统 技术简介:采用Java技术、Spring Boot框架、MySQL数据库等实现。 系统简介:校园博客系统是一个典型的管理系统,主要功能包括管理员:首页、个人中心、博主管理、文章分类管理、文章信息…

【时时三省】(C语言基础)整型数据

山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 整型数据 (1)基本整型(int型) 编译系统分配给int型数据2个字节或4个字节(由具体的C编译系统自行决定)。在存储单元中…

Ollama下载安装+本地部署DeepSeek+UI可视化+搭建个人知识库——详解!(Windows版本)

目录 1️⃣下载和安装Ollama 1. 🥇官网下载安装包 2. 🥈安装Ollama 3.🥉配置Ollama环境变量 4、🎉验证Ollama 2️⃣本地部署DeepSeek 1. 选择模型并下载 2. 验证和使用DeepSeek 3️⃣使用可视化工具 1. Chrome插件-Page …

数据库的sql语句

本篇文章主要用来收集项目开发中,遇到的各种sql语句的编写。 1、根据user表的role_id字段,查询role表。 sql语句:使用JOIN连接两个表 SELECT u.*,r.rolename FROM user u JOIN role r ON u.role_id r.id WHERE u.id 1; 查询结果&#xff1a…

Grok 3 vs. DeepSeek vs. ChatGPT:2025终极AI对决

2025 年,AI 领域的竞争愈发激烈,三个重量级选手争夺霸主地位:Grok 3(由 xAI 开发)、DeepSeek(国内 AI 初创公司)和 ChatGPT(OpenAI 产品)。每个模型都有自己独特的优势,无论是在深度思考、速度、编程辅助、创意输出,还是在成本控制方面,都展现出强大的实力。但究竟…

手机大厂如何处理安卓分屏退出后最近任务显示一半问题?

背景: 近来在有学员朋友在群里讨论到了一个分屏退出后,在桌面最近任务中的卡片显示异常问题,虽然他的问题和目前市场上的最近任务显示一半情况不一样。但是这里也刚好启发了群里vip学员们对这个最近任务对分屏task只显示一半画面问题进行相关…

Spring Cloud——路由网关Zuul

??? 哈喽!大家好,我是【一心同学】,一位上进心十足的【Java领域博主】!??? 【一心同学】的写作风格:喜欢用【通俗易懂】的文笔去讲解每一个知识点,而不喜欢用【高大上】的官方陈述。 【一心同学】博客…

WorldQuant Brain的专属语言——Fast Expression

使用brain需要的编程语言 在使用BRAIN平台时往往不需要事先有编码背景,因此小白也能很快对其上手,但有经验的程序员来讲,该平台暂时没有禁止API通信低强度进行时的程序化访问(但是非常不好意思😣怎么访问我没找到&…

人大金仓KCA | 对象访问权限入门

人大金仓KCA | 对象访问权限入门 一、知识预备1. 对象的分类2. 对象访问权限概述3. 级联授权4. 权限描述符5. 使用EasyKStudio查看用户权限 二、案例实施1. 用户授权综合案例2. 对象的创建者默认就是对象的所属主3. 该表对象的所属主4. 对象属主的权限设置5. 授权普通用户访问对…

StrokesPlus【电脑鼠标键盘手势软件】v0.5.8.0 中文绿色便携版

前言 StrokesPlus.net是一个超方便的手势识别软件,它能帮你用手势来代替鼠标和键盘操作。用起来既简单又灵活,功能还特别强大。 操作起来非常简单,它有好多实用的功能,比如智能识别你写的字、设定手势操作的区域、模拟鼠标的各种…

springBoot统一响应类型3.1版本

前言: 通过实践而发现真理,又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识,又从理性认识而能动地指导革命实践,改造主观世界和客观世界。实践、认识、再实践、再认识,这种形式,循环往…

DDD 架构之领域驱动设计【通俗易懂】

文章目录 1. 前言2. MVC 对比 DDD3. DDD 分层架构4. 完整业务流程 1. 前言 官方回答:DDD是一种应对复杂业务系统的设计方法,通过将软件设计与业务领域紧密结合,帮助开发人员构建清晰、可维护的领域模型。在复杂的业务系统中,它能…

LeetCode 889.根据前序和后序遍历构造二叉树

题目: 给定两个整数数组,preorder 和 postorder ,其中 preorder 是一个具有 无重复 值的二叉树的前序遍历,postorder 是同一棵树的后序遍历,重构并返回二叉树。 如果存在多个答案,您可以返回其中 任何 一…

SSM共享充电宝系统

🍅点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库🍅 本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目希望你能有所收获,少走一些弯路。🍅关注我不迷路🍅 项目视频 SS…

Android 常用命令和工具解析之存储相关

1 基本概念 2 命令解读 2.1 adb shell df df 命令主要用于需要检查文件系统上已使用和可用的磁盘空间的数量。如果没有指定文件名,则显示在当前所有挂载的文件系统上可用的空间。其原理是从proc/mounts 或 /etc/mtab 中检索磁盘信息。 注意:df命令并…

51单片机编程学习笔记——LED原理图

大纲 概览LED电路图Resistor Pack3位数电阻表示法VCC 在《51单片机编程学习笔记——编译代码点亮LED》一文中,我们通过下面这段代码点亮了D1和D2两个LED灯。 sbit LED1P2^0; //将P2.0管脚定义为LED1 sbit LED2P2^1; //将P2.1管脚定义为LED2 …… LED10; LED20;那么…

测试的BUG分析

在了解BUG之前,我们要先了解软件测试的生命周期,因为大多数BUG都是在软件测试的过程中被发现的 软件测试的生命周期 在了解 软件测试的生命周期 之前,我们要先了解 软件的生命周期 ,虽然他们之间只差了两个字,但是差距还是很大的 首先是 软件生命周期 ,这个是站在 软件 的角…

vue3+ts实现动态下拉选项为图标

功能&#xff1a;实现可配置项&#xff0c;下拉选项为图标&#xff0c;如图&#xff1a; 代码如下&#xff1a; <el-select v-model"BuyVolAcc" size"small" style"width: 100%" class"icon-selector"><el-option v-for&qu…

C语言(15)-------------->一维数组

这篇文章介绍的是数组的定义、创建、初始化、使用&#xff0c;在数组中输入内容并输出数组中的内容&#xff0c;并探讨了数组在内存中的存储。里面有些内容建议大家参考下面的一些文章&#xff0c;有助于加深大家对于C语言的理解&#xff1a; C语言&#xff08;2&#xff09;-…