[论文速览] DualVector@ Unsupervised Vector Font Synthesis with Dual-Part Representation

Pre

title: DualVector: Unsupervised Vector Font Synthesis with Dual-Part Representation
accepted: CVPR2023
paper: https://arxiv.org/abs/2305.10462
code: https://github.com/thuliu-yt16/dualvector

关键词: Unsupervison, Vector Font Synthesis, TrueType Font Conversion, English Letters, Implicit Neural Representation, Unsigned Distance Field
阅读理由: 看作者+图1,[Joint Implicit Neural Representation for High-fidelity and Compact Vector Fonts]是这篇的后续工作?好像也不对?

Idea

双分支,使用SDF(UDF)生成矢量字形的同时借助另一分支的像素图片结果精炼矢量字形

Motivation

当今的字体生成方法大多把字形作为像素图片处理,放大有伪影而且矢量化会有质量损失。而已有的矢量字体合成方法无法准确描述形状或训练时需要矢量监督

Background

图1 左边是DualVector合成的,右边是平滑插值结果

矢量字体生成典型做法是将矢量形状视为绘制的序列,然后采用序列建模技术去解决,但是有俩缺点:

  1. 建模指令序列比图片难得多,指令与形状是多对一关系,可能学不明白,而且对合法字形形状难以构建有效的流形
  2. 需要有groundtruth的绘制序列来提供监督信息

Glyph Image Generation 批评基于像素的方法
Image Rasterization and Vectorization DiffVG
Vector Font Generation SVG-VAE, DeepSVG, Im2Vec...

Method(Model)

Overview

图2 DualVector: (a)矢量分支将隐编码z映射到几个贝塞尔路径,进一步汇聚为全局的字形 (b)图片分支生成像素图 (c)轮廓精炼步骤对 dual-parts 应用布尔操作得到轮廓,然后通过推理时的图片引导去优化 两个分支都是用字形图片进行训练

提出矢量字形的 dual part 表示,每个字形建模为固定数量的 dual part 的并集,每个dual part通过 “正”“负” 几何图元 (geometric primitives) 的差集表示,而几何图元有许多选择,为了更强的表示能力选择贝塞尔曲线。最直接是用可微渲染技术来优化贝塞尔曲线的参数,但很容易陷入局部最优,因为仅有形状相交处(交集?)梯度有意义。

受到2D、3D形状的隐式场的启发,监督从贝塞尔曲线的分析表达式导出的占用场(occupancy value),并采用基于无符号距离场(unsigned distance field, UDF)的初始化策略,在整个像素空间上提供密集的梯度.

为了局部细节保真度,训练了字形图像生成模型,并设计了轮廓细化步骤将矢量形状的轮廓与可微渲染的图像轮廓对齐

Dual-Part Representation

记号太麻烦,只记录大体思路。

每个字形g由N条闭合贝塞尔路径P表示,每个路径P由M条端到端相连的二次贝塞尔曲线定义,闭合路径P的占用场(occupancy field)定义如下:

