PPBlinkOCR 5.0.0

PPBlinkOCR 5.0.0

测试已测试
Lang语言 Obj-CObjective C
许可证 Apache-2.0
发布最新发布Apr 2021

Dominik CubelicJurica CerovecJurica CerovecDino GustinJura SkrlecMijo Gracanin 维护。



  • MicroBlink、Jurica Cerovec 和 Jura Skrlec

MicroBlink

Build Status Pod Version

BlinkInput SDK for real time text recognition

BlinkInput SDK 是一种针对移动设备的先进 OCR 模块。它的 OCR 技术专门针对移动设备和架构进行优化,这使得它比一般的基于桌面的 OCR 软件具有更快速的结果和更低的错误率。BlinkInput 功能:

  • 集成相机管理
  • 集成针对 IBAN、价格、电子邮件地址、URL 等字段进行 文本解析 的功能!
  • 分层 API,允许从简单的集成到复杂的 UX 定制。
  • 轻量级,无需互联网连接
  • 企业级安全标准
  • 支持条形码扫描

BlinkInput 是由 MicroBlink 开发的一系列 SDK 之一,用于光学文本识别、条形码扫描、身份证明文件扫描等。

BlinkInput 为 PhotoMath app 提供动力,其中它在实时中用于 识别数学表达式

目录

要求

SDK包包含Microblink框架和一个或多个示例应用程序,演示了框架集成。该框架可在iOS 8.0或更高版本、iPhone 4S或更新型号及iPad 2或更新型号上部署。

当从摄像头获取的图像聚焦时,SDK的性能表现显著。因此,iPad 2和iPod Touch 4th gen设备(没有自动对焦摄像头)的SDK性能可能会较低。

快速入门

开始使用BlinkInput SDK

本快速入门指南将帮助您尽快开始进行OCR扫描。本指南中描述的所有步骤都是集成所必需的。

本指南设置了基本的原始OCR解析和价格解析。它紧密遵循BlinkOCR样本应用程序。我们强烈建议您尝试运行样本应用程序。样本应用程序应在您的设备和iOS模拟器上编译和运行。

样本应用程序的源代码可以在集成过程中用作参考。

1. 初始集成步骤

使用 CocoaPods

  • 如果您想使用版本 v1.2.0 或更高版本,您需要通过运行以下命令安装 Git Large File Storage
brew install git-lfs
git lfs install
  • 务必在安装 Git LFS 之后重新启动您的控制台

  • 应通过 CocoaPods 管理的项目依赖项在名为 Podfile 的文件中指定。在您的 Xcode 项目文件(.xcodeproj)相同的目录中创建此文件。

  • 将以下行复制并粘贴到 TextEdit 窗口

platform :ios, '9.0'
pod 'PPBlinkOCR', '~> 4.0.0'
  • 在项目中安装依赖项
$ pod install
  • 从现在开始,在构建项目时,请务必总是打开生成的 Xcode 工作空间(.xcworkspace)而不是项目文件
open <YourProjectName>.xcworkspace

不使用 CocoaPods 进行集成

-下载最新版本(下载以 BlinkID 开头的 .zip 或 .tar.gz 文件。不要下载源代码,因为 GitHub 并不完全支持 Git LFS)

克隆此 git 仓库

  • 如果您想克隆版本 v1.4.0 或更高版本,您需要通过运行以下命令安装 Git Large File Storage
brew install git-lfs
git lfs install
  • 务必在安装 Git LFS 之后重新启动您的控制台

  • 克隆时,运行以下 shell 命令

git clone [email protected]:blinkinput/blinkinput-ios.git
  • 将 MicroBlink.framework 和 MicroBlink.bundle 复制到您的项目文件夹。

  • 在您的 Xcode 项目中,打开项目导航器。将 MicroBlink.framework 和 MicroBlink.bundle 文件拖放到项目中,最好放在 Frameworks 组中,与您正在使用的其他框架一起。在提示时,选择“创建组”,而不是“创建文件夹引用”选项。

Adding MicroBlink.embeddedframework to your project

  • 由于 MicroBlink.framework 是动态框架,您还需要将其添加到目标的“常规”设置中的嵌入二进制段。

Adding MicroBlink.framework to embedded binaries

  • 在您的目标设置中的“链接的框架和库”部分包含额外的框架和库。

    • AudioToolbox.framework
    • AVFoundation.framework
    • CoreMedia.framework
    • libc++.tbd
    • libiconv.tbd
    • libz.tbd

Adding Apple frameworks to your project

2. 引用头文件

在您想使用扫描功能的应用文件中放置导入指令。

Swift

import MicroBlink

Objective-C

#import <MicroBlink/MicroBlink.h>

3. 启动扫描过程

要启动扫描过程,首先决定你想要在应用中的哪个位置添加扫描功能。通常,扫描库的用户有一个按钮,当点击时,会启动扫描过程。然后在这个按钮的触摸处理程序中放置初始化代码。以下是我们列出的初始化代码,它在触摸处理程序方法中的样子。

此外,为了初始化的目的,发起扫描的 ViewController 有 MBRawParserMBParserGroupProcessorMBBlinkInputRecognizer 的私有属性,因此我们知道如何获取结果。

class ViewController: UIViewController, MBBarcodeOverlayViewControllerDelegate  {
    
    var rawParser: MBRawParser?
    var parserGroupProcessor: MBParserGroupProcessor?
    var blinkInputRecognizer: MBBlinkInputRecognizer?

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func didTapScan(_ sender: AnyObject) {
        
        let settings = MBBarcodeOverlaySettings()
        rawParser = MBRawParser()
        parserGroupProcessor = MBParserGroupProcessor(parsers: [rawParser!])
        blinkInputRecognizer = MBBlinkInputRecognizer(processors: [parserGroupProcessor!])
        
        let recognizerList = [self.blinkInputRecognizer!]
        let recognizerCollection : MBRecognizerCollection = MBRecognizerCollection(recognizers: recognizerList)
        
        /** Create your overlay view controller */
        let barcodeOverlayViewController : MBBarcodeOverlayViewController = MBBarcodeOverlayViewController(settings: settings, recognizerCollection: recognizerCollection, delegate: self)
        
        /** Create recognizer view controller with wanted overlay view controller */
        let recognizerRunneViewController : UIViewController = MBViewControllerFactory.recognizerRunnerViewController(withOverlayViewController: barcodeOverlayViewController)
        
        /** Present the recognizer runner view controller. You can use other presentation methods as well (instead of presentViewController) */
        present(recognizerRunnerViewController!, animated: true, completion: nil)
    }
}
@interface ViewController () <MBBarcodeOverlayViewControllerDelegate>

