Google は、黒人コミュニティのための人種的公平の促進に取り組んでいます。詳細をご覧ください。

iOSでFirebaseAuthとFunctionsを使用して、CloudVisionで画像内のテキストを安全に認識します

アプリからGoogleCloud APIを呼び出すには、承認を処理し、APIキーなどのシークレット値を保護する中間RESTAPIを作成する必要があります。次に、この中間サービスを認証して通信するために、モバイルアプリにコードを記述する必要があります。

このRESTAPIを作成する1つの方法は、Firebase Authentication and Functionsを使用することです。これにより、認証を処理し、ビルド済みのSDKを使用してモバイルアプリから呼び出すことができる、Google CloudAPIへの管理されたサーバーレスゲートウェイが提供されます。

このガイドでは、この手法を使用してアプリからCloud VisionAPIを呼び出す方法を示します。この方法では、認証されたすべてのユーザーがクラウドプロジェクトを通じてCloud Visionの課金サービスにアクセスできるようになるため、続行する前に、この認証メカニズムがユースケースに十分かどうかを検討してください。

あなたが始める前に

プロジェクトを構成する

  1. あなたはすでにあなたのアプリにFirebaseを追加していない場合は、の手順に従って、それを行うセットアップガイドを
  2. あなたは、その使用してXcodeプロジェクトを開くようにしてください、あなたのプロジェクトのポッドをインストールまたはアップデートした後:あなたのPodfileでFirebase含める.xcworkspace
  3. アプリで、Firebaseをインポートします。

    迅速

    import Firebase

    Objective-C

    @import Firebase;
  4. プロジェクトでクラウドベースのAPIをまだ有効にしていない場合は、今すぐ有効にしてください。

    1. 開きFirebase MLのAPIページFirebaseコンソールのを。
    2. すでにブレイズ・プライシング計画にプロジェクトをアップグレードしていない場合は、そうするためにアップグレード]をクリックします。 (プロジェクトがBlazeプランに含まれていない場合にのみ、アップグレードするように求められます。)

      BlazeレベルのプロジェクトのみがクラウドベースのAPIを使用できます。

    3. クラウドベースのAPIがすでに有効になっていない場合は、クラウドベースのAPIを有効にする]をクリックします。
  5. Cloud VisionAPIへのアクセスを禁止するように既存のFirebaseAPIキーを構成します。
    1. 開き、資格情報のCloudコンソールのページを。
    2. リスト内の各APIキーについては、編集ビューを開き、キーの制限]セクションで、リストにクラウドビジョンのAPIを除き、利用可能なAPIのすべてを追加します。

呼び出し可能な関数をデプロイする

次に、アプリとCloud VisionAPIのブリッジに使用するCloudFunctionをデプロイします。 functions-samplesリポジトリには、使用可能な例が含まれています。

デフォルトでは、この関数を介してCloud Vision APIにアクセスすると、アプリの認証されたユーザーのみがCloud VisionAPIにアクセスできます。さまざまな要件に合わせて関数を変更できます。

関数をデプロイするには:

  1. クローンまたはダウンロードが機能-サンプルはレポへと変化するvision-annotate-imageディレクトリ:
    git clone https://github.com/firebase/functions-samples
    cd vision-annotate-image
    
  2. 依存関係をインストールします。
    cd functions
    npm install
    cd ..
    
  3. あなたがFirebase CLIを持っていない場合は、それをインストール
  4. 中Firebaseプロジェクト初期化するvision-annotate-imageディレクトリを。プロンプトが表示されたら、リストからプロジェクトを選択します。
    firebase init
  5. 展開機能:
    firebase deploy --only functions:annotateImage

アプリにFirebaseAuthを追加する

上記でデプロイされた呼び出し可能関数は、アプリの認証されていないユーザーからのリクエストを拒否します。あなたはまだ行っていない場合は、する必要がありますあなたのアプリにFirebase認証を追加します。

アプリに必要な依存関係を追加する

  1. あなたのPodfileにFirebase関数ライブラリの依存関係を追加します。
    pod 'Firebase/Functions'
  2. 依存関係をインストールします。
    pod install

これで、画像内のテキストの認識を開始する準備が整いました。

1.入力画像を準備します

Cloud Visionを呼び出すには、画像をbase64でエンコードされた文字列としてフォーマットする必要があります。処理するにUIImage

迅速

guard let imageData = uiImage.jpegData(compressionQuality: 1.0f) else { return }
let base64encodedImage = imageData.base64EncodedString()

Objective-C

NSData *imageData = UIImageJPEGRepresentation(uiImage, 1.0f);
NSString *base64encodedImage =
  [imageData base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength];

2.呼び出し可能関数を呼び出して、テキストを認識します

