数据准备 (Beta)¶
注解
Dataset Preparer 目前仍处在公测阶段,欢迎尝鲜试用!如遇到任何问题,请及时向我们反馈。
一键式数据准备脚本¶
MMOCR 提供了统一的一站式数据集准备脚本 prepare_dataset.py
。
仅需一行命令即可完成数据的下载、解压、格式转换,及基础配置的生成。
python tools/dataset_converters/prepare_dataset.py [-h] [--nproc NPROC] [--task {textdet,textrecog,textspotting,kie}] [--splits SPLITS [SPLITS ...]] [--lmdb] [--overwrite-cfg] [--dataset-zoo-path DATASET_ZOO_PATH] datasets [datasets ...]
参数 | 类型 | 说明 |
---|---|---|
dataset_name | str | (必须)需要准备的数据集名称。 |
--nproc | str | 使用的进程数,默认为 4。 |
--task | str | 将数据集格式转换为指定任务的 MMOCR 格式。可选项为: 'textdet', 'textrecog', 'textspotting' 和 'kie'。 |
--splits | ['train', 'val', 'test'] | 希望准备的数据集分割,可以接受多个参数。默认为 train val test 。 |
--lmdb | str | 把数据储存为 LMDB 格式,仅当任务为 textrecog 时生效。 |
--overwrite-cfg | str | 若数据集的基础配置已经在 configs/{task}/_base_/datasets 中存在,依然重写该配置 |
--dataset-zoo-path | str | 存放数据库配置文件的路径。若不指定,则默认为 ./dataset_zoo |
例如,以下命令展示了如何使用该脚本为 ICDAR2015 数据集准备文本检测任务所需的数据。
python tools/dataset_converters/prepare_dataset.py icdar2015 --task textdet --overwrite-cfg
该脚本也支持同时准备多个数据集,例如,以下命令展示了如何使用该脚本同时为 ICDAR2015 和 TotalText 数据集准备文本识别任务所需的数据。
python tools/dataset_converters/prepare_dataset.py icdar2015 totaltext --task textrecog --overwrite-cfg
进一步了解 Dataset Preparer 支持的数据集,您可以浏览支持的数据集文档。一些需要手动准备的数据集也列在了 文字检测 和 文字识别 内。
对于中国境内的用户,我们也推荐通过开源数据平台OpenDataLab来下载数据,以获得更好的下载体验。数据下载后,参考脚本中 data_obtainer
的 save_name
字段,将文件放在 data/cache/
下并重新运行脚本即可。
进阶用法¶
LMDB 格式¶
在文本识别任务中,我们通常使用 LMDB 格式来存储数据,以加快数据的读取速度。在使用 prepare_dataset.py
脚本准备数据时,可以通过 --lmdb
参数来指定将数据转换为 LMDB 格式。例如:
python tools/dataset_converters/prepare_dataset.py icdar2015 --task textrecog --lmdb
数据集准备完成后,Dataset Preparer 会在 configs/textrecog/_base_/datasets/
中生成 icdar2015_lmdb.py
配置。你可以继承该配置,并将 dataloader
指向 LMDB 数据集。然而,LMDB 数据集的读取需要配合 LoadImageFromNDArray
,因此你也同样需要修改 pipeline
。
例如,我们想要将 configs/textrecog/crnn/crnn_mini-vgg_5e_mj.py
的训练集改为刚刚生成的 icdar2015,则需要作如下修改:
修改
configs/textrecog/crnn/crnn_mini-vgg_5e_mj.py
:_base_ = [ '../_base_/datasets/icdar2015_lmdb.py', # 指向 icdar2015 lmdb 数据集 ... # 省略 ] train_list = [_base_.icdar2015_lmdb_textrecog_train] ...
修改
configs/textrecog/crnn/_base_crnn_mini-vgg.py
中的train_pipeline
, 将LoadImageFromFile
改为LoadImageFromNDArray
:train_pipeline = [ dict( type='LoadImageFromNDArray', color_type='grayscale', file_client_args=file_client_args, ignore_empty=True, min_size=2), ... ]
数据集配置¶
数据集自动化准备脚本使用了模块化的设计,极大地增强了扩展性,用户能够很方便地配置其他公开数据集或私有数据集。数据集自动化准备脚本的配置文件被统一存储在 dataset_zoo/
目录下,用户可以在该目录下找到所有已由 MMOCR 官方支持的数据集准备脚本配置文件。该文件夹的目录结构如下:
dataset_zoo/
├── icdar2015
│ ├── metafile.yml
│ ├── textdet.py
│ ├── textrecog.py
│ └── textspotting.py
└── wildreceipt
├── metafile.yml
├── kie.py
├── textdet.py
├── textrecog.py
└── textspotting.py
其中,metafile.yml
是数据集的元信息文件,其中存放了对应数据集的基本信息,包括发布年份,论文作者,以及版权等其他信息。其它以任务名命名的则是数据集准备脚本的配置文件,用于配置数据集的下载、解压、格式转换等操作。这些配置文件采用了 Python 格式,其使用方法与 MMOCR 算法库的其他配置文件完全一致,详见配置文件文档。
数据集元文件¶
以数据集 ICDAR2015 为例,metafile.yml
中存储了基础的数据集信息:
Name: 'Incidental Scene Text IC15'
Paper:
Title: ICDAR 2015 Competition on Robust Reading
URL: https://rrc.cvc.uab.es/files/short_rrc_2015.pdf
Venue: ICDAR
Year: '2015'
BibTeX: '@inproceedings{karatzas2015icdar,
title={ICDAR 2015 competition on robust reading},
author={Karatzas, Dimosthenis and Gomez-Bigorda, Lluis and Nicolaou, Anguelos and Ghosh, Suman and Bagdanov, Andrew and Iwamura, Masakazu and Matas, Jiri and Neumann, Lukas and Chandrasekhar, Vijay Ramaseshan and Lu, Shijian and others},
booktitle={2015 13th international conference on document analysis and recognition (ICDAR)},
pages={1156--1160},
year={2015},
organization={IEEE}}'
Data:
Website: https://rrc.cvc.uab.es/?ch=4
Language:
- English
Scene:
- Natural Scene
Granularity:
- Word
Tasks:
- textdet
- textrecog
- textspotting
License:
Type: CC BY 4.0
Link: https://creativecommons.org/licenses/by/4.0/
该文件在数据集准备过程中并不是强制要求的(因此用户在使用添加自己的私有数据集时可以忽略该文件),但为了用户更好地了解各个公开数据集的信息,我们建议用户在使用数据集准备脚本前阅读对应的元文件信息,以了解该数据集的特征是否符合用户需求。
警告
自 MMOCR 1.0.0rc6 起,接下来的章节可能会与实际实现有所出入。
数据集准备脚本配置文件¶
下面,我们将介绍数据集准备脚本配置文件 textXXX.py
的默认字段与使用方法。
我们在配置文件中提供了 data_root
与 cache_path
两个默认字段,分别用于存放转换后的 MMOCR 格式的数据集文件,以及在数据准备过程中下载的压缩包等临时文件。
data_root = './data/icdar2015'
cache_path = './data/cache'
其次,数据集的准备通常包含了“原始数据准备”、“格式转换和保存”及“生成基础配置”这三个主要步骤。因此,我们约定通过 data_obtainer
、 data_converter
和 config_generator
参数来配置这三个步骤的行为。
注解
如果用户需要跳过某一步骤,则可以省略配置相应参数。例如,如果数据集本身已经遵循 MMOCR 的格式,用户就可以省略掉 data_converter
的配置来跳过数据集格式的转换。或者,如果用户不需要自动生成基础配置,可以忽略掉 config_generator
的配置。
接下来,我们将以 ICDAR2015 数据集的文本检测任务准备配置文件(dataset_zoo/icdar2015/textdet.py
)为例,逐个模块解析 Dataset Preparer 的运行流程。
原始数据准备 - data_obtainer
¶
data_obtainer = dict(
type='NaiveDataObtainer',
cache_path=cache_path,
data_root=data_root,
files=[
dict(
url='https://rrc.cvc.uab.es/downloads/ch4_training_images.zip',
save_name='ic15_textdet_train_img.zip',
md5='c51cbace155dcc4d98c8dd19d378f30d',
split=['train'],
content=['image'],
mapping=[['ic15_textdet_train_img', 'textdet_imgs/train']]),
dict(
url='https://rrc.cvc.uab.es/downloads/'
'ch4_training_localization_transcription_gt.zip',
save_name='ic15_textdet_train_gt.zip',
md5='3bfaf1988960909014f7987d2343060b',
split=['train'],
content=['annotation'],
mapping=[['ic15_textdet_train_gt', 'annotations/train']]),
# ...
])
数据准备器 data_obtainer
的类型默认为 NaiveDataObtainer
,其主要功能是依次下载压缩包并解压到指定目录。在这里,我们通过 files
参数来配置下载的压缩包的 URL、保存名称、MD5 值等信息。其中,mapping
参数用于指定该压缩包中的数据解压后的存放路径。另外 split
和 content
这两个可选参数则分别标明了该压缩包中存储的内容类型与其对应的数据集合。
格式转换和保存 - data_converter
¶
data_converter = dict(
type='TextDetDataConverter',
splits=['train', 'test'],
data_root=data_root,
gatherer=dict(
type='pair_gather',
suffixes=['.jpg', '.JPG'],
rule=[r'img_(\d+)\.([jJ][pP][gG])', r'gt_img_\1.txt']),
parser=dict(type='ICDARTxtTextDetAnnParser'),
dumper=dict(type='JsonDumper'),
delete=['annotations', 'ic15_textdet_test_img', 'ic15_textdet_train_img'])
数据转换器 data_converter
主要由转换器及子模块 gatherer
、parser
及 dumper
组成,负责完成原始数据的读取与格式转换,并保存为 MMOCR 支持的格式。
目前,MMOCR 中支持的数据集转换器类别如下:
文本检测任务数据转换器
TextDetDataConverter
文本识别任务数据转换器
TextRecogDataConverter
TextRecogCropConverter
端到端文本检测识别任务转换器
TextSpottingDataConverter
关键信息抽取任务数据转换器
WildReceiptConverter
MMOCR 中目前支持的转换器主要以任务为边界,这是因为不同任务所需的数据格式有细微的差异。
比较特别的是,文本识别任务有两个数据转换器,这是因为不同的文本识别数据集提供文字图片的方式有所差别。有的数据集提供了仅包含文字的小图,它们天然适用于文本识别任务,可以直接使用 TextRecogDataConverter
处理。而有的数据集提供的是包含了周围场景的大图,因此在准备数据集时,我们需要预先根据标注信息把文字区域裁剪出来,这种情况下则要用到 TextRecogCropConverter
。
简单介绍下 TextRecogCropConverter
数据转换器的使用方法:
由于标注文件的解析方式与 TextDet 环节一致,所以仅需继承
dataset_zoo/xxx/textdet.py
的 data_converter,并修改type值为 ‘TextRecogCropConverter’,TextRecogCropConverter
会在执行pack_instance()
方法时根据解析获得的标注信息完成文字区域的裁剪。同时,根据是否存在旋转文字区域标注内置了两种裁剪方式,默认按照水平文本框裁剪。如果存在旋转的文字区域,可以设置
crop_with_warp=True
切换为使用 OpenCV warpPerspective 方法进行裁剪。
_base_ = ['textdet.py']
data_converter = dict(
type='TextRecogCropConverter',
crop_with_warp=True)
接下来,我们将具体解析 data_converter
的功能。以文本检测任务为例,TextDetDataConverter
与各子模块配合,主要完成以下工作:
gatherer
负责收集并匹配原始数据集中的图片与标注文件,如图像img_1.jpg
与标注gt_img_1.txt
parser
负责读取原始标注文件,解析出文本框坐标与文本内容等必要信息转换器将解析后的数据统一转换至 MMOCR 中当前任务的格式
dumper
将转换后的数据保存为指定路径和文件格式转换器删除
delete
参数指定的临时文件
以上个步骤我们分别可以通过 gatherer
,parser
,dumper
, delete
来进行配置。
gatherer
¶
作为数据转换的第一步,data_converter
会通过 gatherer
遍历数据集目录下的文件,将图像与标注文件一一对应,并整理出一份文件列表供 parser
读取。因此,我们首先需要知道当前数据集下,图片文件与标注文件匹配的规则。
OCR 数据集通常有两种标注保存形式,一种为多个标注文件对应多张图片,一种则为单个标注文件对应多张图片,如:
多对多
├── {taskname}_imgs/{split}/img_img_1.jpg
├── annotations/{split}/gt_img_1.txt
├── {taskname}_imgs/{split}/img_2.jpg
├── annotations/{split}/gt_img_2.txt
├── {taskname}_imgs/{split}/img_3.JPG
├── annotations/{split}/gt_img_3.txt
单对多
├── {taskname}/{split}/img_1.jpg
├── {taskname}/{split}/img_2.jpg
├── {taskname}/{split}/img_3.JPG
├── annotations/gt.txt
注解
为了简化处理,gatherer 约定数据集的图片和标注需要分别储存在 {taskname}_imgs/{split}/
和 annotations/
下。特别地,对于多对多的情况,标注文件需要放置于 annotations/{split}
下。如本例中,icdar 2015 训练集的图片就被储存在 textdet_imgs/train/
下,而训练的标注则被存在 annotations/train/
下。
因此,我们内置了 pair_gather
与 mono_gather
来处理以上这两种情况。其中 pair_gather
用于多对多的情况,mono_gather
用于单对多的情况。
在多对多的情况下,pair_gather
需要按照一定的命名规则找到图片文件和对应的标注文件。首先,我们需要通过 suffixes
参数指定图片的后缀名,如上述例子中的 suffixes=[.jpg,.JPG]
。此外,还需要通过正则表达式来指定图片与标注文件的对应关系,如上述例子中的 rule=[r'img_(\d+)\.([jJ][pP][gG])',r'gt_img_\1.txt']
。其中 \d+
用于匹配图片的序号,([jJ][pP][gG])
用于匹配图片的后缀名,\1
则将匹配到的图片序号与标注文件序号对应起来。
单对多的情况通常比较简单,用户只需要指定每个 split 对应的标注文件即可。因此 mono_gather
预设了 train_ann
、val_ann
和 test_ann
参数,供用户直接指定标注文件。
parser
¶
当获取了图像与标注文件的对应关系后,data preparer 将解析原始标注文件。由于不同数据集的标注格式通常有很大的区别,当我们需要支持新的数据集时,通常需要实现一个新的 parser
来解析原始标注文件。parser 将任务相关的数据解析后打包成 MMOCR 的统一格式。
dumper
¶
之后,我们可以通过指定不同的 dumper 来决定要将数据保存为何种格式。目前,我们支持 JsonDumper
, WildreceiptOpensetDumper
,及 TextRecogLMDBDumper
。他们分别用于将数据保存为标准的 MMOCR Json 格式、Wildreceipt 格式,及文本识别领域学术界常用的 LMDB 格式。
delete
¶
在处理数据集时,往往会产生一些不需要的临时文件。这里可以以列表的形式传入这些文件或文件夹,在结束转换时即会删除。
生成基础配置 - config_generator
¶
config_generator = dict(type='TextDetConfigGenerator', data_root=data_root)
在准备好数据集的所有文件后,配置生成器 TextDetConfigGenerator
就会自动为 MMOCR 生成调用该数据集所需要的基础配置文件。生成后的文件默认会被置于 configs/{task}/_base_/datasets/
下。例如,本例中,icdar 2015 的基础配置文件就会被生成在 configs/textdet/_base_/datasets/icdar2015.py
下:
icdar2015_textdet_data_root = 'data/icdar2015'
icdar2015_textdet_train = dict(
type='OCRDataset',
data_root=icdar2015_textdet_data_root,
ann_file='textdet_train.json',
filter_cfg=dict(filter_empty_gt=True, min_size=32),
pipeline=None)
icdar2015_textdet_test = dict(
type='OCRDataset',
data_root=icdar2015_textdet_data_root,
ann_file='textdet_test.json',
test_mode=True,
pipeline=None)
有了该文件后,我们就能从模型的配置文件中直接导入该数据集到 dataloader
中使用(以下样例节选自 configs/textdet/dbnet/dbnet_resnet18_fpnc_1200e_icdar2015.py
):
_base_ = [
'../_base_/datasets/icdar2015.py',
# ...
]
# dataset settings
icdar2015_textdet_train = _base_.icdar2015_textdet_train
icdar2015_textdet_test = _base_.icdar2015_textdet_test
# ...
train_dataloader = dict(
dataset=icdar2015_textdet_train)
val_dataloader = dict(
dataset=icdar2015_textdet_test)
test_dataloader = val_dataloader
注解
除非用户在运行脚本的时候手动指定了 overwrite-cfg
,配置生成器默认不会自动覆盖已经存在的基础配置文件。
由于每个任务所需的基本数据集配置格式不一,我们也针对各个任务推出了 TextRecogConfigGenerator
及 TextSpottingConfigGenerator
等生成器。
向 Dataset Preparer 添加新的数据集¶
添加公开数据集¶
MMOCR 已经支持了许多常用的公开数据集。如果你想用的数据集还没有被支持,并且你也愿意为 MMOCR 开源社区贡献代码,你可以按照以下步骤来添加一个新的数据集。
接下来我们以添加 ICDAR2013 数据集为例,展示如何一步一步地添加一个新的公开数据集。
添加 metafile.yml
¶
首先,我们确认 dataset_zoo/
中不存在我们准备添加的数据集。然后我们先新建以待添加数据集命名的文件夹,如 icdar2013/
(通常,我们使用不包含符号的小写英文字母及数字来命名数据集)。在 icdar2013/
文件夹中,我们新建 metafile.yml
文件,并按照以下模板来填充数据集的基本信息:
Name: 'Incidental Scene Text IC13'
Paper:
Title: ICDAR 2013 Robust Reading Competition
URL: https://www.imlab.jp/publication_data/1352/icdar_competition_report.pdf
Venue: ICDAR
Year: '2013'
BibTeX: '@inproceedings{karatzas2013icdar,
title={ICDAR 2013 robust reading competition},
author={Karatzas, Dimosthenis and Shafait, Faisal and Uchida, Seiichi and Iwamura, Masakazu and i Bigorda, Lluis Gomez and Mestre, Sergi Robles and Mas, Joan and Mota, David Fernandez and Almazan, Jon Almazan and De Las Heras, Lluis Pere},
booktitle={2013 12th international conference on document analysis and recognition},
pages={1484--1493},
year={2013},
organization={IEEE}}'
Data:
Website: https://rrc.cvc.uab.es/?ch=2
Language:
- English
Scene:
- Natural Scene
Granularity:
- Word
Tasks:
- textdet
- textrecog
- textspotting
License:
Type: N/A
Link: N/A
Format: .txt
Keywords:
- Horizontal
metafile.yml
存储了数据集的基本信息,这些信息一方面可以帮助用户了解数据集的基本情况,另一方面也会被用于自动化脚本来生成相应的数据集文档。因此,当你向 MMOCR Dataset Preparer 添加新的数据集支持时,请按照以上模板来填充 metafile.yml
文件。具体地,我们在下表中列出每个字段对应的含义:
字段名 | 含义 |
---|---|
Name | 数据集的名称 |
Paper.Title | 数据集论文的标题 |
Paper.URL | 数据集论文的链接 |
Paper.Venue | 数据集论文发表的会议/期刊名称 |
Paper.Year | 数据集论文发表的年份 |
Paper.BibTeX | 数据集论文的引用的 BibTex |
Data.Website | 数据集的官方网站 |
Data.Language | 数据集支持的语言 |
Data.Scene | 数据集支持的场景,如 Natural Scene , Document , Handwritten 等 |
Data.Granularity | 数据集支持的粒度,如 Character , Word , Line 等 |
Data.Tasks | 数据集支持的任务,如 textdet , textrecog , textspotting , kie 等 |
Data.License | 数据集的许可证信息,如果不存在许可证,则使用 N/A 填充 |
Data.Format | 数据集标注文件的格式,如 .txt , .xml , .json 等 |
Data.Keywords | 数据集的特性关键词,如 Horizontal , Vertical , Curved 等 |
添加对应任务的配置文件¶
在 dataset_zoo/icdar2013
中,我们接着添加以任务名称命名的 .py
配置文件。如 textdet.py
,textrecog.py
,textspotting.py
,kie.py
等。在该文件中,我们需要对数据获取方式和转换方式进行配置。
配置数据集获取方法 data_obtainer
¶
以文本检测任务为例:
data_obtainer = dict(
type='NaiveDataObtainer',
cache_path=cache_path,
data_root=data_root,
files=[
dict(
url='https://rrc.cvc.uab.es/downloads/'
'Challenge2_Training_Task12_Images.zip',
save_name='ic13_textdet_train_img.zip',
md5='a443b9649fda4229c9bc52751bad08fb',
split=['train'],
content=['image'],
mapping=[['ic13_textdet_train_img', 'textdet_imgs/train']]),
dict(
url='https://rrc.cvc.uab.es/downloads/'
'Challenge2_Training_Task1_GT.zip',
save_name='ic13_textdet_test_img.zip',
md5='af2e9f070c4c6a1c7bdb7b36bacf23e3',
split=['test'],
content=['image'],
mapping=[['ic13_textdet_test_img', 'textdet_imgs/test']]),
dict(
url='https://rrc.cvc.uab.es/downloads/'
'Challenge2_Test_Task12_Images.zip',
save_name='ic13_textdet_train_gt.zip',
md5='f3a425284a66cd67f455d389c972cce4',
split=['train'],
content=['annotation'],
mapping=[['ic13_textdet_train_gt', 'annotations/train']]),
dict(
url='https://rrc.cvc.uab.es/downloads/'
'Challenge2_Test_Task1_GT.zip',
save_name='ic13_textdet_test_gt.zip',
md5='3191c34cd6ac28b60f5a7db7030190fb',
split=['test'],
content=['annotation'],
mapping=[['ic13_textdet_test_gt', 'annotations/test']]),
])
我们首先需要配置数据集获取方法,即 data_obtainer
,通常来说,内置的 NaiveDataObtainer
即可完成绝大部分可以通过直链访问的数据集的下载。NaiveDataObtainer
将完成下载、解压、移动文件和重命名等操作。目前,我们暂时不支持自动下载存储在百度或谷歌网盘等需要登陆才能访问资源的数据集。
如下表所示,data_obtainer
主要由四个字段构成:
字段名 | 含义 |
---|---|
type | 数据集获取方法,目前仅支持 NaiveDataObtainer |
cache_path | 数据集缓存路径,用于存储数据集准备过程中下载的压缩包等文件 |
data_root | 数据集存储的根目录 |
files | 数据集文件列表,用于描述数据集的下载信息 |
files
字段是一个列表,列表中的每个元素都是一个字典,用于描述一个数据集文件的下载信息。如下表所示:
字段名 | 含义 |
---|---|
url | 数据集文件的下载链接 |
save_name | 数据集文件的保存名称 |
md5 (可选) | 数据集文件的 md5 值,用于校验下载的文件是否完整 |
split (可选) | 数据集文件所属的数据集划分,如 train ,test 等,该字段可以空缺 |
content (可选) | 数据集文件的内容,如 image ,annotation 等,该字段可以空缺 |
mapping (可选) | 数据集文件的解压映射,用于指定解压后的文件存储的位置,该字段可以空缺 |
注解
为了让 data_converter.gatherer
正常运行,我们约定数据集的图片和标注分别储存在 {taskname}_imgs/{split}/
和 annotations/
下。特别地,对于多对多的情况,标注文件需要放置于 annotations/{split}
下。
配置数据集转换器 data_converter
¶
数据集转换器 data_converter
主要由标注文件获取器 gatherer
,原始标注解析器 parser
,以及数据存储器 dumper
组成。其中 gatherer
负责将图片与标注文件进行匹配,parser
负责将原始标注文件解析为标准格式,dumper
负责将标准格式的标注文件存储为 MMOCR 支持的格式。
一般来说,用户无需重新实现新的 gatherer
或 dumper
,但是通常需要根据数据集的标注格式实现新的 parser
。
我们通过观察获取的 ICDAR2013 数据集文件发现,其每一张图片都有一个对应的 .txt
格式的标注文件:
data_root
├── textdet_imgs/train/
│ ├── img_1.jpg
│ ├── img_2.jpg
│ └── ...
├── annotations/train/
│ ├── gt_img_1.txt
│ ├── gt_img_2.txt
│ └── ...
且每个标注文件名与图片的对应关系为:gt_img_1.txt
对应 img_1.jpg
,以此类推。因此,我们可以使用 pair_gather
来进行匹配。
gatherer=dict(
type='pair_gather',
suffixes=['.jpg'],
rule=[r'(\w+)\.jpg', r'gt_\1.txt'])
其中,规则 rule
是一个正则表达式对,第一个正则表达式用于匹配图片文件名,第二个正则表达式用于匹配标注文件名。在这里,我们使用 (\w+)
来匹配图片文件名,使用 gt_\1.txt
来匹配标注文件名,其中 \1
表示第一个正则表达式匹配到的内容。即,实现了将 img_xx.jpg
替换为 gt_img_xx.txt
的功能。
接下来,我们需要实现 parser
,即将原始标注文件解析为标准格式。通常来说,用户在添加新的数据集前,可以浏览已支持数据集的详情页,并查看是否已有相同格式的数据集。如果已有相同格式的数据集,则可以直接使用该数据集的 parser
。否则,则需要实现新的格式解析器。
数据格式解析器被统一存储在 mmocr/datasets/preparers/parsers
目录下。所有的 parser
都需要继承 BaseParser
,并实现 parse_file
或 parse_files
方法。
其中,parse_file()
方法用于解析单个标注文件,如下代码块所示,parse_file()
接受两个参数,file
是一个 Tuple
类型的变量,包含了由 gatherer
获取的图片文件路径和标注文件路径,而 split
则会传入当前处理的数据集划分,如 train
或 test
。
def parse_file(self, file: Tuple, split: str) -> Tuple:
"""Convert annotation for a single image.
Args:
file (Tuple): A tuple of path to image and annotation
split (str): Current split.
Returns:
Tuple: A tuple of (img_path, instance). Instance is a dict
containing parsed annotations, which should contain the
following keys:
- 'poly' or 'box' (textdet or textspotting)
- 'text' (textspotting or textrecog)
- 'ignore' (all task)
"""
parse_file()
方法的输出是一个 Tuple
类型的变量,包含了图片文件路径和标注信息 instance
。其中,instance
是一个字典列表,包含了解析后的标注信息,依据不同的任务类型,该列表中的每一个字典必须包含以下键:
键名 | 任务类型 | 说明 |
---|---|---|
box/poly | textdet/textspotting | 矩形框坐标 box 或多边形框坐标 poly |
text | textrecog/textspotting | 文本内容 text |
ignore | all task | 是否忽略该样本 |
以下代码块反映了一个 parse_file()
方法返回的数据示例:
('imgs/train/xxx.jpg',
dict(
poly=[[[0, 1], [1, 1], [1, 0], [0, 0]]],
text='hello',
ignore=False)
)
需要注意的是,parse_file()
方法解析单个标注文件,并返回单张图片的标注信息,仅能在标注图像与标注文件满足“多对多”关系时使用。当仅存在单个标注文件时,可以通过重写 parse_files()
方法的方式,直接返回所有样本的数据信息。用户可以参见 mmocr/datasets/preparers/parsers/totaltext_parser.py
中的实现。
通过观察 ICDAR2013 数据集的标注文件:
158 128 411 181 "Footpath"
443 128 501 169 "To"
64 200 363 243 "Colchester"
542, 710, 938, 841, "break"
87, 884, 457, 1021, "could"
517, 919, 831, 1024, "save"
我们发现内置的 ICDARTxtTextDetAnnParser
已经可以满足我们的需求,因此我们可以直接使用该 parser
,并将其配置到 preparer
中。
parser=dict(
type='ICDARTxtTextDetAnnParser',
remove_strs=[',', '"'],
encoding='utf-8',
format='x1 y1 x2 y2 trans',
separator=' ',
mode='xyxy')
其中,由于标注文件中混杂了多余的引号 “”
和逗号 ,
,我们通过指定 remove_strs=[',', '"']
来进行移除。另外,我们在 format
中指定了标注文件的格式,其中 x1 y1 x2 y2 trans
表示标注文件中的每一行包含了四个坐标和一个文本内容,且坐标和文本内容之间使用空格分隔(separator
=’ ‘)。另外,我们需要指定 mode
为 xyxy
,表示标注文件中的坐标是左上角和右下角的坐标,这样以来,ICDARTxtTextDetAnnParser
即可将该格式的标注解析为 MMOCR 统一格式。
最后,数据格式转换器 data_converter
的完整配置如下:
data_converter = dict(
type='TextDetDataConverter',
splits=['train', 'test'],
data_root=data_root,
gatherer=dict(
type='pair_gather',
suffixes=['.jpg'],
rule=[r'(\w+)\.jpg', r'gt_\1.txt']),
parser=dict(
type='ICDARTxtTextDetAnnParser',
remove_strs=[',', '"'],
encoding='utf-8',
format='x1 y1 x2 y2 trans',
separator=' ',
mode='xyxy'),
dumper=dict(type='JsonDumper'))
配置基础配置生成器 config_generator
¶
为了在数据集准备完毕后可以自动生成基础配置,我们还需要配置一下对应任务的 config_generator
。目前,MMOCR 按任务实现了 TextDetConfigGenerator
、TextRecogConfigGenerator
和 TextSpottingConfigGenerator
。它们支持的主要参数如下:
字段名 | 含义 |
---|---|
data_root | 数据集存储的根目录 |
train_anns | 配置文件内训练集标注的路径。若不指定,则默认为 [dict(ann_file='{taskname}_train.json', dataset_postfix=''] 。 |
val_anns | 配置文件内验证集标注的路径。若不指定,则默认为空。 |
test_anns | 配置文件内测试集标注的路径。若不指定,则默认指向 [dict(ann_file='{taskname}_test.json', dataset_postfix=''] 。 |
config_path | 算法库存放配置文件的路径,配置生成器会将默认配置写入 {config_path}/{taskname}/_base_/datasets/{dataset_name}.py 下。若不指定,则默认为 configs/ |
在本例中,我们只需要设置一下 TextDetConfigGenerator
的 data_root
字段,其它字段保持默认即可。
config_generator = dict(type='TextDetConfigGenerator', data_root=data_root)
假如数据集比较特殊,标注存在着几个变体,配置生成器也支持在基础配置中生成指向各自变体的变量,但这需要用户在设置时用不同的 dataset_postfix
区分。例如,ICDAR 2015 文字识别数据的测试集就存在着原版和 1811 两种标注版本,我们可以在 test_anns
中指定它们,如下所示:
config_generator = dict(
type='TextRecogConfigGenerator',
data_root=data_root,
test_anns=[
dict(ann_file='textrecog_test.json'),
dict(dataset_postfix='857', ann_file='textrecog_test_857.json')
])
配置生成器会生成以下配置:
icdar2015_textrecog_data_root = 'data/icdar2015'
icdar2015_textrecog_train = dict(
type='OCRDataset',
data_root=icdar2015_textrecog_data_root,
ann_file='textrecog_train.json',
pipeline=None)
icdar2015_textrecog_test = dict(
type='OCRDataset',
data_root=icdar2015_textrecog_data_root,
ann_file='textrecog_test.json',
test_mode=True,
pipeline=None)
icdar2015_1811_textrecog_test = dict(
type='OCRDataset',
data_root=icdar2015_textrecog_data_root,
ann_file='textrecog_test_1811.json',
test_mode=True,
pipeline=None)
添加标注示例¶
最后,我们可以在 dataset_zoo/icdar2013/
目录下添加标注示例文件 sample_anno.md
以帮助文档脚本在生成文档时添加标注示例,标注示例文件是一个 Markdown 文件,其内容通常包含了单个样本的原始数据格式。例如,以下代码块展示了 ICDAR2013 数据集的数据样例文件:
**Text Detection**
```text
# train split
# x1 y1 x2 y2 "transcript"
158 128 411 181 "Footpath"
443 128 501 169 "To"
64 200 363 243 "Colchester"
# test split
# x1, y1, x2, y2, "transcript"
38, 43, 920, 215, "Tiredness"
275, 264, 665, 450, "kills"
0, 699, 77, 830, "A"
```
添加私有数据集¶
待更新…