[iOS9]CITextFeatureで文字領域検出+TesseractOCRiOSで文字認識してみた
概要
- 画像内のテキスト位置を検出してみる
- フリーのライブラリでOCRにかけてみる
結論から言うと、まだ手放しには使えなそうかなーと。
CITextFeatureについて
iOSにはCoreImageという画像をあれこれするためのFrameworkがあって、
その中にCIDetectorという、画像内の顔検出などができる機能がありました。
iOS9において、これに画像内のテキスト位置を検出する機能が付加されています。
実装
文字領域を取得する場合、CIDetectorを以下のように初期化します。
CIDetector *ciDetector = [CIDetector detectorOfType:CIDetectorTypeText
context:nil
options:nil];
各領域(feature)は、以下のようにArrayに取得します。
// optionsにCIDetectorReturnSubFeaturesを設定することでsubfeatureが取得できる
NSArray *features = [ciDetector featuresInImage:ciImage
options:@{CIDetectorReturnSubFeatures: @YES}];
CITextFeatureは認識した文字の矩形情報を含んでいますが、
さらにその矩形内の子となる文字の矩形情報を含んでいます。
要は、1文字単位の情報もまとめて取得してくれるということです。
この子要素の情報は、subFeatureというpropertyからアクセスすることができます。
これらを使って、文字領域の矩形を囲むよう線を引くコードです。
- (UIImage *) detectText:(UIImage *)inputImage {
CIImage *ciImage = [CIImage imageWithCGImage:inputImage.CGImage];
CIDetector *ciDetector = [CIDetector detectorOfType:CIDetectorTypeText
context:nil
options:nil];
NSArray *features = [ciDetector featuresInImage:ciImage
options:@{CIDetectorReturnSubFeatures: @YES}];
UIGraphicsBeginImageContextWithOptions(inputImage.size, NO, 0.0);
[inputImage drawInRect:CGRectMake(0, 0, inputImage.size.width, inputImage.size.height)];
for (CITextFeature *feature in features) {
CGContextRef drawContext = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(drawContext, 3.f);
// Y座標が逆になるので変換
CGRect textRect = feature.bounds;
textRect.origin.y = inputImage.size.height - (textRect.origin.y + textRect.size.height);
// 線でテキストを囲む
CGContextSetStrokeColorWithColor(drawContext, [UIColor blueColor].CGColor);
CGContextStrokeRect(drawContext,textRect);
// subfeatureのチェック
CGContextSetStrokeColorWithColor(drawContext, [UIColor greenColor].CGColor);
for (CITextFeature *subfeature in feature.subFeatures) {
CGRect subTextRect = subfeature.bounds;
subTextRect.origin.y = inputImage.size.height - (subTextRect.origin.y + subTextRect.size.height);
CGContextStrokeRect(drawContext,subTextRect);
}
}
UIImage *drawedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return drawedImage;
}
さっそくやってみる
画像はKeynoteで適当に作りました。横幅640pxです。
結果
青枠が、UITextFeatureに検出された文字領域。
赤枠が、その検出された文字領域が含む子要素です。
ちょっと微妙な結果になりました。
- あかさたなが取れていない
- 文章によって縦幅が変わっている
- subfeatureの誤認識が多い
( ˘ω˘)うーん…
取れている部分は割と綺麗に矩形が取れていますね。
ひらがなは文字中に隙間が多いので向いていないのかも…?
TesseractOCRiOSで文字を読み取ってみる
折角なので文字認識まで。
目標として、CITextFeatureで取得した領域に絞ってOCRスキャンをかけると
どうなるのかな?と思ったので試してみました。(下記参考にさせて頂きました)
【Swift】文字認識ライブラリ、TesseractOCR for iOSを試してみた
PodsでTesseractOCRiOSを追加してください。
Objective-Cだとこんな感じ。(スキャンに地味に数秒かかります)
- (void) analyze:(UIImage *)image {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
G8Tesseract *tesseract = [[G8Tesseract alloc] initWithLanguage:@"jpn"];
tesseract.delegate = self;
tesseract.image = image;
if ([tesseract recognize]){
NSLog(@"text : %@", tesseract.recognizedText);
}
});
}
認識させてみた
まずは画像全体をスキャンした結果。
あかさたな はまやらわ
える しっているか
しにがみは りんごしか たベない
綺麗に認識できています。
次に、CIDetectorから取得できた文字領域を対象にスキャンを行います。
今回は、上の方で取得できていた青い矩形の領域3つに対し処理を行いました。
...
CGImageRef srcImageRef = inputImage.CGImage;
CGImageRef trimmedImageRef = CGImageCreateWithImageInRect(srcImageRef, textRect);
UIImage *trimmedImage = [UIImage imageWithCGImage:trimmedImageRef];
[self analyze:trimmedImage];
...
以下、その結果です。
はまやらわ
える しつているか
し にがみは り ん ご しか たベない
- 小文字が大文字になってしまっている
- 3行目の区切りが多い
(ヽ´ω`)うーーん……
領域をせばめたせいで、文字内の隙間がよくない感じに認識されているような。
あかさたなはCIDetectorの時点で省かれてしまっていますし微妙ですね。
まとめ
なんだか結果としては微妙でした。サンプルの文字列が悪かったのかも知れません。
コントラストを上げて文字をはっきりさせたり、
画像の解像度を上げるなどで改善の可能性はあるかと思います。
OCRの速度によっては、指定の文字の領域は塗りつぶしてしまって伏せ字に…とかできないかなあと思いました。
Author And Source
この問題について([iOS9]CITextFeatureで文字領域検出+TesseractOCRiOSで文字認識してみた), 我々は、より多くの情報をここで見つけました https://qiita.com/kaway/items/f496ea4edbd0658a149f著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .