OCR技术3-大批量生成文字训练集

2024-03-03 18:48

本文主要是介绍OCR技术3-大批量生成文字训练集,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如果是想训练一个手写体识别的模型,用一些前人收集好的手写文字集就好了,比如中科院的这些数据集。但是如果我们只是想要训练一个专门用于识别印刷汉字的模型,那么我们就需要各种印刷字体的训练集,那怎么获取呢?借助强大的图像库,自己生成就行了!

先捋一捋思路,生成文字集需要什么步骤:

  1. 确定你要生成多少字体,生成一个记录着汉字与label的对应表。
  2. 确定和收集需要用到的字体文件。
  3. 生成字体图像,存储在规定的目录下。
  4. 适当的数据增强。

第三步的生成字体图像最为重要,如果仅仅是生成很正规的文字,那么用这个正规文字集去训练模型,第一图像数目有点少,第二模型泛化能力比较差,所以我们需要对字体图像做大量的图像处理工作,以增大我们的印刷体文字数据集。

我总结了一下,我们可以做的一些图像增强工作有这些:

  1. 文字扭曲
  2. 背景噪声(椒盐)
  3. 文字位置(设置文字的中心点)
  4. 笔画粘连(膨胀来模拟)
  5. 笔画断裂(腐蚀来模拟)
  6. 文字倾斜(文字旋转)
  7. 多种字体

做完以上增强后,我们得到的数据集已经非常庞大了。

现在开始一步一步生成我们的3755个汉字的印刷体文字数据集。

一、生成汉字与label的对应表

这里的汉字、label映射表的生成我使用了pickel模块,借助它生成一个id:汉字的映射文件存储下来。
这里举个小例子说明怎么生成这个“汉字:id”映射表。

首先在一个txt文件里写入你想要的汉字,如果对汉字对应的ID没有要求的话,我们不妨使用该汉字的排位作为其ID,比如“一二三四五”中,五的ID就是00005。如此类推,把汉字读入内存,建立一个字典,把这个关系记录下来,再使用pickle.dump存入文件保存。

二、收集字体文件

字体文件上网收集就好了,但是值得注意的是,不是每一种字体都支持汉字,所以我们需要筛选出真正适合汉字生成的字体文件才可以。我一共使用了十三种汉字字体作为我们接下来汉字数据集用到的字体,具体如下图:

当然,如果需要进一步扩大数据集来增强训练得到的模型的泛化能力,可以花更多的时间去收集各类汉字字体,那么模型在面对各种字体时也能从容应对,给出准确的预测。

三、文字图像生成

首先是定义好输入参数,其中包括输出目录、字体目录、测试集大小、图像尺寸、图像旋转幅度等等。

def args_parse():#解析输入参数parser = argparse.ArgumentParser(description=description, formatter_class=RawTextHelpFormatter)parser.add_argument('--out_dir', dest='out_dir',default=None, required=True,help='write a caffe dir')parser.add_argument('--font_dir', dest='font_dir',default=None, required=True,help='font dir to to produce images')parser.add_argument('--test_ratio', dest='test_ratio',default=0.2, required=False,help='test dataset size')parser.add_argument('--width', dest='width',default=None, required=True,help='width')parser.add_argument('--height', dest='height',default=None, required=True,help='height')parser.add_argument('--no_crop', dest='no_crop',default=True, required=False,help='', action='store_true')parser.add_argument('--margin', dest='margin',default=0, required=False,help='', )parser.add_argument('--rotate', dest='rotate',default=0, required=False,help='max rotate degree 0-45')parser.add_argument('--rotate_step', dest='rotate_step',default=0, required=False,help='rotate step for the rotate angle')parser.add_argument('--need_aug', dest='need_aug',default=False, required=False,help='need data augmentation', action='store_true')   args = vars(parser.parse_args()) return args

接下来需要将我们第一步得到的对应表读入内存,因为这个表示ID到汉字的映射,我们在做一下转换,改成汉字到ID的映射,用于后面的字体生成。

#将汉字的label读入,得到(ID:汉字)的映射表label_dict
label_dict = get_label_dict()char_list=[]  # 汉字列表
value_list=[] # label列表
for (value,chars) in label_dict.items():print (value,chars)char_list.append(chars)value_list.append(value)# 合并成新的映射关系表:(汉字:ID)
lang_chars = dict(zip(char_list,value_list)) 
font_check = FontCheck(lang_chars) 

我们对旋转的角度存储到列表中,旋转角度的范围是[-rotate,rotate].

if rotate < 0:roate = - rotateif rotate > 0 and rotate <= 45:all_rotate_angles = []for i in range(0, rotate+1, rotate_step):  all_rotate_angles.append(i)for i in range(-rotate, 0, rotate_step):all_rotate_angles.append(i)#print(all_rotate_angles)

