UWP 手绘视频创作工具技术分享系列 - 文字的解析和绘制
本篇作为技术分享系列的第二篇,详细讲一下文字的解析和绘制,这部分功能的研究和最终实现由团队共同完成,目前还在寻找更理想的实现方式。
首先看一下文字绘制在手绘视频中的应用场景
文字是手绘视频中很重要的表现形式,应用场景很广,比如字幕、旁白和一些重要的文字说明提示。和普通视频,如 MV、电影等使用某一种固定字体,如宋体、微软雅黑字体不同的是,在手绘视频中,我们通常会使用一些很有个性化的字体,如毛笔字体、卡通字体和很多手写字体。另一个很大的区别,电影等中的问题,是整体出现的,不存在绘制的过程,所以只需要按照字体显示;而手绘视频中的文字,通常是以手绘的形式展出来的。下面两张图片分别是一个电影截图中的字幕和手绘视频中的一种火柴字体。

接下来介绍文字绘制的几种方案
文字的静态显示过程,是通过读取特定字型的字体文件(ttf)中对应文字的矢量路径数据,以显示在屏幕上对应像素上的。对于不同的字型,文字的形状是不一样的,所以对应文字的路径数据也是不同的。因为是矢量路径数据,所以在放大和缩小时,文字才不会失真。
文字的绘制,实际上是把文字对应的某种路径,按照时间和某种顺序描绘出来。下面介绍的几种市面上常见的方案都是基于这种方式:
1. InkScape 等文字转换路径的软件的绘制方式
Inkscape是开源的矢量图像编辑软件,与Illustrator、Freehand、CorelDraw 等软件很相似,它使用 W3C 标准的 SVG 文件格式。它支持把输入的文字,按照字体大小,轮廓粗细,文字颜色等生成一个 SVG 文件。上一篇我们介绍了 SVG 的绘制方式,所以这里不赘述,我们主要来分析一下 InkScape 生成的 SVG 的数据来源和构成。虽然 InkScape 是比较主流的处理软件,但是它对文字的路径数据处理其实还是比较初级的方式:它会直接获取文字在 ttf 中存储的路径数据,未做特殊处理。而这种路径数据,虽然能准确的勾勒出文字,但是缺点也很明显,首先 ttf 路径是文字的边缘路径,换句话说它是围着文字的周边描绘的,而不是正常的笔迹;其次 ttf 中的路径是完全没有顺序可言的,完全没有正常笔迹构成的文字笔画和笔顺,所以整体来说它是不理想的。
下面是一个文字 ”二“ 和 ”四“ 在 Inkscape 中绘制的原理,它会直接获取如图中蓝色箭头组成的路径,而最终绘制时的顺序也如蓝色箭头一样。因为 ”二“ 字由两个简单的横组成,所以笔顺还算正常;再来看 ”四“ 字,它的路径顺序跟笔顺完全不同,而是简单的把一些封闭图形勾勒出来,所以对于文字来说,这种绘制方式不够理想。

2. VideoScribe 的文字绘制方式
VideoScribe 是一个老牌的英国公司,所做的事情也是手绘视频软件。它在文字绘制方面的表现,和真实的笔迹基本吻合,但是只针对英文字母和数字,并不支持汉字和其他文字。这里说明一下为什么英文和数字会更容易实现,其实也很好理解,英文字母大小写加起来只有 52 个字母,而数字一共只有 0-9 十个数字。所以针对英文字母和数字的绘制,可以预先针对每种字体,准备好这 52+10 个特定的路径,绘制时获取对应的文字和字体来绘制和显示。之所以不做汉字的适配,一方面是 VideoScribe 并没有重点推广中国市场,最主要的还是,汉字远比英文的情况复杂,汉字常用字就超过 3500 个。虽然它们都是由固定的十几个偏旁部首组成的,也有一些途径可以拿到每个汉字的笔画和笔顺,但是想得到某个汉字的每个笔画的相对位置,就没有办法了,所以想按照部首来组成汉字的路径,也就行不通了,这也是我们目前遇到的瓶颈。
3. 我们目前的实现方式
我们的实现方式,是基于文字的边缘路径,通过算法得到边缘中央的路径,也就是笔迹的路径,然后进行一定的重新排序和分组,得到最终绘制的路径进行绘制。

其中中间四个步骤的示例图如下:

