Reconnaître le texte dans les images en toute sécurité avec Cloud Vision à l'aide de Firebase Auth et des fonctions sur iOS

Pour appeler une API Google Cloud à partir de votre application, vous devez créer une API REST intermédiaire qui gère l'autorisation et protège les valeurs secrètes telles que les clés API. Vous devez ensuite écrire du code dans votre application mobile pour vous authentifier et communiquer avec ce service intermédiaire.

Une façon de créer cette API REST consiste à utiliser Firebase Authentication and Functions, qui vous offre une passerelle gérée sans serveur vers les API Google Cloud qui gère l'authentification et peut être appelée depuis votre application mobile avec des SDK prédéfinis.

Ce guide montre comment utiliser cette technique pour appeler l'API Cloud Vision depuis votre application. Cette méthode permettra à tous les utilisateurs authentifiés d'accéder aux services facturés Cloud Vision via votre projet Cloud. Déterminez donc si ce mécanisme d'authentification est suffisant pour votre cas d'utilisation avant de continuer.

Avant que tu commences

Configurez votre projet

  1. Si vous ne l' avez pas déjà ajouté Firebase à votre application, faites - en suivant les étapes du guide de démarrage .
  2. Inclure dans votre Firebase PODFILE: Après avoir installé ou mis à jour votre projet de les pods, assurez - vous d'ouvrir votre projet Xcode en utilisant son .xcworkspace .
  3. Dans votre application, importez Firebase :

    Rapide

    import Firebase

    Objectif c

    @import Firebase;
  4. Si vous n'avez pas encore activé les API basées sur le cloud pour votre projet, faites-le maintenant :

    1. Ouvrez la page par API Firebase ML de la console Firebase.
    2. Si vous ne l' avez pas déjà mis à jour votre projet au plan de tarification Blaze, cliquez sur Mise à jour pour le faire. (Vous serez invité à mettre à niveau uniquement si votre projet ne fait pas partie du plan Blaze.)

      Seuls les projets de niveau Blaze peuvent utiliser des API basées sur le cloud.

    3. Si API cloud computing ne sont pas déjà activé, cliquez sur Activer les API cloud computing.
  5. Configurez vos clés API Firebase existantes pour interdire l'accès à l'API Cloud Vision :
    1. Ouvrez la vérification des pouvoirs page de la console Cloud.
    2. Pour chaque clé API dans la liste, ouvrez la vue d' édition, et dans la section Restrictions clés, ajouter toutes les API disponibles , sauf l'API cloud Vision à la liste.

Déployer la fonction appelable

Ensuite, déployez la fonction Cloud que vous utiliserez pour relier votre application et l'API Cloud Vision. Les functions-samples des functions-samples référentiel contient un exemple que vous pouvez utiliser.

Par défaut, l'accès à l'API Cloud Vision via cette fonction autorisera uniquement les utilisateurs authentifiés de votre application à accéder à l'API Cloud Vision. Vous pouvez modifier la fonction pour différentes exigences.

Pour déployer la fonction :

  1. Clone ou télécharger les fonctions échantillons repo et le changement à la vision-annotate-image répertoire:
    git clone https://github.com/firebase/functions-samples
    cd vision-annotate-image
    
  2. Installer les dépendances:
    cd functions
    npm install
    cd ..
    
  3. Si vous ne disposez pas de la CLI Firebase, installez - le .
  4. Initialiser un projet Firebase dans la vision-annotate-image répertoire. Lorsque vous y êtes invité, sélectionnez votre projet dans la liste.
    firebase init
  5. Déployer la fonction:
    firebase deploy --only functions:annotateImage

Ajouter Firebase Auth à votre application

La fonction appelable déployée ci-dessus rejettera toute demande d'utilisateurs non authentifiés de votre application. Si vous ne l' avez pas déjà fait, vous devrez ajouter Firebase Auth à votre application.

Ajoutez les dépendances nécessaires à votre application

  1. Ajoutez les dépendances pour la bibliothèque de fonctions Firebase à votre PODFILE:
    pod 'Firebase/Functions'
  2. Installer les dépendances:
    pod install

Vous êtes maintenant prêt à commencer à reconnaître le texte dans les images.

1. Préparez l'image d'entrée

Pour appeler Cloud Vision, l'image doit être formatée en tant que chaîne encodée en base64. Pour traiter un UIImage :

Rapide

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

Objectif c

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

2. Appelez la fonction appelable pour reconnaître le texte

Reconnaître des repères dans une image, appelez la fonction appelable passant une demande Nuage JSON Vision .

  1. Tout d'abord, initialisez une instance de Cloud Functions :

    Rapide

    lazy var functions = Functions.functions()
    

    Objectif c

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. Créez la demande. Cloud Vision API prend en charge deux types de détection de texte: TEXT_DETECTION et DOCUMENT_TEXT_DETECTION . Voir le cloud Vision OCR Docs pour la différence entre les deux cas d'utilisation.

    Rapide

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

    Objectif c

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"type": @"TEXT_DETECTION"},
      @"imageContext": @{@"languageHints": @[@"en"]}
    };
    
  3. Enfin, invoquez la fonction :

    Rapide

    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
    }
    

    Objectif 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. Extraire du texte à partir de blocs de texte reconnus

Si l'opération de reconnaissance de texte réussit, une réponse JSON de BatchAnnotateImagesResponse sera retourné dans le résultat de la tâche. Les annotations de texte se trouvent dans le fullTextAnnotation objet.

Vous pouvez obtenir le texte reconnu comme une chaîne dans le text champ. Par exemple:

Rapide

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)")

Objectif c

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

Vous pouvez également obtenir des informations spécifiques aux régions de l'image. Pour chaque block , paragraph , word et symbol , vous pouvez obtenir le texte reconnu dans la région et les coordonnées de délimitation de la région. Par exemple:

Rapide

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
}

Objectif 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];
  }
}