现在说一下字体图像是怎么生成的,首先我们使用的工具是PIL。PIL里面有很好用的汉字生成函数,我们用这个函数再结合我们提供的字体文件,就可以生成我们想要的数字化的汉字了。我们先设定好我们生成的字体颜色为黑底白色,字体尺寸由输入参数来动态设定。

# 生成字体图像
class Font2Image(object):def __init__(self,width, height,need_crop, margin):self.width = widthself.height = heightself.need_crop = need_cropself.margin = margindef do(self, font_path, char, rotate=0):find_image_bbox = FindImageBBox()# 黑色背景img = Image.new("RGB", (self.width, self.height), "black")draw = ImageDraw.Draw(img)font = ImageFont.truetype(font_path, int(self.width * 0.7),)# 白色字体draw.text((0, 0), char, (255, 255, 255),font=font)if rotate != 0:img = img.rotate(rotate)data = list(img.getdata())sum_val = 0for i_data in data:sum_val += sum(i_data)if sum_val > 2:np_img = np.asarray(data, dtype='uint8')np_img = np_img[:, 0]np_img = np_img.reshape((self.height, self.width))cropped_box = find_image_bbox.do(np_img)left, upper, right, lower = cropped_boxnp_img = np_img[upper: lower + 1, left: right + 1]if not self.need_crop:preprocess_resize_keep_ratio_fill_bg = \PreprocessResizeKeepRatioFillBG(self.width, self.height,fill_bg=False,margin=self.margin)np_img = preprocess_resize_keep_ratio_fill_bg.do(np_img)# cv2.imwrite(path_img, np_img)return np_imgelse:print("img doesn't exist.")

我们写两个循环,外层循环是汉字列表,内层循环是字体列表,对于每个汉字会得到一个image_list列表,里面存储着这个汉字的所有图像。

for (char, value) in lang_chars.items():  # 外层循环是字image_list = []print (char,value)#char_dir = os.path.join(images_dir, "%0.5d" % value)for j, verified_font_path in enumerate(verified_font_paths):    # 内层循环是字体   if rotate == 0:image = font2image.do(verified_font_path, char)image_list.append(image)else:for k in all_rotate_angles: image = font2image.do(verified_font_path, char, rotate=k)image_list.append(image)

我们将image_list中图像按照比例分为训练集和测试集存储。

   test_num = len(image_list) * test_ratiorandom.shuffle(image_list)  # 图像列表打乱count = 0for i in range(len(image_list)):img = image_list[i]#print(img.shape)if count < test_num :char_dir = os.path.join(test_images_dir, "%0.5d" % value)else:char_dir = os.path.join(train_images_dir, "%0.5d" % value)if not os.path.isdir(char_dir):os.makedirs(char_dir)path_image = os.path.join(char_dir,"%d.png" % count)cv2.imwrite(path_image,img)count += 1

写好代码后,我们执行如下指令,开始生成印刷体文字汉字集。

 python gen_printed_char.py --out_dir ./dataset --font_dir ./chinese_fonts --width 30 --height 30 --margin 4 --rotate 30 --rotate_step 1

解析一下上述指令的附属参数:

  1. --out_dir 表示生成的汉字图像的存储目录
  2. --font_dir 表示放置汉字字体文件的路径
  3. --width --height 表示生成图像的高度和宽度
  4. --margin 表示字体与边缘的间隔
  5. --rotate 表示字体旋转的范围,[-rotate,rotate]
  6. --rotate_step 表示每次旋转的间隔

生成这么一个3755个汉字的数据集的所需的时间还是很久的,估计接近一个小时。其实这个生成过程可以用多线程、多进程并行加速,但是考虑到这种文字数据集只需生成一次就好,所以就没做这方面的优化了。数据集生成完我们可以发现,在dataset文件夹下得到train和test两个文件夹,train和test文件夹下都有3755个子文件夹,分别存储着生成的3755个汉字对应的图像,每个子文件的名字就是该汉字对应的id。随便选择一个train文件夹下的一个子文件夹打开,可以看到所获得的汉字图像,一共634个。

dataset下自动生成测试集和训练集

测试集和训练集下都有3755个子文件夹,用于存储每个汉字的图像。

生成出来的汉字图像

 

 

额外的图像增强

第三步生成的汉字图像是最基本的数据集,它所做的图像处理仅有旋转这么一项,如果我们想在数据增强上再做多点东西,想必我们最终训练出来的OCR模型的性能会更加优秀。我们使用opencv来完成我们定制的汉字图像增强任务。

因为生成的图像比较小,仅仅是30*30,如果对这么小的图像加噪声或者形态学处理,得到的字体图像会很糟糕,所以我们在做数据增强时,把图片尺寸适当增加,比如设置为100×100,再进行相应的数据增强,效果会更好。

噪点增加

def add_noise(cls,img):for i in range(20): #添加点噪声temp_x = np.random.randint(0,img.shape[0])temp_y = np.random.randint(0,img.shape[1])img[temp_x][temp_y] = 255return img

