自动油画这几年热闹归热闹但老实说我一直觉得整个方向陷入了一种“内卷式僵局”大家比拼的是怎么把模型做得更大、数据集刷得更干净、最终图像的指标再提零点几个点却很少有人认真问一句——电脑到底是怎么“决定”下一笔画在哪的大部分方案最后产出的图放大看是漂亮的像素纹理缩小看却经不起推敲笔触堆叠没有逻辑暗部反复覆盖高光位置飘忽不定。你让我说人话这些模型不是在画画是在“猜画”。所以当“Look, Compare and Draw”这套基于差异查询Transformer的自动油画新范式出现在视野里时我第一反应不是“又一篇换皮论文”而是“这个切入点终于对了”。它的核心不是把参考图当成一个静态条件去生成结果而是把“当前画面和参考图到底差在哪”这件事本身做成一种可学习的查询机制让Transformer每一步都明确知道该补哪一笔、不该动哪一笔。这篇博文我想把它从概念到工程拆得再透一点顺带把我复现和调优过程中踩过的坑一并倒出来给想做自动绘画、非真实感渲染NPR、以及一切“迭代式生成”任务的朋友们一份能直接上手的参考。1. 传统自动油画的瓶颈为什么生成结果总差一口气先聊清楚一个前提自动油画和图像风格化是两码事。风格化是把一张照片变成“看起来像油画”的像素图本质是像素域变换而自动油画要求模型输出一组可执行的笔画序列这些笔画叠加在画布上最终构成一幅作品。管线里必须有一个可微的“笔刷渲染器”把笔画参数变成像素然后才能反向传播。这个区别直接决定了很多在风格化里顺手的方法搬到自动油画里就完全使不上劲。1.1 自动油画的本质难点在于“状态依赖”和一次性图像生成不同画家画每一笔之前画布上已经有大量内容。当前画布就是环境状态下一笔的动作会影响之后所有状态。这种马尔可夫决策式的过程意味着模型不能只看最终目标还必须理解“当前在哪一步”。大多数传统方法的问题在于它们把参考图像特征一次性当作条件输入然后让解码器从头生成整幅图或者一堆笔触。结果就是模型对“全局目标”有感觉对“当前局部差距”完全没概念。做个类比你问一个新手画家“画到哪了”他只能把参考图整个描述一遍但一个有经验的画家会直接说“这里暗部还差两个层次那里轮廓线偏右了”。前者是图像检索后者才是绘画决策。自动油画需要的是后一种能力。1.2 已有方法的“盲人摸象”倾向我复现和调研过相当一批这个方向的工作按决策方式大致分三类。第一类是直接回归一批笔画参数网络一次性吐出一整套笔触序列最后的画倒是能看但笔画之间没有递进关系就像打印出来的完全没有人绘画时的主次节奏。第二类是逐步细化式每轮从当前画布提取特征和参考图特征做交叉注意力再生成若干个新笔画。这一步总算有了“迭代”的味道但问题在于交叉注意力的query来自当前画布上的区域特征模型被引导去回答“我看到的这个区域应该长成什么样”而不是“这个区域和参考图差在哪”。第三类则是各种优化式方法比如先模糊对齐再逐步锐化。这类方法的问题是全局能量函数容易让人物边缘发虚笔触也容易被平均化缺乏艺术风格中那种“留白”和“概括”。1.3 问题的实质是缺少“差异建模”把上面这些方法放一起看你会发现一个共同的盲区差异信息没有被显式建模。所谓差异不只是像素差还包括结构差、层次差、笔触疏密差。比如一块已经铺好底色的天空模型不知道该不该停笔于是继续叠笔把本来干净顺滑的云层涂得一坨一坨。究其原因是网络没有收到一个明确的信号说“这片区域已经很接近参考图了别再动”。传统Transformer的交叉注意力机制擅长的是“从参考图里找相似内容”但相似和差异恰恰是互补信息。只看相似会让注意力平均分布到整张参考图上已画好的区域被反复关照没画好的区域却得不到足够的笔画预算。所以在我看这个方向的僵局不是“生成能力不够”而是“决策信息不足”。你给网络一千层Transformer它依然不知道下一步该画哪里因为喂给它的特征图谱里根本没有“差距”这个维度的信息。这也正是“Look, Compare and Draw”这套新范式让我兴奋的原因——它把画家的核心动作“比较”真正变成了模型的一部分。2. “Look, Compare and Draw”如何改写查询机制这套范式从名字上就很直白先看再比然后画。但真正有价值的是它如何把这三个动作翻译成可训练的网络结构。我带着这个问题去梳理设计思路越看越觉得它是冲着传统方法的命门去的。2.1 Look观察参考图但不是“平均地看”第一阶段“看”对应的不是把整张参考图塞进一个编码器就完事而是要建立一个可供后续反复查询的分层表征。油画创作里画家看一张照片时是分层的先看整体构图和大的明暗分布再看中景的形体转折最后才聚焦到局部的颜色和笔触细节。网络设计上对应的就是特征金字塔浅层特征保存局部颜色和笔触走势深层特征编码全局结构与内容语义。这里的细节在于参考图的特征并不是一次性消费掉的它要在每次迭代绘画时被重新“阅读”。所以编码之后每一层特征都要被缓存下来供后续比较阶段反复使用。我看到许多人实现这类方法时只保留最后一层特征这是很大的浪费——浅层特征恰好携带了油画最需要的色彩偏差和边缘锐度信息丢了它们“比较”就会变成一件只有骨架没有血肉的事。2.2 Compare差异查询是整个范式的灵魂第二阶段“比较”是整个范式的核心创新。它的思路可以这样理解模型每一轮迭代时都把当前画布和参考图分别编码然后在多个尺度的特征空间里做差分。这个差分结果不是简单拿去做损失函数而是被进一步编码成一组“差异查询向量”替代传统Transformer解码器里的固定query。我之前看这类方法时总有个疑问直接在特征图上做减法能减出有意义的东西吗答案是直接当然不行因为当前画布特征和参考图特征并不在同一个分布空间做减法会产生大量无意义的噪声。合理的做法是先让画布特征和参考图特征过一个共享的投影层把两者映射到对齐的语义空间再计算差分。投影层的训练本身就让“差异”变得可解释网络会逐渐学到在哪个通道上差异大意味着颜色的偏差大在哪个位置上差异大意味着结构还没对齐。这个环节在工程上常被称作差异编码器输出不只一个全局向量而是一组带空间位置的差异token。比如在8×8的低分辨率特征图上每个位置生成一个token代表“这个局部区域离目标还差多少、差在哪个方向、差到什么程度”。严格说这里的“差”包括三种位置差轮廓没对上、颜色差色相明度偏移、纹理差笔触粗细疏密不对。三种差异在特征通道里天然是纠缠的差异编码器要做的就是把它们分离出来变成可操作的信号。2.3 Draw把差异转化为笔画参数形成闭环第三阶段“画”就是带着差异查询向Transformer解码器发起一轮完整的注意力计算。解码器内部先用自注意力让所有差异token相互交流理解空间上的优先级关系再通过交叉注意力从参考图特征中取出“在差异最大的方向上的目标特征细节”最终回归出一组笔画参数。这一步和传统方法最大的区别在于注意力权重的分布方式。传统方法的注意力权重往往均匀散布在参考图的所有区域而带着差异查询的注意力会把绝大多数权重集中到差距最大的几个位置。说白了模型会主动回答“这里差距第二大先放着那里的轮廓偏了先改那里”。这和我小时候学画时导师说的完全一致——大师画画不是从左上角一笔笔涂到右下角而是永远在比较哪里不对然后优先修正影响最大的地方。更关键的是这一步形成一个闭环执行新笔画后画布被更新下一轮再和参考图比较时差异向量已经发生变化注意力也随之转移。这个动态过程让网络的决策有了“时间上的计划性”而不是静态地在每轮重复同样的操作。3. 模型结构设计与关键模块落地概念说得再好落不了地就是空中楼阁。下面我给出一种经过我实际验证的参考实现结构不贴完整代码但会给出每个模块的设计逻辑和关键参数。这种结构你完全可以当作一个起点根据自己的数据和硬件条件去改。3.1 整体架构三支路加一解码器我把整体结构定为四部分参考图编码器、画布编码器、差异查询生成器、笔触解码器。参考图和画布使用两个权重不同的编码器原因很简单画布上有大量废笔触和半透明颜料层特征分布和干净的照片完全不同共享权重会降低比较质量。两个编码器都采用预训练的图像特征提取主干输出三个层级的特征图尺寸分别是原图的1/4、1/8、1/16。3.2 差异查询生成器的具体设计差异查询生成器接受的输入是三组特征对输出是对应尺度的差异token序列。具体流程分四步对画布特征和参考图特征各做一次1×1卷积投影把通道数统一到d维我用的d是256。在同一尺度上计算差分特征ΔF F_ref_proj - F_canvas_proj。这里的减法是在通道维度上逐元素做乘上一个可学习的逐通道权重向量。差分特征过一个两层MLP加残差连接目的是让网络可以在差分基础上继续提炼高阶差异语义。对每个空间位置生成一个可学习的局部位置编码并叠加输出差异token集D。这一步容易踩的坑是差分特征的值域不稳定早期训练时可能非常大。我给差分特征加了一个层归一化并在进入MLP前用tanh控制一下极值。实验下来这让训练初期的损失曲线平滑不少。3.3 笔触解码器与参数回归头解码器采用四层轻量Transformer模块每层包含一个自注意力和一个交叉注意力。自注意力的输入是差异token序列交叉注意力的query来自差异tokenkey和value来自参考图特征金字塔的对应层级。每个解码层后差异token被更新相当于多轮比较后逐渐聚焦到最值得画的局部。每轮迭代会输出一组笔画参数我设置的是每轮最多画8笔网络同时输出每一笔的置信度分数低于阈值的笔不执行。这样做的好处是模型学会了一个能力叫做“少画”有时候最正确的决策就是不动笔。笔画参数回归头由一个共享的MLP构成输出10个连续值加1个离散类型分布具体如下表所示参数含义范围/取值start_x, start_y笔画起点坐标[0, H], [0, W]end_x, end_y笔画终点坐标[0, H], [0, W]width笔刷宽度[1, 40]像素r, g, b颜料颜色[0, 1]opacity颜料透明度[0.2, 1.0]stroke_type笔刷类型圆头/扁平/干刷坐标回归我一开始直接输出绝对值发现早期极不稳定后来改成相对坐标增量以当前步上一次落笔位置为参照训练速度和稳定性都有明显提升。3.4 可微渲染器的实现选择渲染器的职责是把上面那组参数变成画布上的真实像素。最有效率的方案是预生成一组笔刷掩码贴图对每种笔刷类型预计算不同宽度下的软边掩码。渲染时按笔画角度旋转掩码再用alpha合成方式叠加到画布上。合成公式沿用标准的源上覆盖new_canvas alpha * paint (1 - alpha) * old_canvas。这个公式里的alpha就是透明度参数。干刷类笔刷的掩码边缘带噪声纹理叠加后能产生真实的纸张/画布颗粒感。渲染器全程使用可微张量操作不引入任何非可微采样这一点保证了整条链路端到端可训练。3.5 损失函数不只是算算像素差训练损失我用了四个部分组合。第一是感知重建损失比较当前画布和参考图的VGG特征距离这是主损失。第二是差异拟合损失让差异查询生成器编码出来的量去预测“如果本轮画完画布和参考图的差值会减少多少”这相当于逼着差异token具有预测性。第三是笔画稀疏性正则惩罚过长的笔画和无意义的覆盖。第四是全局色调对齐损失在低分辨率上做整体色调统计匹配避免颜色偏移越来越远。四个损失的权重我调了很久最终比例是1.0、0.3、0.1、0.5。感知重建损失权重最大差异拟合损失适中稀疏性正则只做辅助。全局色调对齐损失在早期训练特别重要它很大程度上避免了画布颜色越画越灰的问题。4. 训练策略、数据准备与实验观察模型结构只是骨架训练过程才是灵魂。这一节讲讲我准备的训练数据和训练策略中的关键决策以及在不同实验组下观察到的现象。4.1 训练数据怎么组织自动油画训练数据有两个来源一是自然照片二是艺术家绘制的真实油画作品。自然照片作为“参考图目标”油画作品作为“风格参照”。训练时我的做法是从一个大规模开放照片库里采样图像缩放到512×512油画作品则用于一个辅助判别损失——强迫生成的笔画序列在低层次统计特征上和真实油画笔触接近。这个方案有个需要注意的地方如果只用照片作为参考图模型容易学会“描图式”的油画也就是所有笔触都贴着照片边缘走结果像彩色铅笔而不像油画。所以在训练中我会混合一部分“粗参考”样本把照片做一次大尺度模糊要求模型用尽量少的笔画去逼近模糊后的色块结构。这个手段非常有效能逼模型学会油画那种块面概括能力。4.2 迭代过程模拟与课程学习每张训练图在训练时都要经过多轮迭代绘画初始画布选择很重要。全空白画布起步会让早期差异信号过强模型手忙脚乱。我一开始用浅灰色底涂层初始化效果不错。后来改成更接近训练集油画底色的浅棕灰模型学习更快最终笔触的暖色倾向也更自然。训练采用课程式策略先固定迭代步数T20训练至损失不再下降后把步数逐步增加到T60。这相当于先让模型学会“大块面铺色”再学会“逐步细化”。如果一开始就训练60步模型会把大量梯度浪费在探索上课程式递进至少让我的训练时间节省了约三分之一。4.3 关键超参数参考给一份可参考的训练配置表超参数取值备注优化器AdamWbeta(0.9, 0.999)基础学习率5e-5前5000步线性预热学习率调度余弦退火对重建损失早期极其有用批量大小16单卡显存充足时可加到32特征维度d256三层共享解码层数4层增加层数收益递减每轮笔画数最多8笔按置信度动态过滤训练迭代60步推理阶段可选更多在损失曲线方面最值得关注的是差异拟合损失。它的下降规律和感知重建损失不同前期快速下降中期基本平缓后期又开始波动。我理解这和注意力聚焦有关前期模型学会把注意力集中到大差异区域差异预测快速变准后期画布已接近参考图剩余的都是细碎差异预测自然变难。4.4 和传统方法的定性对比观察我在相同的自建评测集上对比了直接回归式方法和逐步细化式方法。结论比较明确直接回归式方法生成的油画整体色调很接近但笔触之间没有叠加逻辑层次感和厚度感缺失逐步细化式方法有所改善但容易出现暗部堆颜料的效果。而新范式生成的结果最明显的变化是笔画分布的疏密关系和真实画家接近——大色块区域笔触稀疏五官等细节区域笔触密集存在明确的从粗到细的递进节律。这种定性差异虽然难以用单一指标刻画但人眼扫一眼就能分出来。5. 复现与调优过程中踩过的坑这一节是我最想写、也是我认为对读者最有价值的部分。这些坑在论文里永远不会出现但它们才是决定项目能不能成的关键。5.1 差异查询训练初期的坍缩危机第一次跑通训练流程时我兴奋地发现损失在降但生成结果却很诡异前几轮画的笔触几乎是随机分布的后面几轮才开始修修补补。我调出差异查询向量一看发现它们在前几轮几乎全是零向量——网络学会了偷懒把差异查询全部输出为0等于放弃了比较功能退化成盲画。根因是梯度太小。画布初始是空白的时候差分特征处处都大网络在两三层MLP里做了归一化之后梯度被压缩得很小权重更新缓慢模型发现输出零向量反而能稳定降低损失。解决办法分两步一是给初始画布一个带渐变纹理的底涂层让初始差异不过于极端二是在差异查询生成器里加一个残差分支保证底层特征即使被压缩也有梯度传回。5.2 笔触反复覆盖的“橡皮擦效应”训练中期出现了一个很头疼的现象随着迭代次数增加后画的笔触大量覆盖前面的笔触特别是大色块区域颜料层层叠叠整个画面变脏。我定位到原因感知重建损失只关心最终像素接近参考图它不会惩罚“中间过程里存在不必要的反复涂抹”。模型发现与其仔细规划一笔画到位不如画一笔、觉得不对、再叠一笔反正只要最后像素对了就行。这个问题的修复不能靠调权重而是要在损失上增加“过程一致性”约束。我加了一个动态采样惩罚对每个画布区域的颜料叠加次数做统计超过阈值的区域在损失计算中上调权重逼模型尽早把颜色和位置画准而不是反复覆盖。5.3 颜色输出数值不稳定大约在第三版模型上我注意到生成的油画里频繁出现纯黑和纯白的颜料块。排查后发现是回归头输出层的问题用sigmoid激活颜色值当网络输出强置信结果时sigmoid进入饱和区梯度接近零参数卡在极值处颜色就一直保持纯黑/纯白。把颜色激活函数改成tanh再乘一个0.5的缩放因子问题立刻缓解。这个小改动让整体画面观感提升非常明显。5.4 评估指标的选择陷阱如果你想用这套范式做应用或发论文评估指标是一条大坑。叠加上常见的感知距离指标之前务必同时统计笔画层面的指标。我吃过教训某轮实验感知距离指标大幅下降看起来“接近参考图”了但人工审视却发现画面结构松散笔触七零八落。原因是感知损失主要衡量的是频率特征而油画的美感更多在于笔画形态、疏密节奏和覆盖层次。后来我加入三个统计量作为辅助指标笔画长度分布、笔画覆盖重叠率、局部颜色方差。这些指标不需要人工就能反映笔触质量和主观评价的相关性远比单看感知距离可靠。6. 这套范式的适用边界与后续扩展最后聊聊这套“差异查询”思想的价值边界。我个人的判断是它的适用面远不止自动油画凡是涉及“迭代式生成”和“过程性决策”的任务都可能从中获得启发。6.1 可以迁移的任务方向第一个值得尝试的方向是动画上色与细化。动画制作中上色师的工作本质上就是反复比较线稿和参考色板这与差异查询的逻辑高度一致。第二个方向是交互式绘画辅助用户画几笔草图后系统比较草图和参考图自动补完缺失部分。这个场景里差异查询的价值尤其明显因为系统必须知道“用户已经画了什么还缺什么”。第三个方向是漫画分镜的自动草图清洗通过比较草稿线和目标线稿结构来逐步收缩笔画。6.2 现阶段没有解决的短板说几个目前方案还没跨过去的坎。一是笔刷种类依然有限像刮刀厚涂、湿画晕染这类复杂笔法很难用参数化渲染器描述。二是差异查询建模没有显式的“时间上下文”也就是说模型不记得自己前几步打算怎么画偶尔会出现来回拉扯的振荡。三是大画布场景下特征金字塔多尺度差分的内存开销比较高如果要画4K画布得先解决效率问题。6.3 我接下来打算怎么改进基于上面的短板我的下一步计划是三件事。第一是给差异查询加一个可迭代更新的“记忆向量”让模型能感知到自身绘画历史从而避免反复覆盖同一个区域。第二是把笔刷的参数化渲染换成一个小型的可微笔刷网络让模型自己学出更丰富的笔触形态。第三是尝试用对比学习预训练差异编码器让它在进入端到端训练之前就已经具备“判断差多少”的能力。这步要是走通“Look, Compare and Draw”的工程落地门槛还能再低一截。从我自己的复现体验来说这套范式给我最大的启发并不是“Transformer还能画油画”而是“比较”这件事本身应该被模块化、可学习化。传统生成模型把条件信息喂给网络就不管了这是对信息利用的一种浪费。把“差距”做成查询信号本质上是在引导网络持续关注自己最不擅长的地方——这套逻辑放到很多生成任务里恐怕都值得再印证一次。 SEO 优化官网定制响应式建站教育培训建站