@property (nonatomic, strong) MBRawParser *rawParser;
@property (nonatomic, strong) MBParserGroupProcessor *parserGroupProcessor;
@property (nonatomic, strong) MBBlinkInputRecognizer *blinkInputRecognizer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}


- (IBAction)didTapScan:(id)sender {
    
    MBBarcodeOverlaySettings* settings = [[MBBarcodeOverlaySettings alloc] init];

    self.rawParser = [[MBRawParser alloc] init];
    self.parserGroupProcessor = [[MBParserGroupProcessor alloc] initWithParsers:@[self.rawParser]];
    self.blinkInputRecognizer = [[MBBlinkInputRecognizer alloc] initWithProcessors:@[self.parserGroupProcessor]];

    /** Create recognizer collection */
    MBRecognizerCollection *recognizerCollection = [[MBRecognizerCollection alloc] initWithRecognizers:@[self.blinkInputRecognizer]];
    
    MBBarcodeOverlayViewController *overlayVC = [[MBBarcodeOverlayViewController alloc] initWithSettings:settings recognizerCollection:recognizerCollection delegate:self];
    UIViewController<MBRecognizerRunnerViewController>* recognizerRunnerViewController = [MBViewControllerFactory recognizerRunnerViewControllerWithOverlayViewController:overlayVC];
    
    /** Present the recognizer runner view controller. You can use other presentation methods as well (instead of presentViewController) */
    [self presentViewController:recognizerRunnerViewController animated:YES completion:nil];

}

@end

4. 为扫描事件注册

在前一步中,您实例化了 MBBarcodeOverlayViewController 对象,并带有一个委托对象。该对象会在扫描生命周期中的某些事件上收到通知。在这个例子中,我们将其设置为 self。委托必须实施的协议是 MBBarcodeOverlayViewControllerDelegate 协议。遵守该协议是必要的。我们将在高级集成部分中进一步讨论协议。您可以使用以下协议的默认实现来开始。

func barcodeOverlayViewControllerDidFinishScanning(_ barcodeOverlayViewController: MBBarcodeOverlayViewController, state: MBRecognizerResultState) {

    // this is done on background thread
    // check for valid state
    if state == MBRecognizerResultState.valid {

        // first, pause scanning until we process all the results
        barcodeOverlayViewController.recognizerRunnerViewController?.pauseScanning()

        DispatchQueue.main.async(execute: {() -> Void in
            // All UI interaction needs to be done on main thread
        })
    }
}

func barcodeOverlayViewControllerDidTapClose(_ barcodeOverlayViewController: MBBarcodeOverlayViewController) {
    // Your action on cancel 
}
- (void)barcodeOverlayViewControllerDidFinishScanning:(MBBarcodeOverlayViewController *)barcodeOverlayViewController state:(MBRecognizerResultState)state {
    
    // this is done on background thread
    // check for valid state
    if (state == MBRecognizerResultStateValid) {
        
        // first, pause scanning until we process all the results
        [barcodeOverlayViewController.recognizerRunnerViewController pauseScanning];
        
        dispatch_async(dispatch_get_main_queue(), ^{
            // All UI interaction needs to be done on main thread
        });
    }
}

- (void)barcodeOverlayViewControllerDidTapClose:(MBBarcodeOverlayViewController *)barcodeOverlayViewController {
    // Your action on cancel 
}

高级 BlinkInput 集成说明

本部分包含 BlinkInput 集成的更多高级细节。

  1. 第一部分 将涵盖使用 SDK 提供的 UI 时的可能定制。
  2. 第二部分 将描述如何将 MBRecognizerRunnerViewController 的委托 嵌入您的 UIViewController,目标是创建一个定制的扫描 UI,同时仍然使用 SDK 的相机管理功能。
  3. 第三部分 将描述如何使用 MBRecognizerRunner(直接 API)从 UIImage 直接进行识别,而无需相机,或者从通过自定义相机管理获得的相机帧中进行识别。
  4. 第四部分 将描述识别器概念和可用的识别器。

内置的 MBOverlayViewControllersMBOverlaySubviews 的 UI 定制

内置覆盖视图控制器和覆盖子视图

在 BlinkInput SDK 中,有几个内置的覆盖视图控制器和扫描子视图覆盖,您可以用来执行扫描。

MBBarcodeOverlayViewController

MBBarcodeOverlayViewController 是最适合进行各种条形码扫描的覆盖视图控制器。它有一个 MBBarcodeOverlayViewControllerDelegate 代理,可以直接用来使用默认 UI 执行扫描。

使用 MBBarcodeOverlayViewController

MBBarcodeOverlayViewController 是一个内置的覆盖视图控制器,非常适合用于扫描各种条形码。如您在 快速入门 中所见,MBBarcodeOverlayViewControllerMBBarcodeOverlaySettings。以下是如何使用和初始化 MBBarcodeOverlayViewController 的示例

Swift

/** Create your overlay view controller */
let barcodeOverlayViewController : MBBarcodeOverlayViewController = MBBarcodeOverlayViewController(settings: barcodeSettings, recognizerCollection: recognizerCollection, delegate: self)

/** Create recognizer view controller with wanted overlay view controller */
let recognizerRunneViewController : UIViewController = MBViewControllerFactory.recognizerRunnerViewController(withOverlayViewController: barcodeOverlayViewController)

/** Present the recognizer runner view controller. You can use other presentation methods as well (instead of presentViewController) */
self.present(recognizerRunneViewController, animated: true, completion: nil)

Objective-C

MBBarcodeOverlayViewController *overlayVC = [[MBBarcodeOverlayViewController alloc] initWithSettings:settings recognizerCollection: recognizerCollection delegate:self];
UIViewController<MBRecognizerRunnerViewController>* recognizerRunnerViewController = [MBViewControllerFactory recognizerRunnerViewControllerWithOverlayViewController:overlayVC];

/** Present the recognizer runner view controller. You can use other presentation methods as well (instead of presentViewController) */
[self presentViewController:recognizerRunnerViewController animated:YES completion:nil];

如您所见,初始化 MBBarcodeOverlayViewController 时,我们将代理属性设置为 self。要获取结果,我们需要遵循 MBBarcodeOverlayViewControllerDelegate 协议。

自定义叠加视图控制器

请检查我们的pdf417-sample-Swift以获取叠加视图控制器的自定义实现。

叠加视图控制器是一个抽象类,用于所有叠加视图。

它的责任是提供有意义且实用的用户界面供用户互动。

需要允许用户执行的一些典型操作包括

  • 直观和有意义的方式来引导用户完成扫描过程。这通常通过在用户需要放置被扫描物体时展示“视窗”实现
  • 一种取消扫描的方式,通常使用“取消”或“后退”按钮
  • 一种按键来打开和关闭灯光(即“手电筒”)的方式

BlinkInput SDK一直为每个具体使用情况提供它自己的默认叠加视图控制器实现。您的实现应尽可能模仿默认实现,因为它是经过与最终用户彻底测试的结果。它还与底层扫描技术紧密匹配。

例如,扫描技术通常是用户将设备的相机以预期的方式放置在被扫描物体上方后非常快地给出结果。这意味着扫描进度条对用户并不特别有用。用户的大部分时间都花在正确放置设备的相机上。这只是举例说明默认相机叠加视图背后的深思熟虑和决策。

1. 初始化

要使用您自定义的叠加视图与MicroBlink的相机视图,您必须首先子类化 MBCustomOverlayViewController 并实现符合所需协议的叠加行为。

2. 协议

有五个 MBRecognizerRunnerViewController 协议和一个叠加协议 MBOverlayViewControllerInterface

五个 RecognizerRunnerView 协议包括

viewDidLoad 中,可以完成其他协议的确认,这些确认是在 MBOverlayViewControllerrecognizerRunnerViewController 属性上进行的,例如

Swift和Objective-C

self.scanningRecognizerRunnerViewControllerDelegate = self;

3. 叠加视图

开发者需要知道哪些子视图用于自定义视图控制器。如果您想使用内置实现,我们建议使用 MBModernViewfinderOverlaySubview。可以在 viewDidLoad 方法中将其初始化。

Swift

viewfinderSubview = MBModernViewfinderOverlaySubview()
viewfinderSubview.moveable = true
view.addSubview(viewfinderSubview)

Objective-C

self.viewfinderSubview = [[MBModernViewfinderOverlaySubview alloc] init];
self.viewfinderSubview.delegate = self.overlaySubviewsDelegate;
self.viewfinderSubview.moveable = YES;
[self.view addSubview:self.viewfinderSubview];

4. 初始化

在《快速入门》指南中,展示了如何使用 MBBarcodeOverlayViewController。现在,您可以替换 MBBarcodeOverlayViewControllerCustomOverlayViewController

Swift

let recognizerRunnerViewController : UIViewController = MBViewControllerFactory.recognizerRunnerViewController(withOverlayViewController: CustomOverlayViewController)

Objective-C

UIViewController<MBRecognizerRunnerViewController>* recognizerRunnerViewController = [MBViewControllerFactory recognizerRunnerViewControllerWithOverlayViewController:CustomOverlayViewController];

直 接 处 理 Api

本指南将简要介绍如何使用 PDF417.mobi SDK 对 UIImage 对象进行处理,而不启动相机视频捕获。

使用该特性,您可以解决各种用例,例如:- 识别相机胶卷中的图像上的文本 - 拍摄全分辨率照片并发送它进行处理 - 扫描电子邮件中的图像上的条形码等。

在这里的 DirectAPI 示例演示应用程序将展示 UIImagePickerController 以拍摄全分辨率照片,然后使用 MicroBlink SDK 通过直接处理 API 处理它以获取扫描结果。

直接处理 API 由 MBRecognizerRunner 处理。这是一个处理图像的类。它还具有类似 MBRecognizerRunnerViewController 的协议。开发者可以选择遵循哪个协议。

在示例中,我们遵循了 MBScanningRecognizerRunnerDelegate 协议。

要启动扫描过程,首先决定你想要在应用中的哪个位置添加扫描功能。通常,扫描库的用户有一个按钮,当点击时,会启动扫描过程。然后在这个按钮的触摸处理程序中放置初始化代码。以下是我们列出的初始化代码,它在触摸处理程序方法中的样子。

Swift

func setupRecognizerRunner() {
    var recognizers = [MBRecognizer]()
    pdf417Recognizer = MBPdf417Recognizer()
    recognizers.append(pdf417Recognizer!)
    let recognizerCollection = MBRecognizerCollection(recognizers: recognizers)
    recognizerRunner = MBRecognizerRunner(recognizerCollection: recognizerCollection)
    recognizerRunner?.scanningRecognizerRunnerDelegate = self
}

func processImageRunner(_ originalImage: UIImage) {
    var image: MBImage? = nil
    if let anImage = originalImage {
        image = MBImage(uiImage: anImage)
    }
    image?.cameraFrame = true
    image?.orientation = MBProcessingOrientation.left
    let _serialQueue = DispatchQueue(label: "com.microblink.DirectAPI-sample-swift")
    _serialQueue.async(execute: {() -> Void in
        self.recognizerRunner?.processImage(image!)
    })
}

func recognizerRunner(_ recognizerRunner: MBRecognizerRunner, didFinishScanningWith state: MBRecognizerResultState) {
    if blinkInputRecognizer.result.resultState == MBRecognizerResultStateValid {
        // Handle result
    }
}

Objective-C

- (void)setupRecognizerRunner {
    NSMutableArray<MBRecognizer *> *recognizers = [[NSMutableArray alloc] init];
    
    self.blinkInputRecognizer = [[MBBlinkInputRecognizer alloc] init];
    
    [recognizers addObject:self.blinkInputRecognizer];
    
    MBRecognizerCollection *recognizerCollection = [[MBRecognizerCollection alloc] initWithRecognizers:recognizers];
    
    self.recognizerRunner = [[MBRecognizerRunner alloc] initWithRecognizerCollection:recognizerCollection];
    self.recognizerRunner.scanningRecognizerRunnerDelegate = self;
}

- (void)processImageRunner:(UIImage *)originalImage {
    MBImage *image = [MBImage imageWithUIImage:originalImage];
    image.cameraFrame = YES;
    image.orientation = MBProcessingOrientationLeft;
    dispatch_queue_t _serialQueue = dispatch_queue_create("com.microblink.DirectAPI-sample", DISPATCH_QUEUE_SERIAL);
    dispatch_async(_serialQueue, ^{
        [self.recognizerRunner processImage:image];
    });
}

#pragma mark - MBScanningRecognizerRunnerDelegate
- (void)recognizerRunner:(nonnull MBRecognizerRunner *)recognizerRunner didFinishScanningWithState:(MBRecognizerResultState)state {
    if (self.blinkInputRecognizer.result.resultState == MBRecognizerResultStateValid) {
        // Handle result
    }
}

现在您已经了解了如何实现直接处理 API。

基本上,此 API 由以下两个步骤组成

  • 扫描器的初始化。
  • 为每个您拥有的 UIImage 或 CMSampleBufferRef 调用 processImage: 方法。

MBRecognizer 和可用的识别器

MBRecognizer 概念

MBRecognizer 是 SDK 内部处理的基本单元。其主要目的是处理图像并从中提取有价值的信息。正如你将在 下面 看到,SDK 有许多不同功能的 MBRecognizer 对象。

每个 MBRecognizer 都有一个包含从图像中提取的数据的 MBRecognizerResult 对象。这个 MBRecognizerResult 对象是相应的 MBRecognizer 对象的成员,其生命周期与其父 MBRecognizer 对象绑定。如果你想让你 MBRecognizerRecognizer 对象比其父 MBRecognizer 对象存活更久,你必须通过调用其方法 copy 制作它的副本。

MBRecognizer 对象工作时,它改变其内部状态和结果。MBRecognizer 对象的 MBRecognizerResult 总是处于 Empty 状态。当相应的 MBRecognizer 对象对给定的图像进行识别时,其 MBRecognizerResult 有可能保持在 Empty 状态(如果 MBRecognizer 未能执行识别),移动到 Uncertain 状态(如果 MBRecognizer 执行了识别,但没有提取到所有必需信息)或移动到 Valid 状态(如果 MBRecognizer 执行识别并成功从图像中提取了所有必需信息)。

一旦给定的MBRecognizerRunnerMBRecognizerRunnerViewController传入的MBRecognizerCollection中的任何一个MBRecognizer对象的MBRecognizerResult变为Valid状态,就会在同一线程上调用onScanningFinished回调函数,此时你有机会检查各个MBRecognizer对象的MBRecognizerResult,看看哪个对象已经变为Valid状态。

onScanningFinished方法结束时,MBRecognizerRunnerViewController将继续使用相同的MBRecognizer对象处理新的相机帧,除非处于paused状态。处理器的继续或reset识别将会修改或重置所有MBRecognizer对象的MBRecognizerResult。当使用内置活动时,一旦onScanningFinished被调用,内置活动会暂停MBRecognizerRunnerViewController,并开始完成活动,同时保存包含活跃MBRecognizerMBRecognizerCollection

MBRecognizerCollection概念

MBRecognizerCollectionMBRecognizer对象的包装器,它包含MBRecognizer对象的数组,可以被用于将MBRecognizer对象传入MBRecognizerRunnerMBRecognizerRunnerViewController进行处理。

MBRecognizerCollection通常使用[[MBRecognizerCollection alloc] initWithRecognizers:recognizers]的数组创建,其中包含需要准备进行识别的MBRecognizer对象(即它们的属性已经调整过)。

MBRecognizerCollection管理识别过程中MBRecognizer对象的链。当一个新的图像到来时,它会首先由链中的第一个MBRecognizer处理,然后是第二个,以此类推,直到一个MBRecognizer对象的MBRecognizerResult状态变为Valid,或者链中的所有MBRecognizer对象都被调用过(其中没有任何一个获得Valid状态的结果)。

您不能改变链中 MBRecognizer 对象的顺序 - 无论您将 MBRecognizer 对象以何种顺序提供给 MBRecognizerCollection,它们内部都会以提供最佳性能和准确性的方式进行排序。此外,为了使 SDK 能够以最佳方式对识别链中的 MBRecognizer 对象进行排序,链中不允许存在相同类型的多个 MBRecognizer 对象实例。尝试这样做将会导致您的应用崩溃。

可用识别器列表

本节将列出 PDF417.mobi SDK 中所有可用的 MBRecognizer 对象,它们的作用以及如何使用它们以获得最佳性能和用户体验的建议。

捕帧识别器

MBFrameGrabberRecognizer 是 SDK 中最简单的识别器,因为它不对提供的图像进行任何处理,而是仅将其返回给其 onFrameAvailable。其结果永远不会从空状态发生变化。

此识别器最适合与 MBRecognizerRunnerViewController 简单捕获相机帧。请注意,发送到 onFrameAvailableMBImage 是临时的,它们的内部缓冲区仅在 onFrameAvailable 方法执行期间有效 - 一旦方法结束,MBImage 对象的所有内部缓冲区都将被丢弃。如果您需要将 MBImage 对象存储起来以供以后使用,您必须通过调用 copy 创建它的一个副本。

成功的捕获帧识别器

《MBSuccessFrameGrabberRecognizer》(MB成功帧抓取识别器)是一个特殊的《MBecognizer》类,它包装了其他某个《MBRecognizer》(MB识别器)类并在处理图像时冒充它。然而,当被冒充的《MBRecognizer》对象将其《MBRecognizerResult》(MB识别结果)状态修改为“有效”(Valid)时,《MBSuccessFrameGrabberRecognizer》将捕获图像并保存到它自己的《MBSuccessFrameGrabberRecognizerResult》(MB成功帧抓取识别结果)对象中。