画像内のランドマークを認識するために、渡して呼び出し可能な関数呼び出しJSONクラウドビジョン要求を

  1. まず、CloudFunctionsのインスタンスを初期化します。

    迅速

    lazy var functions = Functions.functions()
    

    Objective-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. リクエストを作成します。クラウドビジョンAPIは、次の2つのサポートタイプ:テキスト検出のTEXT_DETECTIONDOCUMENT_TEXT_DETECTION 。参照クラウドビジョンOCRドキュメントを2つの使用例との違いのために。

    迅速

    let requestData = [
      "image": ["content": base64encodedImage],
      "features": ["type": "TEXT_DETECTION"],
      "imageContext": ["languageHints": ["en"]]
    ]
    

    Objective-C

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"type": @"TEXT_DETECTION"},
      @"imageContext": @{@"languageHints": @[@"en"]}
    };
    
  3. 最後に、関数を呼び出します。

    迅速

    functions.httpsCallable("annotateImage").call(requestData) { (result, error) in
      if let error = error as NSError? {
        if error.domain == FunctionsErrorDomain {
          let code = FunctionsErrorCode(rawValue: error.code)
          let message = error.localizedDescription
          let details = error.userInfo[FunctionsErrorDetailsKey]
        }
        // ...
      }
      // Function completed succesfully
    }
    

    Objective-C

    [[_functions HTTPSCallableWithName:@"annotateImage"]
                              callWithObject:requestData
                                  completion:^(FIRHTTPSCallableResult * _Nullable result, NSError * _Nullable error) {
            if (error) {
              if (error.domain == FIRFunctionsErrorDomain) {
                FIRFunctionsErrorCode code = error.code;
                NSString *message = error.localizedDescription;
                NSObject *details = error.userInfo[FIRFunctionsErrorDetailsKey];
              }
              // ...
            }
            // Function completed succesfully
            // Get information about labeled objects
    
          }];
    

3.認識されたテキストのブロックからテキストを抽出します

テキスト認識操作が成功した場合、のJSONレスポンスBatchAnnotateImagesResponseは、タスクの結果で返されます。テキスト注釈はで見つけることができfullTextAnnotationオブジェクト。

あなたは、文字列として認識されたテキストを取得することができtextフィールド。例えば:

迅速

guard let annotation = (result?.data as? [String: Any])?["fullTextAnnotation"] as? [String: Any] else { return }
print("%nComplete annotation:")
let text = annotation["text"] as? String ?? ""
print("%n\(text)")

Objective-C

NSDictionary *annotation = result.data[@"fullTextAnnotation"];
if (!annotation) { return; }
NSLog(@"\nComplete annotation:");
NSLog(@"\n%@", annotation[@"text"]);

画像の領域に固有の情報を取得することもできます。それぞれについてblockparagraphword 、およびsymbol 、あなたは地域で認識されたテキストや地域の境界の座標を取得することができます。例えば:

迅速

guard let pages = annotation["pages"] as? [[String: Any]] else { return }
for page in pages {
var pageText = ""
guard let blocks = page["blocks"] as? [[String: Any]] else { continue }
for block in blocks {
    var blockText = ""
    guard let paragraphs = block["paragraphs"] as? [[String: Any]] else { continue }
    for paragraph in paragraphs {
    var paragraphText = ""
    guard let words = paragraph["words"] as? [[String: Any]] else { continue }
    for word in words {
        var wordText = ""
        guard let symbols = word["symbols"] as? [[String: Any]] else { continue }
        for symbol in symbols {
        let text = symbol["text"] as? String ?? ""
        let confidence = symbol["confidence"] as? Float ?? 0.0
        wordText += text
        print("Symbol text: \(text) (confidence: \(confidence)%n")
        }
        let confidence = word["confidence"] as? Float ?? 0.0
        print("Word text: \(wordText) (confidence: \(confidence)%n%n")
        let boundingBox = word["boundingBox"] as? [Float] ?? [0.0, 0.0, 0.0, 0.0]
        print("Word bounding box: \(boundingBox.description)%n")
        paragraphText += wordText
    }
    print("%nParagraph: %n\(paragraphText)%n")
    let boundingBox = paragraph["boundingBox"] as? [Float] ?? [0.0, 0.0, 0.0, 0.0]
    print("Paragraph bounding box: \(boundingBox)%n")
    let confidence = paragraph["confidence"] as? Float ?? 0.0
    print("Paragraph Confidence: \(confidence)%n")
    blockText += paragraphText
    }
    pageText += blockText
}

Objective-C

for (NSDictionary *page in annotation[@"pages"]) {
  NSMutableString *pageText = [NSMutableString new];
  for (NSDictionary *block in page[@"blocks"]) {
    NSMutableString *blockText = [NSMutableString new];
    for (NSDictionary *paragraph in block[@"paragraphs"]) {
      NSMutableString *paragraphText = [NSMutableString new];
      for (NSDictionary *word in paragraph[@"words"]) {
        NSMutableString *wordText = [NSMutableString new];
        for (NSDictionary *symbol in word[@"symbols"]) {
          NSString *text = symbol[@"text"];
          [wordText appendString:text];
          NSLog(@"Symbol text: %@ (confidence: %@\n", text, symbol[@"confidence"]);
        }
        NSLog(@"Word text: %@ (confidence: %@\n\n", wordText, word[@"confidence"]);
        NSLog(@"Word bounding box: %@\n", word[@"boundingBox"]);
        [paragraphText appendString:wordText];
      }
      NSLog(@"\nParagraph: \n%@\n", paragraphText);
      NSLog(@"Paragraph bounding box: %@\n", paragraph[@"boundingBox"]);
      NSLog(@"Paragraph Confidence: %@\n", paragraph[@"confidence"]);
      [blockText appendString:paragraphText];
    }
    [pageText appendString:blockText];
  }
}