\[\mathcal{O}_{P_i}(x) = \left\{\begin{aligned} 1, x\in P_i \\ 0, x \notin P_i \\ \end{aligned}\right. \tag{2} \]

将g的坐标归一化到[-1, 1]的范围,也是任何点x的范围,通过最大化操作可以确定x是否在被表示的字形中,也就是g的占用场:

\[{\cal O}(x) = \max_{i}{\cal O}_{P_{i}}(x) = \left\{\begin{aligned} 1, x\in \cup_i P_i \\ 0, x \notin \cup_i P_i \\ \end{aligned}\right. \tag{3} \]

这种表示不适用于中空的形状,因此作者为每个路径\(P_i\)加了个负路径\(Q_i\),二者合称 "dual part" ,这样\(g\)通过\(\cup_i(P_i - Q_i)\)来表示,占用场可以定义为:

\[{\cal O}(x) = \max_{i}[\min{\cal O}_{P_i}(x), 1-{\cal O}_{Q_i}(x)] = \left\{\begin{aligned} 1, x\in g \\ 0, x \notin g \\ \end{aligned}\right. \tag{4} \]

\({\cal O}\) 对路径参数不可微,为此改用g的SDF推导来的近似占用场\(\hat{\cal O}\),由于任意点p到贝塞尔曲线B的距离\(d(p;B)\)可以计算得到,路径的SDF因此可微:

\[s_{P_{i}}(x)=[2{\mathcal O}_{P_{i}}(x)-1]\operatorname*{min}_{j}d(x;B_{i,j}) \tag{5} \]

根据已有的矢量图形光栅化技术,采用抛物线核\(\alpha\)的解析像素预滤波(analytical pixel pre-filtering)方法逼近\({\cal O}\)

\[\hat{\cal O}_{P_{i}}(x) = \alpha(s_{P_{i}}(x)) \\ \hat{{\cal O}} = \max_i[\min(\hat{{\cal O}}_{P_{i}},1-\hat{{\cal O}}_{Q_{i}})] \tag{6} \]

Vector Branch

路径解码器\(\mathcal{D}_P\)直接根据隐变量z预测正负路径对的控制点

Image Branch

使用CNN解码器\(\mathcal{D}_I\)生成灰度图,用以引导精炼矢量形状轮廓

Contour Refinement

先使用Paper.js将dual part转换为字形轮廓 \(\partial \mathcal{O}\),这样就能够在SVG路径上进行任意的布尔操作,\(\partial \mathcal{O}\)由K个闭合贝塞尔路径组成:

\[\partial{\cal O}=\{C_{1},C_{2},...,C_{K}\} \tag{9} \]

也就是说对 \(\mathcal{O}\) 求导就是其轮廓 \(\partial \mathcal{O}\)

精炼过程有几个策略:
Subdivision 将长度超过画布10%的贝塞尔曲线从中点割开,可以改进表示的质量。

Simplification 以直代曲,或聚合那些过短的线条与曲线的端点,有一定标准

Pruning 去掉一些面积小于阈值的闭合路径,否则会导致精炼过程产生冗余曲线,并最终收敛为点

Optimization Objectives

Font reconstruction. 字形g的像素图片\(\mathcal{I}_g\)先通过编码器\(\mathcal{E}\)得到隐变量z,然后z输入双分支获得dual-parts和重建的像素图片\(\mathcal{I}\),损失如下:

\[\mathcal{L}=\lambda_{P}\mathcal{L}_{P}+\lambda_{I}\mathcal{L}_{I} \tag{11} \]

其中:

\[\mathcal{L}_{P} = \mathbb{E}_{x\sim[-1,1]^{2}}\bigl[\|\hat{\mathcal{O}}(x) - \mathcal{I}_{g}(x)\|_{1}\bigr] \\ \mathcal{L}_{I}=||\mathcal{I}-\mathcal{I}_{g}||_{2} + \mathrm{LPIPS}(\mathcal{I},\mathcal{I}_{g}) \tag{12} \]

按这样说\(z\)需要\(\mathcal{I}_g\)来获取,也需要\(\mathcal{I}_g\)来计算损失,那这哪里无监督了?难道不使用矢量绘制命令去监督就等于无监督?不如说

Font generation. 字体生成任务输入是多个风格参考图片\(R_i\)和相应的字符标签T,参考图片的数量\(N_R\)。风格参考先过编码器,再过自注意力层得到\(\mu, \sigma\),汇聚特征得到风格隐编码\(z_{style} = \mu+\epsilon\sigma,\epsilon\sim\mathcal{N}(0,1)\)。然后T通过嵌入层后跟\(z_{style}\)一起得到目标字形的隐编码\(z_T\),将其输入解码器可生成字形。

同时为了方便训练使用重建任务的编码器\(\mathcal{E}\)对真值输出\(g_T\)算损失:

\[{\mathcal{L}}_{l a t e n t}=||z_T-{\mathcal{E}}(g_{T})||_{2} \tag{14} \]

为了可以采样字体,引入KL损失:

\[\mathcal{L}_{k l}=\mathrm{KL}(\mathcal{N}(\mu,\sigma^{2})||\mathcal{N}(0,1)) \tag{15} \]

Refinement 重建和生成任务有相同的轮廓精炼过程,给定 \(\partial \mathcal{O},\; \mathcal{I}\),精炼通过推理时优化生成SVG格式的轮廓,使用DiffVG(记为DR)渲染轮廓。损失如下:

\[\mathcal{L}_{r e f i n e}=\mathcal{L}_{r a s}+\lambda_{r e g}\mathcal{L}_{r e g} \tag{16} \]

其中 photometric loss 约束光栅化图片和图片分支的输出

\[\mathcal{L}_{r a s}=||\mathrm{DR}(\partial\mathcal{O})\mathcal{I}||_{1} \tag{17} \]

正则化项限制 \(\mathcal{O}\) 的整体长度

\[\mathcal{L}_{r e g}=\sum_{i=1}^{K}\mathrm{len}(C_{i}) \tag{18} \]

Unsigned Distance Field Warm-up

矢量分支虽然端到端可训练,但梯度只出现在边界附近。为了克服梯度消失问题,基于矢量部分的 无符号距离场(UDF) 增加了额外损失以预热(warm up)系统训练。

对两个闭合曲线\(c_1,\;c_2\),通常无法获得任意布尔操作结果准确的SDF,曲线的布尔操作就是对各自SDF进行逐点操作。作为两个SDF的并集近似,有:

公式19

作者说 \(min(\cdot)\) 操作能得到形状外部准确的SDF,但内部SDF是不准的,而 \(max(\cdot)\) 则反过来,因此很难得到整个字形的准确SDF \(s_{\mathcal{O}}\)

就公式19来说,x应该是一个点,若它不属于\(c_1,\;c_2\)并集,说明x在这两个闭合曲线外部,那该点处对于两曲线整体的SDF值按定义就是到该整体距离最小值,那么直接取它对两个曲线SDF值里更小的那个即可。

反过来没想明白。x如果属于两曲线并集,说明它至少在一个闭合曲线内部,此时应该要取两个SDF中更大的那个(较大的负数)才能反映该点处的准确SDF。但作者给出了\(\le \min(\cdot)\),和他论文里说取最大能准确表示内部SDF有冲突呀

作者说实际上只需要一个粗糙的初始值给dual parts,避免优化陷入局部最小值即可,发现用近似的无符号距离场不错。定义UDF\(u\)

\[u(x) = \max(0, s(x)) \tag{20} \]

近似UDF \(\hat{u}_g\) 定义为:

\[\hat{u}_g=\min_i[\max(u_{P_i},u_{Q_i})] \tag{21} \]

其中

\[u_{P_i}(x)=\max(s_{P_{i}}(x),0) u_{Q_i}(x)=\max(-s_{Q_{i}}(x),0) \tag{22} \]

对于字体重建任务应用下列损失去 warm up:

\[\mathcal{L}=\lambda_{P}\mathcal{L}_{P}+\lambda_{I}\mathcal{L}_{I}+\lambda_{u}\mathcal{L}_{u} \\ \mathcal{L}_{u} = \mathbb{E}_{x\sim\left[-1,1\right]^{2}}\left[\|\hat{u}_{g}(x) - u_{g}(x)\|_1\right] \tag{23} \]

其中真值UDF\(u_g\)根据像素图片g获得

Experiment

Settings

Dataset

使用SVG-VAE的SVG-Fonts数据集,分辨率128 × 128

Font Reconstruction

图3 字体重建质量的比较 第二第三行的 \mathcal{I} \mathcal{O} 分别是图2里两个分支的输出

表1 定量比较。灰度标准化到[0,1]

Font Generation

公平起见用 "ABab"四个字符作为风格参考

图4 图像生成结果。输入的风格参考以红框标出。典型的缺陷用蓝虚线框标出。左侧给出了一些细节的放大

表2 定量比较

表3 不同方法用于每个字形的平均指令数量 MLQC分别表示移动,直线,二次贝塞尔曲线和三次贝塞尔曲线

Ablation Studies

图5 M轮廓的比较 (a)将dual parts的并集换为所有路径的并集(也就是去掉dual part?) (b)不使用UDF warm-up (c)去掉精炼策略

表4 重建精度。矢量字形渲染为512x512以计算L1

a很难重建凹面区域,b生成了冗余的曲线,c的边缘是z字形的(zigzags)

表5 不同重建设置和指标。图片分辨率512

图5里NM来自 Dual-Part Representation 一节:

每个字形g由N条闭合贝塞尔路径P表示,每个路径P由M条端到端相连的二次贝塞尔曲线定义

图5没加粗?说是M=4最好,N从6到8不明显,所以考虑到时间开销用了\((N,M) = (6,4)\)

Font Sampling and Interpolation

图6 根据采样的风格生成的新字体

由于风格隐编码\(z_{style}\)根据变分的KL散度训练,因此可以从正态分布中采样,并用于新字体的生成。同时dual part的表示还允许平滑插值,如图1

Conclusion

限制:

  1. 轮廓精炼步骤需要推理时进行梯度下降,要求大量的时间开销
  2. DualVector只能在固定大小的画布上生成字形,没考虑过字距调整(kerning),因此字符间距不太自然,不过通过后处理或数据驱动的方式能够解决

方法能够在没有矢量监督(但是有像素图\(\mathcal{I}_g\)监督,归根到底不还是有监督?)的情况下生成矢量字体,而且能直接转换为常见的数字字体格式

将来更合理的初始化和监督能将该表示方式用于更复杂的字体上(中文字体)

Critique

记号多而且不够清晰,甚至有的地方乱标,看着很累
公式19为何x在并集内部不是用\(\max(\cdot)\)
新概念Unsupervise
怎么不比较自己CVPR那篇"Joint Implicit Neural Representation for High-fidelity and Compact Vector Fonts"?
但不可否认 dual part 这种正负矢量图形对通过相减来组合出新矢量图形的方式不错

posted @ 2024-06-02 17:34  NoNoe  阅读(95)  评论(0编辑  收藏  举报