アプリから Google Cloud API を呼び出すには、承認を処理し、API キーなどの秘密の値を保護する中間 REST API を作成する必要があります。次に、モバイル アプリでコードを記述して、この中間サービスを認証し、通信する必要があります。
この REST API を作成する 1 つの方法は、Firebase Authentication and Functions を使用することです。これにより、Google Cloud API へのマネージド サーバーレス ゲートウェイが提供されます。このゲートウェイは、認証を処理し、ビルド済みの SDK を使用してモバイル アプリから呼び出すことができます。
このガイドでは、この手法を使用してアプリから Cloud Vision API を呼び出す方法を示します。この方法では、すべての認証済みユーザーが Cloud プロジェクトを介して Cloud Vision の有料サービスにアクセスできるようになるため、先に進む前に、この認証メカニズムがユースケースに十分かどうかを検討してください。
あなたが始める前に
プロジェクトを構成する
アプリに Firebase をまだ追加していない場合は、スタート ガイドの手順に従って追加してください。Swift Package Manager を使用して、Firebase の依存関係をインストールおよび管理します。
- Xcode で、アプリ プロジェクトを開いた状態で、 File > Add Packagesに移動します。
- プロンプトが表示されたら、Firebase Apple プラットフォーム SDK リポジトリを追加します。
- Firebase ML ライブラリを選択します。
- 完了すると、Xcode はバックグラウンドで依存関係の解決とダウンロードを自動的に開始します。
https://github.com/firebase/firebase-ios-sdk
次に、アプリ内セットアップを実行します。
- アプリで、Firebase をインポートします。
迅速
import FirebaseMLModelDownloader
Objective-C
@import FirebaseMLModelDownloader;
さらにいくつかの構成手順を実行すると、準備が整います。
プロジェクトでクラウドベースの API をまだ有効にしていない場合は、ここで有効にします。
- Firebase コンソールのFirebase ML API ページを開きます。
プロジェクトを Blaze 料金プランにまだアップグレードしていない場合は、[アップグレード] をクリックしてアップグレードします。 (プロジェクトが Blaze プランに含まれていない場合にのみ、アップグレードするように求められます。)
Blaze レベルのプロジェクトのみがクラウドベースの API を使用できます。
- クラウドベースの API がまだ有効になっていない場合は、[クラウドベースの API を有効にする] をクリックします。
- Cloud Vision API へのアクセスを禁止するように、既存の Firebase API キーを構成します。
- Cloud コンソールの資格情報ページを開きます。
- リスト内の API キーごとに編集ビューを開き、[キーの制限] セクションで、Cloud Vision API を除く使用可能なすべての API をリストに追加します。
呼び出し可能な関数をデプロイする
次に、アプリと Cloud Vision API をブリッジするために使用する Cloud Function をデプロイします。 functions-samples
リポジトリには、使用できる例が含まれています。
デフォルトでは、この関数を介して Cloud Vision API にアクセスすると、アプリの認証済みユーザーのみが Cloud Vision API にアクセスできます。さまざまな要件に合わせて機能を変更できます。
関数をデプロイするには:
- functions-samples リポジトリを複製またはダウンロードし、
vision-annotate-image
ディレクトリに変更します:git clone https://github.com/firebase/functions-samples
cd vision-annotate-image
- 依存関係のインストール:
cd functions
npm install
cd ..
- Firebase CLI がない場合は、インストールします。
-
vision-annotate-image
ディレクトリで Firebase プロジェクトを初期化します。プロンプトが表示されたら、リストからプロジェクトを選択します。firebase init
- 関数をデプロイします:
firebase deploy --only functions:annotateImage
アプリに Firebase Auth を追加する
上記でデプロイされた呼び出し可能関数は、アプリの認証されていないユーザーからのリクエストを拒否します。まだ行っていない場合は、アプリに Firebase Auth を追加する必要があります。
アプリに必要な依存関係を追加する
Swift Package Manager を使用して Cloud Functions for Firebase ライブラリをインストールします。
これで、画像内のテキストの認識を開始する準備が整いました。
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. callable 関数を呼び出してテキストを認識する
画像内のランドマークを認識するには、 JSON Cloud Vision リクエストを渡して呼び出し可能な関数を呼び出します。まず、Cloud Functions のインスタンスを初期化します。
迅速
lazy var functions = Functions.functions()
Objective-C
@property(strong, nonatomic) FIRFunctions *functions;
リクエストを作成します。 Cloud Vision API は、
TEXT_DETECTION
とDOCUMENT_TEXT_DETECTION
の 2種類のテキスト検出をサポートしています。 2 つのユース ケースの違いについては、 Cloud Vision OCR ドキュメントを参照してください。迅速
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"]} };
最後に、関数を呼び出します。
迅速
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. 認識されたテキストのブロックからテキストを抽出する
テキスト認識操作が成功すると、タスクの結果でBatchAnnotateImagesResponseの JSON 応答が返されます。テキスト注釈は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"]);
画像の領域に固有の情報を取得することもできます。 block
、 paragraph
、 word
、および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];
}
}