1. 准备工作

1.1 文件准备


可以看到一个example_data的文件夹,里面主要就是这么几个文件夹。

java可以使用paddleocr吗 java调用paddleocr_java可以使用paddleocr吗


如果想使用这个现有的example来产生自己的数据,需要做这么几个事情

  1. bg文件夹,存放要产生的图片的背景(图片颜色不重要,因为产出的图都是灰度图)
  2. char文件夹 默认有两个txt文件,chn.txt和eng.txt,里面放的就是要产生的 文本的字符,一行一个(我做数字识别,就是10行,每行分别是0-9这10个数字,注意:要保存成utf-8的格式,不然后面执行的时候回报错,其余文本文件同理)
  3. font文件夹 存放你要放在背景图上的文字的字体,也就是产生特定字体的文字图片,我这里主要是晶体管/七段数码管的字体(默认只有一个 simsun.ttf 宋体)
  4. font_list文件夹 默认有一个font_list.txt文件,每行一个字体名称(对应于font文件夹中的.ttf文件)

    如果不想手动一个一个字体名称复制粘贴,可以代码完成:
import os
def generate_font_txt(ttf_path,txt_path):
    ttf_list=os.listdir(ttf_path)
    txt_file_path=os.path.join(txt_path,'font_list.txt') # 默认的是font_list.txt
    # with当文件不存在的时候 就直接创建
    with open(txt_file_path,'w',encoding='utf-8') as f:
        for i in ttf_list:
            f.writelines(i+'\n')    
ttf_path='E:XXX/example_data/font'
txt_path='E:XXX/example_data/font_list'
generate_font_txt(ttf_path,txt_path)
  1. output文件夹 这个就是存放产出的图片及标签的文件
  2. text文件夹 默认有三个txt文件,分别是chn_text.txt,eng_text.txt,enum_text.txt。
    chn_text.txt里存放着中文文章(有标点符号,分段的那种),程序会自动从里面随机截取一段生成图片;同理,eng_text.txt里也是一段英文文档(有空格 有标点符号 分段的那种)。所以这两个文件我暂时用不到,和我的场景不是很匹配。
    enum_text.txt里每行一串字符,会随机从这个文件中的行里挑选一行,然后结合背景,产生图片(会选择一整行的文本,所以是enumerate 枚举)
    为了生成随机的数字,代码:
    (这里注意,位数越大的数字个数也越多,所以如果要产生1-8位的数字,想要比较随机的话,最好分开产生 我的场景里大部分数字都是3位数。。。再加个标点符号)
def generate_enum_text(enum_path):   
    low_num=np.random.choice(a=np.arange(10**4,10**8),size=200,replace=False) 
    high_num=np.random.choice(a=np.arange(10**4),size=100,replace=False) 
    low_numlist=list(low_num)
    high_numlist=list(high_num)
    low_numlist.extend(high_numlist) # extend函数是原地操作 没有返回值
    random.shuffle(low_numlist) # shuffle也是原地操作函数 无返回值
    enum_file_path=os.path.join(enum_path,'enum_text.txt')     
    with open(enum_file_path,'w',encoding='utf-8') as f:
        for i in low_numlist:
            f.writelines(str(i)+'\n')
enum_txt_path='E:XXX/example_data/text'
generate_enum_text(enum_txt_path)

1.2 代码修改

  • example.py中,只需要保留与enum_data相关的部分,其余都注释掉就可以
  • 这里可以使用的效果很少,所以就按照默认的只加了透视变换
  • 修改产生图片的数量 num_image
  • num_pick=1 这个参数的意思是每次从texts里选几个来生成文本,默认是1,但是可能由于我的enum_text.txt文件只有2800多项,但是生成的图片要1w多张,在实际生成的图片里,我看到了8位数的图片???(我enum_text.txt文件里只有3位数到6位数的)
    根据源码:Source code for text_renderer.corpus.enum_corpus 这个参数默认值也是1,但是实际试验的效果告诉我,还是写上,不然会产错
  • 产生图片是追加,不是覆盖文件夹内容(所以每次要新产一次,要么改文件夹名称,要么删除该文件夹,让它重建。训练集,测试集分开产,不然标签文件要自己改,比较麻烦)
enum_data = GeneratorCfg(
    num_image=10240,
    save_dir=OUT_DIR / "enum_corpus",
    render_cfg=RenderCfg(
        bg_dir=BG_DIR,
        perspective_transform=perspective_transform,
        corpus=EnumCorpus(
            EnumCorpusCfg(
                text_paths=[TEXT_DIR / "enum_text.txt"],
                filter_by_chars=True,
                num_pick=1,
                chars_file=CHAR_DIR / "chn.txt",
                **font_cfg
            ),
        ),
    text_color_cfg= SimpleTextColorCfg(alpha=(200, 255))
    ),
)

