如何使用SyhthText合成自己的数据


发布于

|

分类

,

OCR标注贵,所以我们需要「自己造数据」,即数据合成。数据合成的原料是「字体文件、没有字的背景图、文本语料」,过程是「用某种字体,将某些文字渲染在背景图上」。合成的目标是「合成数据和目标数据看起来要尽量接近,比较像」。

在「场景文本」方面,SynText是一个传说中做得还不错的文本合成工具。那么就来试一试,合成一点自己的数据。

先说结论:生成出来的东西不能用。建议放弃。

材料准备

下载代码

不多说,直接git clone就完事儿了

main/master分支说的是针对Python2的,其实我们可以使用 2to3 这个Python自带的工具,将版本「升级」为Python3

下载原材料-Part1

按照SynthText的说法,他们会根据深度图,在图片上「较为平坦」的地方渲染上文字。所以就需要下载一下他们处理好的图片。——自己做也是可以的啦,只是说还需要安装Matlab这个大魔头,比较麻烦。所以还是用他们处理好的比较省事儿。8000张背景图也算够用。

按照说明,需要下载 imnames.cp、bg_img.tar.gz、depth.h5和seg.h5这四个东西。

下载原材料-Part2

在gen.py里面,我们还发现了这个文件: http://www.robots.ox.ac.uk/~ankush/renderer_data.tar.gz 也需要下载下来,并解压缩。我们称解压缩后的路径为renderer_data

加入自己的东西

上面说了,我们希望绕过的是「matlab的部分」。所以对照着最开始的「背景图、字体、语料」的清单——我们还需要准备字体和语料

准备字体

首先,筛出来一些字体。可以参考这篇博客

为啥要筛字体?如果你做过相关工作你就会知道,字体文件真的是千奇百怪,有些字体真的不适合用来做渲染,例如那些稀奇古怪的Icon字体(例如A是大洋洲,B是北美洲,C是南美洲;再或者,《塞尔达传说:荒野之息》里面的西卡文字,其实也是字体)、大小写不分的字体、过于花哨的字体(例如,A头上开朵花、著名的「小人举牌」字体)。

然后,将它们的路径保存成一个txt文件,替换renderer_data/fonts里面的字体列表文件。

准备语料

这个就比较随意了……如果嫌麻烦的话,可以直接替换 renderer_data/newsgroup/newsgroup.txt 。不想替换的话,在代码里面改也成,下文会说到。

改代码

适配Python3

Python2都死了好几年了……就别在用了,直接上Python3吧。官方说master分支里面的代码是只适配Python2的,我们自己动手让它适配Python3,也不难。

首先,Python有2to3这个工具,可以查一下用法。我这里直接在每个文件夹里面使用 2to3 -w *.py 简单暴力。

然后,这份代码里面多处用到了pickle这个序列化的东西(就是那些 .cp 文件)。由于Python2和Python3的兼容性原因,我们需要把open()函数的”r”改成”rb”,”w”改成”wb”,同时在pickle.load()里面添加一下参数,改为 pickle.load(f, encoding=”bytes”)。

适配下载的东西

我也是看了好久才看懂 use_preproc_bg.py 是干啥的……简而言之,使用 use_preproc_bg.py 这个文件里面的东西,替换掉 gen.py 里 main 函数里面相应的东西即可。同时还要注意,由于替换了东西, get_data 函数可以直接干掉,同时 wget 这个依赖就可以去掉了。

跑代码和Debug

好了,跑就是了。会出现几个Bug:

第一个是语料。如果你使用了自己的语料,但不是覆盖的 renderer_data/newsgroup/newsgroup.txt ,那么会报文件找不到。这个是一个硬编码的东西,改掉即可。

第二个是在synthgen.py 里面的 cv2.findContours 会报错。解决办法是去掉最前面的那个返回值接收。

第三个是colorize3_poisson.py里面一直会报 ValueError: zero-size array to reduction operation minimum which has no identity ,这个我没想通。

其他……反正在运行的过程中会不断报错,不影响的话忽略即可,只是生成的数据会少一些而已。——多跑几遍啦~

生成速度会比较慢,大概每秒1张。

转换数据格式

原来代码生成出来的是 h5 格式的「压缩包」,如果用在自己的项目里面的话需要拆解这个文件,转换成自己需要的格式。

本来要转换格式,顺带的做一下可视化吧,虽然自带也有可视化:

from pathlib import Path

import cv2
import h5py
import numpy as np
from tqdm import tqdm

db = h5py.File("SynthText.h5", 'r')
for ith, name in tqdm(enumerate(db["data"].keys())):
    sample_name = f"{ith:06d}"

    img_data = np.array(db["data"][name])
    text = data.attrs["txt"].tolist()
    bbox = data.attrs["wordBB"].astype(int).transpose(2, 1, 0)
    
    img_data = cv2.polylines(img_data, bbox, True, (0, 0, 255), 1)

    data_out.put_image(f"image/{sample_name}.jpg", cv2.cvtColor(img_data, cv2.COLOR_BGR2RGB))

print("Done")

遇到的坑

果然是学术代码……没有怎么考虑到易用性。比如硬编码了语料文件路径。

应该是字体考虑不周,所以生成出来的东西并不怎么能用。会有比较多的「一个位置放多个文本行,导致有些显示不全」,还会出现「有些文本行没有框,有些文本行框不对,有些框里面没有文本行」。所以,个人并不建议用它。

那些pickle文件一直报错。本来想重新在Python2下面读出来再生成一下,结果发现依旧报错。然后尝试了print出来,手动复制,再贴到代码里面,重新生成一下,然后发现这个方法可行。但是,有个文件里面存的是numpy.array,不能print出来再贴回去……于是找到了 encoding 这个参数。


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注