适当腐蚀

def add_erode(cls,img):kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))    img = cv2.erode(img,kernel) return img

适当膨胀

def add_dilate(cls,img):kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))    img = cv2.dilate(img,kernel) return img

然后做随机扰动

def do(self,img_list=[]):aug_list= copy.deepcopy(img_list)for i in range(len(img_list)):im = img_list[i]if self.noise and random.random()<0.5:im = self.add_noise(im)if self.dilate and random.random()<0.25:im = self.add_dilate(im)if self.erode and random.random()<0.25:im = self.add_erode(im)    aug_list.append(im)return aug_list

输入指令

python gen_printed_char.py --out_dir ./dataset2 --font_dir ./chinese_fonts --width 100 --height 100 --margin 10 --rotate 30 --rotate_step 1 --need_aug

使用这种生成的图像如下图所示,第一数据集扩大了两倍,第二图像的丰富性进一步提高,效果还是明显的。当然,如果要获得最好的效果,还需要调一下里面的参数,这里就不再详细说明了。

 至此,我们所需的印刷体汉字数据集已经成功生成完毕,下一步要做的就是利用这些数据集设计一个卷积神经网络做文字识别了!

原文地址:http://www.cnblogs.com/skyfsm/p/8436820.html

 

欢迎扫码关注我的微信公众号

 

这篇关于OCR技术3-大批量生成文字训练集的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/770552

相关文章

k8s admin用户生成token方式

《k8sadmin用户生成token方式》用户使用Kubernetes1.28创建admin命名空间并部署,通过ClusterRoleBinding为jenkins用户授权集群级权限,生成并获取其t... 目录k8s admin用户生成token创建一个admin的命名空间查看k8s namespace 的

Java中的Schema校验技术与实践示例详解

《Java中的Schema校验技术与实践示例详解》本主题详细介绍了在Java环境下进行XMLSchema和JSONSchema校验的方法,包括使用JAXP、JAXB以及专门的JSON校验库等技术,本文... 目录1. XML和jsON的Schema校验概念1.1 XML和JSON校验的必要性1.2 Sche

Vue3 如何通过json配置生成查询表单

《Vue3如何通过json配置生成查询表单》本文给大家介绍Vue3如何通过json配置生成查询表单,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录功能实现背景项目代码案例功能实现背景通过vue3实现后台管理项目一定含有表格功能,通常离不开表单

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

Python从Word文档中提取图片并生成PPT的操作代码

《Python从Word文档中提取图片并生成PPT的操作代码》在日常办公场景中,我们经常需要从Word文档中提取图片,并将这些图片整理到PowerPoint幻灯片中,手动完成这一任务既耗时又容易出错,... 目录引言背景与需求解决方案概述代码解析代码核心逻辑说明总结引言在日常办公场景中,我们经常需要从 W

C#使用Spire.XLS快速生成多表格Excel文件

《C#使用Spire.XLS快速生成多表格Excel文件》在日常开发中,我们经常需要将业务数据导出为结构清晰的Excel文件,本文将手把手教你使用Spire.XLS这个强大的.NET组件,只需几行C#... 目录一、Spire.XLS核心优势清单1.1 性能碾压:从3秒到0.5秒的质变1.2 批量操作的优雅

Python中高级文本模式匹配与查找技术指南

《Python中高级文本模式匹配与查找技术指南》文本处理是编程世界的永恒主题,而模式匹配则是文本处理的基石,本文将深度剖析PythonCookbook中的核心匹配技术,并结合实际工程案例展示其应用,希... 目录引言一、基础工具:字符串方法与序列匹配二、正则表达式:模式匹配的瑞士军刀2.1 re模块核心AP

Python使用python-pptx自动化操作和生成PPT

《Python使用python-pptx自动化操作和生成PPT》这篇文章主要为大家详细介绍了如何使用python-pptx库实现PPT自动化,并提供实用的代码示例和应用场景,感兴趣的小伙伴可以跟随小编... 目录使用python-pptx操作PPT文档安装python-pptx基础概念创建新的PPT文档查看

在ASP.NET项目中如何使用C#生成二维码

《在ASP.NET项目中如何使用C#生成二维码》二维码(QRCode)已广泛应用于网址分享,支付链接等场景,本文将以ASP.NET为示例,演示如何实现输入文本/URL,生成二维码,在线显示与下载的完整... 目录创建前端页面(Index.cshtml)后端二维码生成逻辑(Index.cshtml.cs)总结

Python实现数据可视化图表生成(适合新手入门)

《Python实现数据可视化图表生成(适合新手入门)》在数据科学和数据分析的新时代,高效、直观的数据可视化工具显得尤为重要,下面:本文主要介绍Python实现数据可视化图表生成的相关资料,文中通过... 目录前言为什么需要数据可视化准备工作基本图表绘制折线图柱状图散点图使用Seaborn创建高级图表箱线图热