由于《MBSuccessFrameGrabberRecognizer》冒充其从属的《MBRecognizer》对象,因此不可能同时将具体的《MBRecognizer》对象和封装它的《MBSuccessFrameGrabberRecognizer》加入相同的《MBRecognizerCollection》(MB识别器集合)——这样做会有与向《MBRecognizerCollection》提供两个相同类型的《MBRecognizer》实例相同的结果——它会使您的应用程序崩溃。

本识别器最适合需要在某个《MBRecognizer》对象的状态变为“有效”(Valid)时捕获该对象正在处理的精确图像的场景。当这种情况发生时,《MBSuccessFrameGrabberRecognizerResult》也将变为“有效”(Valid),并包含描述的图像。

PDF417识别器

《MBPdf417Recognizer》是一个专门用于扫描PDF417 2D条码的识别器。此识别器只能识别PDF417 2D条码——若要识别其他条码,请参阅BarcodeRecognizer

此识别器可在任何覆盖视图控制器中使用,但与具有专门适合条码扫描的最优用户界面的《MBBarcodeOverlayViewController》配合使用效果最佳。

条码识别器

MBBarcodeRecognizer是一个专门用于扫描各种条码的识别器。在扫描条码时,您应将其作为首选识别器,因为它支持大量的条码符号,包括PDF417 二维条码,从而使PDF417 识别器可能变得冗余,但仅为了其简洁性而保留。

您可以在该识别器中启用多种条码符号,但请注意,启用更多条码符号会影响扫描性能 —— 启用的条码符号越多,整体识别性能越慢。此外,请注意,一些简单缺乏适当冗余的条码符号,如Code 39,可以包含在更复杂的条码中,特别是二维条码,如PDF417

此识别器可在任何覆盖视图控制器中使用,但与具有专门适合条码扫描的最优用户界面的《MBBarcodeOverlayViewController》配合使用效果最佳。

BlinkInput 识别器

MBBlinkInputRecognizer是一种通用的OCR识别器,用于扫描指定可用于扫描的MBProcessors的段。在此识别器中最常见的MBProcessorMBParserGroupProcessor,它激活组中的所有MBParsers以从OCR结果中提取感兴趣的数据。

此识别器可以用于任何上下文。它被用于提供的MBFieldByFieldOverlayViewController的实现中。

MBProcessors处理器概念部分中解释,您可以在解析器概念部分找到有关MBParsers的更多信息。

检测识别器

MBDetectorRecognizer是一种用于扫描使用自定义MBDetector的通用文档的识别器。您可以在检测器概念部分中找到有关Detector的更多信息。MBDetectorRecognizer可以简单地用于文档检测和获取其图像。更有趣的使用案例是从自定义文档类型中提取数据。MBDetectorRecognizer执行文档检测,并可以通过使用模板API配置来提取扫描文档中的感兴趣字段。您可以在本节中找到有关模板API的更多信息。

字段逐个 扫描功能

字段逐个 扫描功能是为扫描小型文本字段(称为扫描元素)设计的。对于每个扫描元素,定义一个专门的 MBParser 来从 OCR 结果中提取感兴趣的结构化数据。专注于逐个扫描的小型文本字段使得支持实现 自由格式文档 成为可能,因为不需要字段检测。用户负责在扫描窗口内定位感兴趣的字段,扫描过程会引导他。当实现对自定义文档的支持时,只需定义感兴趣的字段。

以下章节将描述 字段逐个 方法。

字段逐个 功能

字段逐个 功能是为使用 MBFieldByFieldViewController 按预定义顺序扫描小型文本字段而设计的。

要使用字段逐个功能,您需要初始化 MBFieldByFieldOverlayViewController 并遵守 MBFieldByFieldOverlayViewControllerDelegate(本示例遵循我们的 FieldByField-sample-Swift 项目)

Swift

    // Create MBFieldByFieldOverlaySettings
    let settings = MBFieldByFieldOverlaySettings(scanElements: MBGenericPreset.getPreset()!)
    
    // Create field by field VC
    let fieldByFieldVC = MBFieldByFieldOverlayViewController(settings: settings, delegate: self)
    
    // Create scanning VC
    let recognizerRunnerViewController: (UIViewController & MBRecognizerRunnerViewController)? = MBViewControllerFactory.recognizerRunnerViewController(withOverlayViewController: fieldByFieldVC)
    
    // Present VC
    self.present(recognizerRunnerViewController!, animated: true, completion: nil)


    func field(_ fieldByFieldOverlayViewController: MBFieldByFieldOverlayViewController, didFinishScanningWith scanElements: [MBScanElement]) {
    	// Whatever you want to do with results
    }

Objective-C

	// Create MBFieldByFieldOverlaySettings
	MBFieldByFieldOverlaySettings *settings = [[MBFieldByFieldOverlaySettings alloc] initWithScanElements: [MBGenericPreset getPreset] initWithSettings: settings, delegate: self];

	// Create field by field VC
	MBFieldByFieldOverlayViewController *fieldByFieldOverlayViewController =  [[MBFieldByFieldOverlayViewController alloc] initWithSettings:settings delegate: self];

	// Create scanning VC
	UIViewController<MBRecognizerRunnerViewController>* recognizerRunnerViewController = [MBViewControllerFactory recognizerRunnerViewControllerWithOverlayViewController:fieldByFieldOverlayViewController];

	/ Present VC
	[self presentViewController:recognizerRunnerViewController animated:YES completion:nil];

	- (void)fieldByFieldOverlayViewController:(MBFieldByFieldOverlayViewController *)fieldByFieldOverlayViewController didFinishScanningWithElements:(NSArray<MBScanElement *> *)scanElements {
		// Whatever you want to do with results
	}

MBProcessorMBParser

MBProcessorsMBParsersBlinkInput SDK 内部的标准处理单元,用于从输入图像中提取数据。与 MBRecognizer 不同,MBProcessorMBParser 不是独立的处理单元。始终在 MBRecognizer 中使用 MBProcessor,并在适当的 MBProcessor 中使用 MBParser 来从 OCR 结果中提取数据。

《MBProcessor》概念

MBProcessor 是一种处理单元,用于一些支持处理器的 Recognizer 中。它以具体的 MBProcessor 实现方式处理包围 Recognizer 预准备的输入图像。

