首页 > 其他分享 >[论文阅读] Disentangling Writer and Character Styles for Handwriting Generation

[论文阅读] Disentangling Writer and Character Styles for Handwriting Generation

时间:2023-10-25 18:46:01浏览次数:36  
标签:Disentangling Styles 书写 Writer 汉字 生成 风格 SDT mathcal

Pre

title: Disentangling Writer and Character Styles for Handwriting Generation
accepted: CVPR2023
paper: https://arxiv.org/abs/2303.14736
code: https://github.com/dailenson/sdt
ref: https://mp.weixin.qq.com/s/aqHfC0hfimK0QhEUzQRZgw

关键词: handwriting, style-disentangled, 对比学习, 在线字体, 序列生成
阅读理由: CVPR!

Idea

对不同字体、同一字体的不同字都应用对比损失,以序列的形式预测出字的每个位置点(在线字体),也提供了(大概)将其渲染回图片的方法

Motivation&Solution

  1. 主流方法大多默认风格对于同一书写者是统一的,忽略了同一个人写不同的字也会有不同的风格差异 -> 使用对比学习解耦两种风格
  2. 风格参考图片少的情况下难以学会风格 -> 解耦两个风格,靠跨注意力融合

Background

图1 两个在线手写汉字,每种颜色代表一个笔画,递增的数字表示书写顺序

不同于英文字母,汉字数量是极其庞大的,想要创造一套自己的专属字体代价十分高昂。例如,最新发布的国标GB18030-2022中文字符集包含87887个汉字。

如图1,在线汉字含有丰富的信息(书写顺序),本文想自动生成这种在线手写体,不仅要符合文本内容,还希望提取笔迹中蕴含的书写风格(例如字符的大小、倾斜程度、横宽比、笔画的长短和曲率等)

图2 每行都是不同人写的,尽管同一个人的字整体相似(倾斜度),但字之间还是有差异

  1. 相同书写者的笔迹存在着一种整体上的风格共性,各个字符呈现出相似的倾斜程度和宽高比,且不同书写者的风格共性各不相同。由于这种特性可以用于区分出不同的书写者,研究者们称其为书写者风格。
  2. 除了整体上的风格共性,来自同一书写者的不同字符间存在着细节上的风格不一致。例如,对于 “黑” 和 “杰” 两个字符,二者在字符结构上具有相同的四点水部首,但该部首在不同的字符中存在微弱的书写差异,体现在笔画书写的长短、位置和曲率上。研究者们将这种字形上的细微的风格模式称为字形风格。

Method(Model)

Overview

图4 Overview 使用 WriterNCE L_wri 和 GlyphNCE L_gly 来指导编码器两个头去学习风格 L_pre 和 L_cls 分别表示 pen moving 预测损失和 pen state 分类损失

受启发于上述观察,SDT 旨在从个人笔迹中解耦出书写者和字形风格,期望提升对用户笔迹的风格模仿能力。作者提出了style-disentangled Transformer (SDT),它有一个双头风格编码器,以及内容编码器和 transformer 解码器

图3 在“园”里切两块作为正样本,负样本从另一个字中拿,patch的选取符合均匀分布

writer-wise: 将同一个人的字作为正样本,不同人的字作为负样本,WriterNCE
character-wise: 取一个字的不同部分作为正样本,裁剪不同字的作为负样本,如图3,GlyphNCE

而内容编码器实际上使用了Resnet18,它输出的特征图patch喂入Transformer编码器来抽取文本内容表达,而且其中的 CNN Encoder 跟风格编码器那个架构一模一样

之后SDT 利用 transformer 的注意力机制 (multi-head attention) 对风格特征和内容编码器提取到的内容特征q进行动态融合,自回归地合成在线手写汉字。

最终总的损失函数:

\[\mathcal{L}=\mathcal{L}_{w r i}+\mathcal{L}_{g l y}+\mathcal{L}_{p r e}+\lambda\mathcal{L}_{c l s}, \tag{1} \]

Dual-head Style Encoder

Writer-wise Contrastive Learning

\[\mathcal{L}_{w r i}=\frac{-1}{N}\sum_{j\in M}\frac{1}{|P(j)|}\sum_{p\in P(j)}\log\frac{\exp\left(\mathrm{sim}(e_{j},e_{p})/\tau\right)}{\sum_{a\in A(j)}\exp\left(\mathrm{sim}\left(e_{j},e_{a}\right)/\tau\right)}, \tag{2} \]

上式中j是一个batch中的某个样本下标,A(j)表示batch中除j之外的其他样本下标,e表示writer-wise的风格特征,M是batch size。\(P(j)=\{p\in A(j):w_{p}=w_{j}\}\),表示A(j)里跟j属于同一个书写者的样本下标。

\(\mathrm{sim}\left(e_{j},\,e_{p}\right) = f_{1}\left(e_{j}\right)^{\top}\,\mathcal{f}_{1}\left(e_{p}\right),\) \(\tau\)是温度系数,\(f(\cdot)\)是一个多层感知机,将特征投影到 \(\mathcal{L}_{w r i}\) 用的L2空间

