業(yè)務(wù)需求
通過用戶的股票App中的自選股截圖,使用OCR來識(shí)別圖中的股票名字和股票編碼。通過這樣的方式,讓用戶方便地遷移他的自選股。而且我們希望做到離線的識(shí)別。
通過選型,我們最后選擇了tesseract。它是一款開源的OCR;更重要的是它在移動(dòng)端有現(xiàn)成的輪子:Tesseract-OCR-iOS和tess-two。
優(yōu)化
提升速度
使用了chi_sim+eng兩個(gè)訓(xùn)練集來識(shí)別,發(fā)現(xiàn)識(shí)別速度不夠快。怎么樣優(yōu)化呢?tesseract利用了機(jī)器學(xué)習(xí),機(jī)器學(xué)習(xí)這個(gè)方式是擬人的。我們就想到了如果是人的話,會(huì)怎么辦?
我們發(fā)現(xiàn),絕大多數(shù)(幾乎所有)國內(nèi)股票App自選股名字和代碼都在左側(cè),而且大多數(shù)都是這樣的布局:status-bar navigation-bar tab-bar。所以優(yōu)化方案呼之欲出。那就是減少識(shí)別區(qū)域,加快了識(shí)別速度。具體就是在橫向,只識(shí)別從最左側(cè)到中線??v向,去掉3個(gè)bar的高度和位置。和人一樣,人在看到自選股的時(shí)候,他所關(guān)心的是股票代碼和名字,自然而然他會(huì)把視線集中在左側(cè),加快識(shí)別速度和準(zhǔn)確率。
這樣做不僅加快了速度,也提高了準(zhǔn)確率,對(duì)于tesseract干擾更少了。因?yàn)楦蓴_更少了,所以速度提升超過了50%這個(gè)我們當(dāng)初的猜想。優(yōu)化速度到達(dá)65%。
提升識(shí)別能力
我們發(fā)現(xiàn)國內(nèi)股票App場上的色系風(fēng)格都很雷同,但這樣就導(dǎo)致了一個(gè)問題,識(shí)別率不高,甚至識(shí)別不出。所以我們通過濾鏡的方式,增強(qiáng)對(duì)比度,做到一個(gè)黑底白字來提供高識(shí)別能力。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;
}
訓(xùn)練集大小問題
訓(xùn)練集大小問題是個(gè)頭疼的問題。eng+chi_sim加起來有80M,壓縮后也有44M。這個(gè)大小進(jìn)入到App是不可以接受的。那怎么辦呢?兩個(gè)方案:1.在線下載/使用時(shí)下載。2.自己制作訓(xùn)練集。
我們選擇2.
實(shí)際上常用漢子有2500個(gè)字,還包含了各種字體。但3000只股票用到的漢子肯定不到2500個(gè)字。粗略估計(jì)在800個(gè)字左右。這樣就可以減少3分之2大小。另外,目標(biāo)App所使用的字體也是一個(gè)有限集,例如iOS上基本上都是蘋方。蘋方雖然也有中黑,標(biāo)準(zhǔn)等字體,但實(shí)際上只要一種就可以把其他的也識(shí)別出來。所以減少的包大小是很可觀的。
如何制作訓(xùn)練集
參考這篇。我也自己額外寫了一個(gè)簡單的shell腳步。
創(chuàng)建一個(gè)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.