分享

OCR(光学字符识别)的简单解析与使用(内含 Demo)

 AI科技馆 2018-07-27

2015年12月23日 17:18:52

公司前些日子准备在项目中使用 光学字符识别技术,

(也就是我们经常听说的,你拿着相机,照一下,之后就能直接显示图片中的文字是什么)

之后我在 GIT 上找了一个歪果友仁的 Demo, 对他的项目进行简单地解析,以此来帮助其他小伙伴,简单的了解一下.




Demo: https://github.com/hatena-iti/tesseract-sample



注意:  下面开启唐僧模式,对 OCR 已经有一定了解或只是想使用的同学可以直接跳到代码部分..


首先来介绍一下 OCR 到底是什么.

OCR是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,

通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程.


其中 通过检测暗、亮的模式确定其形状   在我们的开发中,就涉及到图片的二值化等一系列操作,设计 OPEN_CV或 OPEN_GL等.

ps:图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果.

例如这样:

而经过二值化处理的图片,

是不是觉得很像复印的照片呢.233...



了解了图片的基本原理,接下来就到了介绍工具的部分.


我们程序中最重要的第三方库  TesseractOCR.framework


工具下载地址:

TesseractOCR.framework: https://github.com/gali8/Tesseract-OCR-iOS


  1. <span style="font-size:18px;">@interface Tesseract : NSObject
  2. + (NSString *)version;

  3. @property (nonatomic, strong) NSString* language;

  4. @property (nonatomic, strong) UIImage *image;
  5. @property (nonatomic, assign) CGRect rect;

  6. @property (nonatomic, readonly) short progress; // from 0 to 100
  7. @property (nonatomic, readonly) NSString *recognizedText;

  8. @property (nonatomic, weak) id<TesseractDelegate> delegate;</span>

它的代理方法如下

  1. <span style="font-size:18px;">- (id)initWithDataPath:(NSString *)dataPath language:(NSString *)language DEPRECATED_ATTRIBUTE;
  2. - (id)initWithLanguage:(NSString*)language;
  3. - (void)setVariableValue:(NSString *)value forKey:(NSString *)key;

  4. - (BOOL)recognize;
  5. - (void)clear DEPRECATED_ATTRIBUTE;</span>

我们在使用当中需要传递给 TesseractOCR 我们需要解析的语言,我们需要解析的图片,并告诉程序,我们是否承认.


需要注意的是,TesseractOCR默认支持英文和数字,毕竟人家才26个字母外加0-9这几个数字,

如果需要识别额外的语言,则需要在 tessdata 文件下 添加对应的语言包.



磨叽了一大堆,下面开始代码部分..

首先在 StroyBoard 中 创建我们需要的图像展示区和文字展示区.


之后将其拉入 ViewController.h 中 作为属性.

  1. <span style="font-size:18px;">#import <UIKit/UIKit.h>
  2. #import <TesseractOCR/TesseractOCR.h>

  3. @interface ViewController : UIViewController<TesseractDelegate>

  4. @property (nonatomic, strong) IBOutlet UIImageView *imageView;
  5. @property (nonatomic, strong) IBOutlet UILabel *label;

  6. @end</span>

之后在.m 文件中,也同样创建属性方便我们之后的使用.

  1. <span style="font-size:18px;">// kImageFileName の値を @"ocr-sample-japanese"(日本語文字サンプル)に指定した場合は、
  2. // kLanguage の値を @"jpn" に指定します。
  3. // kImageFileName == @"ocr-sample-english" の場合は、kLanguage = @"eng" とします。)

  4. //static NSString * const kImageFileName = @"ocr-sample-japanese"; // 日本語文字サンプル
  5. //static NSString * const kImageFileName = @"ocr-sample-english"; // 英数字サンプル
  6. static NSString * const kImageFileName = @"ocr-sample-chinese"; // 汉文サンプル

  7. //static NSString * const kLanguage = @"jpn"; <span style="white-space:pre"> </span> // 解析対象言語:日本語
  8. //static NSString * const kLanguage = @"eng"; <span style="white-space:pre"> </span> // 解析対象言語:英語
  9. static NSString * const kLanguage = @"chi_sim"; <span style="white-space:pre"> </span> // 解析対象言語:中文</span>