MBProcessor 架构类似于 في “Recognizer 概念” 部分中描述的 MBRecognizer 架构。每个实例还关联一个内部 MBRecognizerResult 对象,其生命周期与父 MBProcessor 对象绑定,并在 MBProcessor 工作时更新。如果您需要使 MBRecognizerResult 对象超出其父 MBProcessor 对象的生命周期,您必须调用其 copy 方法来复制它。

它还有自己的内部状态。在识别过程中处于 工作状态 时,不允许调整 MBProcessor 对象的属性。

为了支持常见的用例,有几个不同的 MBProcessor 实现可用。它们将在下一节中列出。

可用处理器列表

本节将列出 BlinkInput SDK 中的可用 MBProcessor 类型及其用途。

图像返回处理器

MBImageReturnProcessor 用于获取输入图像。它简单地将输入图像保存并使其在扫描完成后可用。

输入图像的外观取决于 MBImageReturnProcessor 所使用的上下文。例如,当它用于 MBBlinkInputRecognizer 中时,仅处理扫描区域的原始图像。当它用于 Templating API 中时,输入图像将被去扭曲(裁剪和旋转)。

图像以原始的 MBImage 类型返回。处理程序还可以配置以将保存的图像编码为 JPEG。

解析器组处理器

MBParserGroupProcessor 是一种执行图像上的 OCR(光字符识别)的处理器类型,并允许组内的所有解析器从 OCR 结果中提取数据。 MBParser 的概念在下一节中描述。

在进行OCR之前,通过组合来自同一组中每个MBParser所需的最佳OCR引擎选项,计算出最佳的OCR引擎选项。例如,如果一个解析器期望和产生输出大写字母的结果,而另一个解析器从数字中提取数据,那么大写字母和数字都必须添加到可能出现在OCR结果中允许字符的列表中。这是一个简化的解释,因为OCR引擎选项包含许多参数,这些参数是由MBParserGroupProcessor组合的。

因此,如果在扫描过程中使用了多个解析器和多个解析器组合处理器,仔细分组解析器非常重要。

让我们通过一个例子来看看:假设我们有可用的两个解析器:MBAmountParserMBEmailParserMBAmountParser知道如何从OCR结果中提取金额,并要求OCR仅识别数字、句点和逗号,忽略字母。另一方面,MBEmailParser知道如何从OCR结果中提取电子邮件,并要求OCR识别字母、数字、'@'字符和句点,但不包含逗号。

如果我们把MBAmountParserMBEmailParser都放入同一个MBParserGroupProcessor中,合并的OCR引擎设置将需要识别所有字母、所有数字、'@'字符和句点及逗号。这样的OCR结果将包含所有MBEmailParser正确解析电子邮件所需的字符,但如果OCR错误地将某些字符分类为数字,可能会使MBAmountParser困惑。

如果我们把MBAmountParser放入一个MBParserGroupProcessor中,而MBEmailParser放入另一个MBParserGroupProcessor中,OCR将为每个解析器组独立执行,从而防止MBAmountParser困惑,但需要执行两次图像的OCR,这可能会影响性能。

MBParserGroupProcessor是最常见的MBProcessor。只需需要OCR时就会使用它。在OCR执行并且所有解析器都已运行后,可以通过组内封装的解析器对象获得解析结果。MBParserGroupProcessor实例还有一个关联的内部MBParserGroupProcessorResult,其状态在处理过程中更新,其属性ocrLayout可以用来获得用于解析数据的原始MBOcrLayout

请注意,如果允许的BlinkInput SDK许可证密钥,则可以访问MBOcrLayoutMBOcrLayout结构包含有关所有识别字符及其在图像中的位置的信息。为了避免有人滥用,只有通过高级许可证密钥允许获取MBOcrLayout结构。

MBParser概念

MBParser是一组用于从原始OCR结果中提取结构化数据的对象。必须在执行OCR的MBParserGroupProcessor内使用,因此MBParser不是一个独立处理单元。

MBRecognizer和其他所有处理单元一样,每个MBParser实例都有一个与其生命周期绑定的内部MBRecognizerResult对象,其生命周期与父MBParser对象相同,并在MBParser工作时更新。当解析完成后,可以使用MBParserResult来获取提取的数据。如果您需要您的MBParserResult对象在父MBParser对象的生命周期之外继续存在,您必须通过调用其方法copy制作一个副本。

它还有其内部状态,在识别过程中处于工作状态时,不允许修改MBParser对象属性。

有很多不同类型的MBParsers用于从各种文档中提取最常见的字段。此外,大多数都可以针对特定用例进行调整。对于所有其他自定义数据字段,都提供了RegexParser,可以通过任意正则表达式进行配置。

可用解析器列表

金额解析器

MBAmountParser用于从OCR结果中提取金额。

日期解析器

MBDateParser用于从OCR结果中提取不同格式的日期。

邮件解析器

MBEmailParser用于从OCR结果中提取电子邮件地址。

IBAN 解析器

MBIbanParser 用于从OCR结果中提取IBAN(国际银行账户号)。

车牌解析器

MBLicensePlatesParser 用于从OCR结果中提取车牌内容。

纯解析器

MBRawParser 用于获取未经任何智能解析操作的原始OCR结果字符串版本。

正则表达式解析器

MBRegexParser 用于提取与给定正则表达式匹配的OCR结果内容。正则表达式解析不是使用Java的正则表达式引擎进行的。相反,它使用自定义的正则表达式引擎。

充值解析器

MBTopUpParser 用于从OCR结果中提取TopUp(手机充值券)代码。存在一个具有最常用供应商预设置的TopUpPreset枚举。可以使用方法- (void)setTopUpPreset:(MBTopUpPreset)topUpPreset来配置解析器,使其只返回由使用的预设定义的正确格式的代码。

VIN(车辆识别号)解析器

MBVinParser 用于从OCR结果中提取VIN(车辆识别号)。

使用模板API扫描通用文档

本节讨论了为扫描模板文档设置 MBDetectorRecognizer。请查看 Templating-sample 示例应用程序以获取源代码示例。

模板文档是指由其模板定义的任何文档。模板包含有关文档应该如何检测的信息,即检测到相机场景以及文档哪些部分包含哪些有用信息。

定义检测文档的方式

