使用tesseract在移动端上做OCR的一些小优化

业务需求

通过用户的股票App中的自选股截图,使用OCR来识别图中的股票名字和股票编码。通过这样的方式,让用户方便地迁移他的自选股。而且我们希望做到离线的识别。

通过选型,我们最后选择了tesseract。它是一款开源的OCR;更重要的是它在移动端有现成的轮子:Tesseract-OCR-iOS和tess-two。

优化

提升速度

使用了chi_sim+eng两个训练集来识别,发现识别速度不够快。怎么样优化呢?tesseract利用了机器学习,机器学习这个方式是拟人的。我们就想到了如果是人的话,会怎么办?

我们发现,绝大多数(几乎所有)国内股票App自选股名字和代码都在左侧,而且大多数都是这样的布局:status-bar navigation-bar tab-bar。所以优化方案呼之欲出。那就是减少识别区域,加快了识别速度。具体就是在横向,只识别从最左侧到中线。纵向,去掉3个bar的高度和位置。和人一样,人在看到自选股的时候,他所关心的是股票代码和名字,自然而然他会把视线集中在左侧,加快识别速度和准确率。

这样做不仅加快了速度,也提高了准确率,对于tesseract干扰更少了。因为干扰更少了,所以速度提升超过了50%这个我们当初的猜想。优化速度到达65%。

提升识别能力

我们发现国内股票App场上的色系风格都很雷同,但这样就导致了一个问题,识别率不高,甚至识别不出。所以我们通过滤镜的方式,增强对比度,做到一个黑底白字来提供高识别能力。iOS上具体的代码:

- (UIImage *)g8_blackAndWhite
{
    CIImage *beginImage = [CIImage imageWithCGImage:self.CGImage];

    CIImage *blackAndWhite = [CIFilter filterWithName:@"CIColorControls" keysAndValues:kCIInputImageKey, beginImage, @"inputBrightness", @0.0, @"inputContrast", @1.1, @"inputSaturation", @0.0, nil].outputImage;
    CIImage *output = [CIFilter filterWithName:@"CIExposureAdjust" keysAndValues:kCIInputImageKey, blackAndWhite, @"inputEV", @0.7, nil].outputImage;
    
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef cgiimage = [context createCGImage:output fromRect:output.extent];
    UIImage *newImage = [UIImage imageWithCGImage:cgiimage scale:0 orientation:self.imageOrientation];
    
    CGImageRelease(cgiimage);
    return newImage;
}

训练集大小问题

训练集大小问题是个头疼的问题。eng+chi_sim加起来有80M,压缩后也有44M。这个大小进入到App是不可以接受的。那怎么办呢?两个方案:1.在线下载/使用时下载。2.自己制作训练集。

我们选择2.

实际上常用汉子有2500个字,还包含了各种字体。但3000只股票用到的汉子肯定不到2500个字。粗略估计在800个字左右。这样就可以减少3分之2大小。另外,目标App所使用的字体也是一个有限集,例如iOS上基本上都是苹方。苹方虽然也有中黑,标准等字体,但实际上只要一种就可以把其他的也识别出来。所以减少的包大小是很可观的。

如何制作训练集

参考这篇。我也自己额外写了一个简单的shell脚步。

创建一个chi_$FontName.$FontName.exp0.tif的tif就可以。

FontName=$1

NeedEng=$2

LAN = 'chi_sim'
if [ NeedEng ]; then
    LAN = 'chi_sim+eng'
fi

tesseract chi_$FontName.$FontName.exp0.tif chi_$FontName.$FontName.exp0 -l $LAN batch.nochop makebox
echo '修改完box后按回车'
read
unicharset_extractor chi_$FontName.$FontName.exp0.box
tesseract chi_pfzh.pfzh.exp0.tif chi_pfzh.pfzh.exp0 -l $LAN nobatch box.train
echo pfzh 0 0 0 0 0 >font_properties
mftraining -F font_properties -U unicharset -O chi_$FontName.unicharset chi_$FontName.$FontName.exp0.tr
cntraining chi_$FontName.$FontName.exp0.tr

mv inttemp chi_$FontName.inttemp
mv pffmtable chi_$FontName.pffmtable
mv normproto chi_$FontName.normproto
mv shapetable chi_$FontName.shapetable

combine_tessdata chi_$FontName.

你可能感兴趣的:(使用tesseract在移动端上做OCR的一些小优化)