/pixel-anchor-link-and-text-detector-experience

结合实际项目经验谈文本检测,顺便展示一下我们只用合成数据训练的通用印刷体文本检测算法pixel-anchor-link

text-detector-experience

结合实际项目经验谈文本检测

不知不觉已经转行一年了,一年以来,一直在搞各类检测和分割的算法,主要落地的场景是文本检测。由于我们这之前的OCR都是用的传统算法, 基于mser那一套,因此基于深度学习的文本检测我算是头一个吃螃蟹的,真的是一切只能靠自己。

刚开始的时候,毫无经验,只能去刷论文,然后在github上搜一些比较热门的项目。最开始看到的是旷世的EAST还有白翔试验室的Textboxes++。在基于分割和基于anchor的算法里摸爬了两个月,用ICDAR15数据集练练手。终于把文章的结果都复现了,而且复现的结果比原论文要好。正沾沾自喜的时候,当把算法用到实际项目场景的时候,发现实际根本没法用。因为EAST和Textboxes++针对的都是多方向的英文数据集,对于长中文无能为力。刷榜和实际落地果然是两码事。CVPR上公开的论文基本上以刷ICDAR的榜为主,只能用来启发思路。但是多看看其实也是可以的,通过这些方法来练手,锻炼自己的算法能力,然后才有可能自己去完整开发一套算法框架。解决实际问题的时候,往往没有什么特别的trick,只有最基本的原理,和对算法的深刻理解,要因地制宜设计算法。

实际项目主要针对印刷体,无非两种,一种结构化的需求,一种通用的需求。两种需求需要走不同的开发路线。

结构化的需求主要针对一些单据,比如我们开发的最复杂的增值税票据,需要把每一个名称字段和内容字段分别检测出来。还有银行的一些存单,现金支票等。这些场景经常碰到的问题是,内容字段和名称字段会印重,因此需要把它们分开。传统的link方法从原理上无法解决这个问题,类似pixel-link,PSENET那些github上公开的算法都会遇到文本粘连的问题,实际应用达不到工业级的鲁棒程度。只能走直接回归的路线,通过finetune的方式过拟合特定的场景。直接回归有两种方式,一种是基于anchor的回归,一种是角点回归和匹配。两种方法我们都取得了不错的效果,并成功落地在增值税发票的文本检测当中。当然实际开发当中会碰到各种各样的问题,实际动手后碰到问题解决问题,才能最终获得满意的结果。比如基于anchor回归的方式,你会发现anchor设计非常难,而且经常碰到的情况是对于长中文文本检测到的边界框时而准时而不准。角点回归和匹配主要难点在后处理,如何鲁棒性的匹配准也需要不断尝试。

通用场景下,首先碰到的问题是,对于中文文本行,没有办法准确定义文本的边界,到底隔多少字符算做一个文本行?所以不能走直接回归的方式,link的方式应该是主流方法。但是直接link的话也不行,像pixel-link和PSENet这种算法,对于小文本基本就看不见了,除非把图像放得很大,但是放得很大成本又太高。而且像素的link最大的问题在于容易受背景干扰,不够鲁棒,其次还有就是容易把紧密的文本粘连起来,实际跑过这些算法的同学应该知道有多痛苦。其实要想做到鲁棒而且泛化能力强的话,最好把问题简单化。大部分应用场景文本只有一个主方向,因此加一个方向矫正模块,把问题简化成一个一维问题,类似于CTPN的方式。CTPN还可以勉强用用,但是速度太慢。强烈推荐一下我们自己开发的pixel-anchor-link算法,只用合成数据训练就能获得极强的泛化能力,详见展示图片。学习最简单的特征,其泛化能力就会很好。pixel方法容易受背景干扰,anchor方法泛化能力不强,两者有机结合,具有超强的泛化能力和抗干扰能力,根本用不着ctpn这种加lstm的操作,lstm很慢。讽刺的是,这种实用的方法根本发不了顶会论文,因为一方面公司不会发实用的方法出去,另一方面学术圈的怪象发论文先benchmark刷刷榜。刚入行的同学最容易犯的一个错误是:刷无数的论文-->复现-->没用-->继续刷论文,还是不要迷信CVPR这些顶会,解决实际问题,追求工业级的鲁棒性才是王道。

有些细节不方便细说,只能帮大家到这了。愿你不要像我一样趟这么多坑,不过趟坑使人成长,内功最重要,把握分类和回归两个核心,针对实际场景解决实际问题,有时候越简单越好,算法保佑你。