在执行文档OCR之前,BlinkInput 首先需要在相机场景中找到其位置。为了进行检测,您需要定义 MBDetector

您必须在创建 MBDetectorRecognizer 时设置具体的 MBDetector,并将其作为其构造函数的参数。

您可以在可用检测器列表部分找到有关可使用的检测器的更多信息。最常用的检测器是 MBDocumentDetector

定义如何提取感兴趣字段

MBDetector 生成包含文档位置的结果。在检测到文档之后,所有后续处理都是在检测到的输入图像部分上进行的。

同一类型的文档可能存在一个或多个变体,例如,对于某些文档可能存在旧版和新版,都必须支持。因此,为了实现每个文档的支持,使用一个或多个模板类。有关 MBTemplatingClass 的详细信息,请参阅模板类组件部分。

MBTemplatingClass 包含处理其类文档所需的所有信息和组件。模板类依次处理。对于首次成功提取数据的类别,链终止并返回识别结果。对于每个输入图像,处理方式如下:

  1. 在定义的位置运行分类 MBProcessorGroups 以提取数据。使用 MBProcessorGroup 来定义感兴趣的区域和从该位置提取数据的 MBProcessors。关于 MBProcessorGroup 的更多信息,请参阅 下一节

  2. 使用分类处理器组提取的数据运行 MBTemplatingClassifier 来决定当前扫描的文档是否属于当前类别。其 classify 方法仅返回 YES/trueNO/false。如果分类器返回 NO/false,识别将转移到链中的下一个类别(如果存在)。有关 MBTemplatingClassifier 的更多信息,请参阅 本节

  3. 如果 MBTemplatingClassifier 决定当前扫描的文档属于当前类别,则运行非分类 MBProcessorGroups 以提取其他感兴趣字段。

MBProcessorGroup 组件

在模板 API 中,使用 MBProcessorGroup 来定义检测到的文档上感兴趣字段的区域以及如何通过以下构造函数中设置以下参数来处理该位置:

  1. 相对于文档检测的坐标位置,以 Rectangle 对象形式传递。

  2. MBDewarpPolicy 可以决定处理后的图像块的输出。您可以在 可用的 dewarp 策略列表 部分找到每个 MBDewarpPolicy 的描述、目的以及在何种情况下使用这些策略以获得最佳结果的建议。

  3. 将执行处理当前文档位置图像块的处理器集合。有关处理器的更多信息,请参阅 处理器概念 部分。

可用的 dewarp 策略列表

具体的 MBDewarpPolicy 定义了如何对感兴趣的具体位置进行 dewarp(裁剪和旋转)。它决定了输出 dewarp 图像的像素高度和宽度。以下是可用的 dewarp 策略列表,以及链接文档以获取更多信息:

  • MBFixedDewarpPolicy

    • 定义 dewarp 图像的确切高度(以像素为单位)
    • 通常对使用旧版 OCR 引擎的处理器组来说是最优策略
  • MBDPIBasedDewarpPolicy:

    • 定义所需的DPI(每英寸点数)
    • 解扭曲图像的高度将根据用户提供的实际物理尺寸和所选DPI来计算
    • 通常是对处理组准备输出位置原始图像的最佳策略
  • MBNoUpScalingDewarpPolicy:

    • 定义了解扭曲图像的最大允许高度(像素)
    • 解扭曲图像的高度将以一种方式计算,以确保图像的任何部分都不会被放大
    • 如果结果的图像高度超过最大允许值,则将使用最大允许的高度作为实际高度,这会有效地缩小图像
    • 通常是使用神经网络的处理器的最佳策略,例如,深度OCR、全息检测或基于NN的分类

MBTemplatingClass 组件

MBTemplatingClass 允许实现支持特定类别的文档的扫描支持,该类别应使用模板API进行扫描。模板识别器的最终实现由一个或多个模板类组成,每个文档版本一个类。

MBTemplatingClass 包含两个 MBProcessorGroups 集合和一个 MBTemplatingClassifier

MBTemplatingClass 中包含的两个处理器组集合是

  1. 通过使用 [- (void)setClassificationProcessorGroups:(nonnull NSArray<__kindof MBProcessorGroup *> *)processorGroups] 方法设置的分类处理器组。此集合中的 MBProcessorGroups 会在分类之前执行,这意味着它们总是会在处理到此类时执行。

  2. 通过使用 [- (void)setNonClassificationProcessorGroups:(nonnull NSArray<__kindof MBProcessorGroup *> *)processorGroups] 方法设置的非分类处理器组。如果分类结果为正,则此集合中的 MBProcessorGroups 会在分类之后执行。

决定扫描的文档是否属于当前类的组件是 MBTemplatingClass。可以通过使用 - (void)setTemplatingClassifier:(nullable id)templatingClassifier 方法来设置。如果尚未设置,则不会执行非分类处理器组。关于实现 MBTemplatingClassifier 的说明在下一个章节中给出。

实现 MBTemplatingClassifier

每个具体的模板分类器实现了 MBTemplatingClassifier 接口,该接口要求实现其 classify 方法,该方法在评估相关的 MBTemplatingClass 时会被调用。

分类决策应根据分类处理器组集合中包含的一个或多个处理单元返回的处理结果来做出。如ProcessorGroup组件部分所述,每个处理器组包含一个或多个MBProcessors。有不同类型的MBProcessors包围更小的处理单元,例如,MBParserGroupProcessor维护一个MBParsers的组。该层次结构中每个处理单元的结果都可以用于分类。在大多数情况下,使用MBParser的结果来决定预期的格式数据是否存在于指定位置。

要检索用于分类的各种处理单元的结果,需要在调用classify方法时提供它们的实例。

获取识别结果

当识别完成后,可以通过用于配置MBTemplatingRecognizer和随后处理输入图像的处理单元实例(如:MBProcessorsMBParsers等)来获得结果。

MBDetector概念

MBDetector是一个处理单元,用于某些支持检测器的MBRecognizer,如MBDetectorRecognizer。具体的MBDetector知道如何在输入图像中找到特定的对象。MBRecognizer可以使用它进行对象检测,然后再进一步识别检测到的对象的内容。