Character-wise Contrastive Learning
不同字符的字节常有不同,这里最大化相同字符不同视角间的互信息

\[\mathcal{L}_{g l y}=-\log\frac{\exp\left(sim\left(o,o^{+}\right)/\tau\right)}{\exp\left(sim(o,o^{+})/\tau\right)+\sum_{j=1}^{B-1}\exp\left(sim(o,o_{j}^{-})/\tau\right)}. \tag{3} \]

其中B是取的不同字符数,o都是从字符的character-wise风格特征g中采样的,其他细节略(跟公式2的差不多而且感觉不会马上用到)
这里把正样本对也塞分母去了,不过 \(\min\frac{pos}{neg + pos} \equiv \max(\frac{neg}{pos} + 1)\),应该是没差的。事实上代码跟github一份SupContrast几乎一样,这样可能是为了方便代码的实现

Transformer Decoder for Handwriting

图5 解码器对风格信息的融合。每一步t,查询向量由内容特征q跟前面预测的t-1个点编码得到,然后融合EG两种风格特征,得到当前步的输出

这里EG充当key/value向量,Q充当query,内容上下文 \([q, y_1, ..., y_t−1],\) 用于得到查询向量 \(Q_t\),这里用groundtruth的 \(y_i\) 是为了加速训练时的收敛。推理的时候改用 \([q, \hat{y}_1, ..., \hat{y}_t−1],\) 做自回归。输出 \(O_t\) 用于生成 pen moving 和 pen state,(具体的就不细看了,总之这两个再拿去算 \(\mathcal{L}_{p r e},\; \mathcal{L}_{c l s}\))

Experiment

Training Detail

风格参考数量K=15(训练时数量翻倍,推测为两组风格参考,组内特征取平均,两组略有差异(字不一样)互为正样本对,而推理时不用算loss也就不用分两组),图片尺寸都是64x64(好小),(一些Transformer的实现细节),先预训练内容编码器做汉字分类,共 138k iterations (batch size 256),然后整个模型再训练 148k iterations (batch size 128)

设备为一块RTX3090,优化器Adam,学习率0.0002,gradient clipping=5.0,sampling ratio α 通过搜索得知取0.25最佳,\(\lambda\) 取2

跟 《Deep imitator: Handwriting calligraphy imitation via deep attention networks》 一样,用生成的在线汉字坐标点渲染为离线风格

Dataset

train: 经典手写数据集 CASIA-OLHWDB (1.0-1.2),1020个书写者,3.7m个在线汉字(一人写3627字?)
test: ICDAR-2013 competition database,60个书写者,3755个常用汉字

使用 Ramer-Douglas-Peucker (RDP)算法去除汉字里冗余的点,最终平均序列长度为50。

内容字采用 Scfont (Scfont: Structure-guided chinese font generation via deep
stacked networks) 的平均汉字字体。

Metrics

使用 Dynamic Time Warping (DTW) 去计算生成的和真实汉字之间的距离,用 Content Score (Deep imitator: Handwriting calligraphy imitation via deep attention networks.) 测量生成汉字的结构正确性,用 Style Score (Write like you: Synthesizing your cursive online chinese handwriting via metric-based meta learning) 量化风格相似度。也做了用户满意度调查。

Chinese handwriting generation

这里比较的似乎都是本文这种序列式的模型,Drawing, FontRNN, DeepImitator 和 WriteLikeYou。其中Drawing 和 FontRNN 有修改

表1 和SOTA模型对比

Quantitative comparison. SDT 在中文、日文、印度文和英文数据集上都取得了最优异的性能,尤其是在 Style Score 上,相比之前的 SOTA 方法,SDT 取得了较大突破。

图6 在在线汉字手写生成上跟SOTA的比较。红蓝分别框出了风格和结构的问题,WriteLi.就是WriteLikeYou-v2,绿框标出生成的汉字跟目标之间的细节比较

Quantitative comparison. 在中文生成方面,相比以前的方法,SDT 生成的手写字符既能避免字符的崩坏又能很好的临摹用户的书写风格。得益于字形风格学习,SDT 在字符的笔画细节生成方面也能做的很好。

Analysis

表2 消融研究,使用FID衡量

作者还尝试了两种风格特征喂入解码器的先后顺序,结论是在 Style Score 上没有明显差异 (93.72% vs. 94.50%).

图7 两种风格表达的频谱分析。这里有7个书写者的频率幅值可视化,每个频谱图都是同一个人100个字平均来的,越亮的地方幅值越大,像素越远离中心其频率越高。可以看到 writer-wise 风格表征捕捉了更低频的信息,另一个更高频

根据 《The fast fourier transform and its applications》,低频成分包含目标的整体轮廓,高频成分则更加关注物体的细节。这一发现进一步验证和解释了解耦书写风格的有效性。

图8 DTW矩阵的热力图