同时再去声明一个属性

  1. <span style="font-size:18px;">@implementation ViewController {
  2. // 文字解析用に加工したイメージデータを保持するフィールド
  3. UIImage *adjustedImage_;
  4. }</span>


之后

  1. <span style="font-size:18px;">//@synthesize是在m文件中定义setter和getter方法的实现
  2. @synthesize imageView=imageView_;
  3. @synthesize label=label_;</span>


至此前期准备工作已经结束.

接下来到程序的运行阶段.

  1. <span style="font-size:18px;">- (void)viewDidLoad {
  2. [super viewDidLoad];

  3. // 文字解析対象の画像を表示する
  4. self.imageView.image = [UIImage imageNamed:kImageFileName];

  5. // 文字解析を実行する
  6. [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

  7. [self analyze];
  8. }</span>


记得

  1. <span style="font-size:18px;">- (void)dealloc {
  2. [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  3. }</span>


之后重头戏来了,首先我们需要对我们的图片进行简单的处理,加强黑白色的对比,以此增强我们文字的轮廓的清晰度,

文字的清晰度对文字的检测的成功率有很大的影响.

对图片进行了简单的处理之后,我们就将我们处理之后的图片传入我们的第三方库.并将识别出的文字返回,展示给我们.

代理方法可以展示我们对当前图片的解析程度达到了多少.

  1. <span style="font-size:18px;">// 文字解析を実行する
  2. - (void)analyze {
  3. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{

  4. CIImage *ciImage = [[CIImage alloc] initWithImage:self.imageView.image];

  5. //文字を読みやすくするため、白黒にして、コントラストを強めに、また輪郭をくっきりさせるよう設定する
  6. CIFilter *ciFilter =
  7. [CIFilter filterWithName:@"CIColorMonochrome"
  8. keysAndValues:kCIInputImageKey, ciImage,
  9. @"inputColor", [CIColor colorWithRed:0.75 green:0.75 blue:0.75],
  10. @"inputIntensity", [NSNumber numberWithFloat:1.0],
  11. nil];
  12. ciFilter =
  13. [CIFilter filterWithName:@"CIColorControls"
  14. keysAndValues:kCIInputImageKey, [ciFilter outputImage],
  15. @"inputSaturation", [NSNumber numberWithFloat:0.0],
  16. @"inputBrightness", [NSNumber numberWithFloat:-1.0],
  17. @"inputContrast", [NSNumber numberWithFloat:4.0],
  18. nil];

  19. ciFilter =
  20. [CIFilter filterWithName:@"CIUnsharpMask"
  21. keysAndValues:kCIInputImageKey, [ciFilter outputImage],
  22. @"inputRadius", [NSNumber numberWithFloat:2.5],
  23. @"inputIntensity", [NSNumber numberWithFloat:0.5],
  24. nil];

  25. CIContext *ciContext = [CIContext contextWithOptions:nil];
  26. CGImageRef cgImage =
  27. [ciContext createCGImage:[ciFilter outputImage] fromRect:[[ciFilter outputImage] extent]];

  28. // 文字解析対象の画像の色、コントラストを調整したものを変数に保存する
  29. UIImage *adjustedImage = [UIImage imageWithCGImage:cgImage];
  30. CGImageRelease(cgImage);
  31. //----------------------------------------------------------------------------------------------
  32. Tesseract* tesseract = [[Tesseract alloc] initWithLanguage:kLanguage];
  33. tesseract.delegate = self;
  34. [tesseract setImage:adjustedImage]; //image to check
  35. [tesseract recognize];
  36. NSString *recognizedText = [tesseract recognizedText];
  37. tesseract = nil; //deallocate and free all memory

  38. dispatch_async(dispatch_get_main_queue(), ^{
  39. // 解析結果を画面に表示する
  40. self.label.text = recognizedText;
  41. NSLog(@"\n\n%@",recognizedText);
  42. [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
  43. });
  44. });
  45. }
  46. </span>

代理方法(可用作展示解析程度).

  1. <span style="font-size:18px;">#pragma mark - TesseractDelegate methods

  2. - (BOOL)shouldCancelImageRecognitionForTesseract:(Tesseract*)tesseract {
  3. NSLog(@"progress: %d", tesseract.progress);
  4. return NO; // return YES, if you need to interrupt tesseract before it finishes
  5. }</span>

最后效果:




完结撒花!~


更多精彩文章,尽在我的公众号.




    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多