MBDetector架构类似于在识别器概念部分描述的MBRecognizer架构。每个实例还关联一个内部MBRecognizerResult对象,其生命周期绑定到其父MBDetector对象的生命周期,并在MBDetector工作时更新。如果您需要让您的MBRecognizerResult对象超出其父MBDetector对象的生命周期,您必须通过调用其copy方法来创建一个副本。

它还具有其内部状态,在识别过程中的工作状态时,不允许修改MBDetector对象的属性。

当对输入图像执行检测时,与其关联的每个MBDetector在其MBDetectorResult对象中保存以下信息

为支持常见用例,有几个不同的MBDetector实现可用。它们将在下一节中列出。

可用检测器列表

文档检测器

MBDocumentDetector 用于检测卡片文件、支票、A4大小文件、收据等多种文件。

它接受一个或多个 MBDocumentSpecificationsMBDocumentSpecification 通过使用边缘检测算法和预定义的宽高比来表示应该被检测的文件的规格。

对于最常用的文档格式,存在一个辅助方法 + (instancetype)createFromPreset:(MBDocumentSpecificationPreset)preset,它根据给定的 MBDocumentSpecificationPreset 创建和初始化文件规格。

有关所有可用的配置方法,请参阅 MBDocumentDetector 文档,以及有关可用结果内容的说明,请参阅 MBDocumentDetectorResult 文档。

MRTD 检测器

MBMrtdDetector 用于执行可读旅行文件的检测。

可以使用方法 - (void)setMrtdSpecifications:(NSArray<__kindof MBMrtdSpecification *> *)mrtdSpecifications 来定义哪些 MRTD 文档应该是可检测的。它接收 MBMrtdSpecification 的数组。 MBMrtdSpecification 表示应该被检测的 MRTD 的规格。可以通过使用 + (instancetype)createFromPreset:(MBMrtdSpecificationPreset)preset 方法从 MBMrtdSpecificationPreset 创建。

如果没有设置 MBMrtdSpecifications,则将检测所有受支持的可读旅行文件格式。

有关所有可用的配置方法的列表,请参阅 MBMrtdDetector 文档,以及有关可用结果内容的说明,请参阅 MBMrtdDetectorResult 文档。

故障排除

集成问题

如果集成SDK出现问题,首先请确保您已按照以下集成说明将其集成到Xcode中。

如果您已按照Xcode集成说明操作,但仍存在集成问题,请通过help.microblink.com与我们联系。

SDK问题

如果使用SDK时出现问题,您应按照以下操作进行

许可问题

如果您收到“无效的许可证密钥”错误或其他与许可证相关的问题(例如,某些应该启用的功能未启用或相机上出现水印),请首先检查控制台。所有与许可证相关的问题都会记录到错误日志中,因此可以轻松确定出了什么问题。

当您确定了许可证相关的问题或您根本不了解日志时,您应通过help.microblink.com与我们联系。在联系我们时,请确保您提供以下信息

  • 您应用的精确 Bundle ID(从您的 info.plist 文件中获取)
  • 导致问题的许可证
  • 请强调您报告的是与iOS版本的PDF417.mobi SDK相关的问题
  • 如果您不确定问题,还应提供包含许可证错误的控制台摘录

其他问题

如果您在扫描某些项目、特定设备上的不希望的行为、PDF417.mobi SDK内部的崩溃或其他未提及的问题,请按以下步骤操作

  • help.microblink.com上描述您的问题并以下列信息
    • 之前步骤中获得的日志文件
    • 您正尝试扫描的项目的高分辨率扫描/照片
    • 您所使用的设备信息
    • 请强调您报告的是与iOS版本的PDF417.mobi SDK相关的问题

经常提问的问题及已知问题

以下是一系列常见的提问及其解决方案,以及SDK中已知的问题及其解决方法。

在演示模式下,一切运行正常,但在切换到生产许可证后,当构造特定的MBRecognizer对象时,我收到包含MBMicroblinkSDKRecognizerErrorDomainMBRecognizerFailedToInitalize错误代码的NSError

每个许可证密钥都包含有关允许使用哪些功能和未允许使用哪些功能的信息。这个NSError表示您的生产许可证不允许使用特定的MBRecognizer对象。您应该联系支持来检查提供的许可证是否正常,并且它确实包含您购买的所有限特性。

当使用试用许可证密钥时,我收到包含MBMicroblinkSDKRecognizerErrorDomainMBRecognizerFailedToInitalize错误代码的NSError

每次您构造任何MBRecognizer对象或检查许可证是否允许使用该对象时,都会执行这项检查。如果在构造该对象之前未设置许可证,您将收到包含MBMicroblinkSDKRecognizerErrorDomainMBRecognizerFailedToInitalize代码的NSError。我们建议尽可能早地在您的应用中设置许可证。

在架构armv7上存在未定义的符号

确保您的应用程序已连接到iconv和Accelerate框架,具体操作请参考快速入门。如果您使用CocoaPods,请务必在安装pods之前已安装git-lfs。如果您仍然遇到此错误,请转到项目文件夹并执行命令git-lfs pull

在我的 didFinish 回调中,我在MBRecognizer中看到了结果,但是当扫描活动结束时,结果消失了

这通常发生在使用MBRecognizerRunnerViewController,却在您的didFinish回调中忘记暂停MBRecognizerRunnerViewController时发生。然后,一旦发生didFinish,结果就会被在您的didFinish回调和实际完成扫描活动之间的时间内在MBRecognizer执行的额外处理所修改或重置。有关MBRecognizer对象的状态性更多信息,请查看本节

提交应用程序到App Store时不受支持的架构

Microblink.framework是一个包含所有架构切片的动态框架 - 设备和模拟器。如果计划提取用于ad hoc分发的.ipa文件,您需要先对框架进行预处理以删除模拟器架构。

理想的解决方案是在嵌入框架构建阶段之后添加一个构建阶段,该阶段从嵌入框架中清除未使用的切片。

该构建步骤基于此处提供的:http://ikennd.ac/blog/2015/02/stripping-unwanted-architectures-from-dynamic-libraries-in-xcode/

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done

其他信息

完整的API参考请在此处找到:http://blinkinput.github.io/blinkinput-ios/docs/index.html.

对于任何其他问题,请随时通过help.microblink.com联系我们。