运行 (切换到有main.py的目录下 调出cmd 直接命令行 不需要 anaconda prompt)

# 不是linux环境,所以也不是python3 直接python就可以
python main.py  --config example_data\example.py --dataset img --num_processes 2 --log_period 10

2. 制作符合PaddleOCR要求的数据集

2.1 修改文件夹形式和名称

执行上面命令两次,把产出的东西图片文件夹及对应标签重新命名,类似;

java可以使用paddleocr吗 java调用paddleocr_数据集_02


最后的数据集的目录格式应该类似:

|- train_data
	|- train.txt
	|- train
		|- word_001.jpg
		|- ..
	|- test.txt
	|- test
		|- word_001.jpg
		|- ..

2.2 修改标签文件格式

标签文件中的格式应该类似于:

train/train_0001.jpg\t简单可依赖
train/train_0002.jpg\t用科技让复杂的世界更简单

所以要用代码改一下标签格式,观察json文件,其实改起来应该也比较简单

import os
import json
def change_label_format(prefix,dirPath):
    json_path=os.path.join(dirPath,prefix+'.json')
    txt_path=os.path.join(dirPath,prefix+'.txt')
    with open(json_path, 'r',encoding='utf8') as f:
        json_data = json.load(f)
    with open(txt_path,'w',encoding='utf8') as f2:
        for k,v in json_data['labels'].items():
            linStr=prefix+'/'+str(k)+'.jpg'+'\t'+str(v)
            f2.writelines(linStr+'\n')
Path='E:XXXX/num_data'
change_label_format('train',Path)  # 训练集
change_label_format('test',Path)  # 测试集

改完之后的效果:

java可以使用paddleocr吗 java调用paddleocr_txt文件_03


java可以使用paddleocr吗 java调用paddleocr_java可以使用paddleocr吗_04

2.3 放到PaddleOCR中

在PaddleOCR文件夹中,默认就有一个train_data文件夹,最好把自己的训练集测试集文件夹再放到一个文件夹中再放进去,这样方便以后其他的训练(比如我的是 num_data)
这里配置文件会有:

img_set_dir: ./train_data/num_data
label_file_path: ./train_data/num_data/train.txt

所以标签文件里图片路径给的是 train/train_0001.jpg 只要和img_set_dir拼起来就是完整路径了(都是可以自己配置的,只要合理即可)

|-PaddleOCR
	|-train_data
	    |-num_data
	        |- train.txt
	        |- train
	            |- word_001.png
	            |- word_002.jpg
	            |- word_003.jpg
	            | ...
	        |- rec_gt_test.txt
			|- test
			            |- word_001.jpg
			            |- word_002.jpg
			            |- word_003.jpg
			            | ...

把修改过标签文件的数据集放到PaddleOCR的train_data文件夹中。(这里注意,不是直接通过xshell的lrzsz拖动完成的,是通过winscp上传的,而且winscp设置过一些东西(自己是管理员权限),参考之前写的
PaddleOCR数字仪表识别——3.paddleocr迁移学习的3.2.2.2部分,目录只显示到3级,没有四级,自己手动定位。

等一会就上传好了,比较慢。。。

java可以使用paddleocr吗 java调用paddleocr_数据集_05


上传之后我的差不多是这样子

3. 额外要注意的点

3.1 要不要产含有小数点的图

java可以使用paddleocr吗 java调用paddleocr_java可以使用paddleocr吗_06


可以发现:小数点占位(是一整格还是非一整格)是与字体有关的,对于宋体,小数点和其他数字一样,都占一格,但是对于大部分的数码管字体,小数点都不会占一格。网上没有找到很多关于深度学习处理小数点的内容,只有一个论文

Text detection and recognition in raw image dataset of seven segment digital energy meter display

java可以使用paddleocr吗 java调用paddleocr_数据集_07


论文里说:在他们的场景中,他们的数据中小数点都位于最后一个数字前一位,可以看到,他们的图片中小数点有时候也是占一整格,有时候占的格也很小。

但是他们是字符分割,我们是行识别,不一样。。。没法类比,所以行识别识别小数点不太现实。

所以数据暂时还是不生产小数了,还是多生产一些2-5位数的数字吧

3.2 数据集大小

两个数字要确定

  1. 数据集的大小
  2. 要产生的 enum_text.txt中枚举的数字序列的个数


java可以使用paddleocr吗 java调用paddleocr_json_08


363w张 5990个字符 99:1的训练集和验证集

对等一下 10个字符 差不多就是3630000/5990*10=6060.100166944908 那就多一点好了

之前训练的时候:
batch_size * devices_num * num_workers (2048) 要求训练集数量要大于这个
batch_size*devices_num*num_workers(256) 测试集的时候 要求大于这个

此外,考虑到字体有很多种类,所以还是多一些好