4. 我们正在开发的方式
如上面说到的,汉字的绘制,最大的问题在于文字过多,而每种字体的表现形式又有很大差异,通过获取笔顺的方式,很难匹配到多种字体中。我们目前正在尝试的方式是:
① 通过一些合作网站获取的一种正规字型的字体的路径数据,如微软雅黑这种没有笔画附加路径的字体,我们称为基础路径
② 获取常见汉字的笔顺和笔画组成
③ 对于每种字体,准备十几个部首的路径数据,覆盖所有汉字,我们称为部首路径
④ 绘制时针对每个汉字,先取得笔顺中对应的笔画,对应取得基础路径中对应笔顺的起点,在从部首路径中取得对应部首。
⑤ 以笔顺起点为起点,通过指定的缩放率,绘制这个部首。这样对每个部首做处理,就完成了文字的绘制。
这种做法,可以完成大部分字体的文字绘制,缺点时首先要获取到合适的基础路径数据,这点已经完成;其次是如果每种字型的部首起点差异较大,那么效果就不会特别理想。所以我们还在尝试更多的绘制方式,以达到针对每种字体的汉字的绘制。
文字的解析和绘制方式就介绍到这里,目前虽然由解决方式,但是每种方式都有自己的问题,都不够理想,如果大家有更好的方式,欢迎和我交流,谢谢!
UWP 手绘视频创作工具技术分享系列 - 文字的解析和绘制的更多相关文章
- UWP 手绘视频创作工具技术分享系列 - SVG 的解析和绘制
本篇作为技术分享系列的第一篇,详细讲一下 SVG 的解析和绘制,这部分功能的研究和最终实现由团队的 @黄超超 同学负责,感谢提供技术文档和支持. 首先我们来看一下 SVG 的文件结构和组成 SVG ( ...
- UWP 手绘视频创作工具技术分享系列
开篇先来说一下写这篇文章的初衷. 初到来画,通读了来画 UWP App 的代码,发现里面确实有很多比较高深的技术点,同时也是有很多问题的,扩展性,耦合,性能,功能等等.于是我们决定从头重构这个产品,做 ...
- UWP 手绘视频创作工具技术分享系列 - 全新的 UWP 来画视频
从2017年11月开始,我们开始规划和开发全新的来画Pro,在12月23日的短视频峰会上推出了预览版供参会者体验,得到了很高的评价和关注度.吸取反馈建议后,终于在2018年1月11日正式推出了全新版本 ...
- UWP 手绘视频创作工具技术分享系列 - 有 AI 的手绘视频
AI(Artificial Intelligence)正在不断的改变着各个行业的形态和人们的生活方式,图像识别.语音识别.自然语言理解等 AI 技术正在自动驾驶.智能机器人.人脸识别.智能助理等领域中 ...
- UWP 手绘视频创作工具技术分享系列 - Ink & Surface Dial
本篇作为技术分享系列的第四篇,详细讲一下手绘视频中 Surface Pen 和 Surface Dial 的使用场景. 先放一张微软官方商城的图,Surface 的使用中结合了 Surface Pen ...
- UWP 手绘视频创作工具技术分享系列 - 手绘视频导出
手绘视频最终的生成物是视频文件,前面几篇主要讲的是手绘视频的创作部分,今天讲一下手绘视频的导出问题.主要以 UWP 为例,另外会介绍一些 Web 端遇到的问题和解决方法. 如上所述,手绘视频在创作后, ...
- UWP 手绘视频创作工具技术分享系列 - 手绘视频与视频的结合
本篇作为技术分享系列的第三篇,详细讲一下手绘视频中结合视频的处理方式. 随着近几年短视频和直播行业的兴起,视频成为了人们表达情绪和交流的一种重要方式,人们对于视频的创作.编辑和分享有了更多的需求.而视 ...
- UWP 手绘视频创作工具技术分享系列 - 位图的绘制
前面我们针对 SVG 的解析和绘制做了介绍,SVG 是图片的一种形式,而另一种很重要的图片是:位图,包括 png.jpeg.bmp 等格式.位图的基本规则是,组成的基本元素是像素点,由宽度 * 高度个 ...
- UWP 手绘视频创作工具 “来画Pro” 技术分享系列
开篇先来说一下我和来画的故事,以及写这篇文章的初衷. 今年年初时,我还在北京,在 Face++,做着人脸识别技术的 Windows 和 Android 端,做着人工智能终将实现世间所有美好的梦.这时的 ...
随机推荐
- 网页设计——7.css的入门
css的介绍 div+css的设计: 什么是div? 理解示意图: 实例操作: 这里就要用到div+css的布局操作 先写一个html文件,见下图: <html><head>& ...
- Solr6.5.0配置solrcore图文详解
准备环境: solr6.5.0安装完成 jdk1.8 solrhome配置成功 详情:
- NavMesh--导航网格寻路
一.概述: NavMesh是3D游戏世界中用于实现动态物体自动寻路的一种技术,他将游戏场景中复杂的结构组织关系简化为带有一定信息的网格, 进而在这些网格的基础上通过一些列的计算来实现自动寻路. 二.简 ...
- 迭代加深搜索POJ 3134 Power Calculus
题意:输入正整数n(1<=n<=1000),问最少需要几次乘除法可以从x得到x的n次方,计算过程中x的指数要求是正的. 题解:这道题,他的结果是由1经过n次加减得到的,所以最先想到的就是暴 ...
- python爬虫(七)_urllib2:urlerror和httperror
urllib2的异常错误处理 在我们用urlopen或opener.open方法发出一个请求时,如果urlopen或opener.open不能处理这个response,就产生错误. 这里主要说的是UR ...
- "Insufficient RAM for Flash Algorithms"出错原因及解决方式
"Insufficient RAM for Flash Algorithms"错误通常会有一个"cannot load flash programming algorit ...
- iOS 获取导航栏和状态栏的高度
CGRect rect = [[UIApplication sharedApplication] statusBarFrame]; 状态栏的高度: float status height = rec ...
- linux shell 推断文件或目录是否真的存在
#推断文件或目录是否存在 filepath=/data/test.txt folderpath=/data/qtech #推断文件是否存在 if [ -f "$file" ] th ...
- Esri:为Web GIS注入新内涵
纵观近些年IT与空间技术的发展,云计算.大数据.实时信息.LBS.无人机.倾斜摄影等新技术层出不穷:互联网基础设施建设成绩瞩目,宽带成为国家战略性公共基础设施. GIS(地理信息系统)作为空间信息分析 ...
- zephyr初始化流程
1.调用应用层main()函数 kernel/init.c 181行 /** * * @brief Mainline for kernel's background task ...