图8横轴纵轴都是书写者index,对图中一个点,随机取属于两个书写者的风格输入去分别生成两组字(200个),生成结果之间再算平均DTW。黑色对角线表示即便用同一个书写者的不同字(横纵轴都是同一个人的风格,但用于生成的风格参考 \(X_s\) 不同)去生成也能维持高相似度,表明本文模型能够根据多样风格输入生成一致的结果。

Applications to Other Languages

表3 SDT在其他语言上的的定量评估

图9 不同语言上手写生成的比较,WriteLi.表示WriteLikeYou-v2.

日语数据集:TUAT HANDS 《Collection and analysis of on-line handwritten japanese character patterns》
印度语数据集Tamil,作者说印度语手写更难,轨迹点比汉字多,
英语数据集:CASIA OLHWDB(1.0-1.2) 和 ICDAR-2013 competition database的字母部分,任务整体简单,但里面一些字母区分度低,如Oo,导致SDT的 content score 也比较低。

Conclusion

SDT主要为 handwriting generation 设计,但也能用于 font generation 等其他生成任务
附录中也有提到他这个模型生成是轨迹点的序列,属于在线汉字,通过连起来再用 ornamentation network 去渲染就能得到字形图片(离线汉字)

Critique

写得很清晰,实验附录充足得有些太多了,看着效果不错,但生成的分辨率有些低。

附录A.4测试提出的 offline-to-offline handwriting generation framework 的有效性,但这玩意前面也没讲过啊?

Unknown

content encoder为何要预训练,不做的话会有多大影响?

标签:Disentangling,Styles,书写,Writer,汉字,生成,风格,SDT,mathcal
From: https://www.cnblogs.com/Stareven233/p/17536192.html

相关文章

  • Java基础 字符输出流之一——FileWriter
     FileWriter书写细节:1.创建字符输出流对象细节①:参数是字符串表示的路径或者File对象都可以细节②:如果文件不存在会创建一个新的文件,但要保证父级路径是存在的细节③:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关 2.写数据细节:如果write方法的参......
  • js_doucment.styleSheets获取StyleSheetList接口
    通过document.styleSheets可以获取到一个StyleSheetList接口constaStyleList=document.styleSheetsconsole.log(aStyleList.constructor.name)//StyleSheetListconsole.log(Object.prototype.toString.call(aStyleList))//[objectStyleSheetList]console.log(Arra......
  • IO流,字符输出流PrintWriter
    PrintWriter 具有自动刷新(用这个就不用写flush方法),特点是按行输出字符串 并且可以通过printfln()方法实现自动换行 结果: ......
  • 利用hutool中的 ExcelWriter 编写导出信息
    我们现在很多网站都有导出信息这个功能,而今天我介绍的是hutool中的ExcelWriter,通过这个在后端编写代码,将信息导出在excel,然后通过浏览器进行保存下载。后端代码:/***导出接口*/@GetMapping("/export")publicvoidexport(HttpServletResponseresponse......
  • 使用 StringWriter 和 printWriter 打印异常原因
    StringWriter和PrintWriter都是Java中用于输出文本的类,它们的主要区别在于输出的目标不同。StringWriter是一个字符流,它将输出的内容保存在一个字符串缓冲区中,可以通过toString()方法获取缓冲区中的字符串。因此,StringWriter通常用于将输出内容保存到字符串中,而不是直接输出到控......
  • 【中秋国庆不断更】OpenHarmony多态样式stateStyles使用场景
    @Styles和@Extend仅仅应用于静态页面的样式复用,stateStyles可以依据组件的内部状态的不同,快速设置不同样式。这就是我们本章要介绍的内容stateStyles(又称为:多态样式)。概述stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以下四种状态:​......
  • 【中秋国庆不断更】OpenHarmony多态样式stateStyles使用场景
    @Styles和@Extend仅仅应用于静态页面的样式复用,stateStyles可以依据组件的内部状态的不同,快速设置不同样式。这就是我们本章要介绍的内容stateStyles(又称为:多态样式)。概述stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以下四种状态:......
  • 【中秋国庆不断更】OpenHarmony多态样式stateStyles使用场景
    @Styles和@Extend仅仅应用于静态页面的样式复用,stateStyles可以依据组件的内部状态的不同,快速设置不同样式。这就是我们本章要介绍的内容stateStyles(又称为:多态样式)。概述stateStyles是属性方法,可以根据UI内部状态来设置样式,类似于css伪类,但语法不同。ArkUI提供以下四种状态:​......
  • OpenHarmony定义组件重用样式:@Styles装饰器
    OpenHarmony定义组件重用样式:@Styles装饰器如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。@Styles装饰器可以将多条样式设置提炼成一个方法......
  • OpenHarmony定义组件重用样式:@Styles装饰器
     如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,虽然可以复制粘贴,但为了代码简洁性和后续方便维护,我们推出了可以提炼公共样式进行复用的装饰器@Styles。@Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。通过@Styl......