Reconnaître les points de repère en toute sécurité avec Cloud Vision en utilisant Firebase Auth et Functions sur les plates-formes Apple

Pour appeler une API Google Cloud depuis 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 et 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 explique comment utiliser cette technique pour appeler l'API Cloud Vision à partir de votre application. Cette méthode permettra à tous les utilisateurs authentifiés d'accéder aux services facturés de Cloud Vision via votre projet Cloud. Vérifiez donc si ce mécanisme d'authentification est suffisant pour votre cas d'utilisation avant de continuer.

Avant que tu commences

Configurez votre projet

Si vous n'avez pas encore ajouté Firebase à votre application, faites-le en suivant les étapes du guide de démarrage .

Utilisez Swift Package Manager pour installer et gérer les dépendances Firebase.

  1. Dans Xcode, avec votre projet d'application ouvert, accédez à File > Add Packages .
  2. Lorsque vous y êtes invité, ajoutez le dépôt du SDK des plates-formes Apple Firebase :
  3.   https://github.com/firebase/firebase-ios-sdk
  4. Choisissez la bibliothèque Firebase ML.
  5. Une fois terminé, Xcode commencera automatiquement à résoudre et à télécharger vos dépendances en arrière-plan.

Ensuite, effectuez une configuration dans l'application :

  1. Dans votre application, importez Firebase :

    Rapide

    import FirebaseMLModelDownloader

    Objectif c

    @import FirebaseMLModelDownloader;

Encore quelques étapes de configuration, et nous sommes prêts :

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

    1. Ouvrez la page API Firebase ML de la console Firebase.
    2. Si vous n'avez pas encore mis à niveau votre projet vers le plan tarifaire Blaze, cliquez sur Mettre à niveau pour le faire. (Vous serez invité à mettre à niveau uniquement si votre projet n'est pas sur le plan Blaze.)

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

    3. Si les API basées sur le cloud ne sont pas déjà activées, cliquez sur Activer les API basées sur le cloud .
  2. Configurez vos clés d'API Firebase existantes pour interdire l'accès à l'API Cloud Vision :
    1. Ouvrez la page Identifiants de la console Cloud.
    2. Pour chaque clé d'API de la liste, ouvrez la vue de modification et, dans la section Key Restrictions, ajoutez toutes les API disponibles à l' exception de 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. Le référentiel functions-samples contient un exemple que vous pouvez utiliser.

Par défaut, l'accès à l'API Cloud Vision via cette fonction n'autorisera que 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. Clonez ou téléchargez le référentiel functions-samples et accédez au répertoire vision-annotate-image :
    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 n'avez pas la CLI Firebase, installez-la .
  4. Initialisez un projet Firebase dans le répertoire vision-annotate-image . Lorsque vous y êtes invité, sélectionnez votre projet dans la liste.
    firebase init
  5. Déployez 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.

Ajouter les dépendances nécessaires à votre application

Utilisez Swift Package Manager pour installer la bibliothèque Cloud Functions for Firebase.

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

Pour appeler Cloud Vision, l'image doit être au format d'une chaîne encodée en base64. Pour traiter une 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 les points de repère

Pour reconnaître des points de repère dans une image, appelez la fonction appelable en transmettant une requête JSON Cloud 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 une requête avec Type défini sur LANDMARK_DETECTION :

    Rapide

    let requestData = [
      "image": ["content": base64encodedImage],
      "features": ["maxResults": 5, "type": "LANDMARK_DETECTION"]
    ]
    

    Objectif c

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"maxResults": @5, @"type": @"LANDMARK_DETECTION"}
    };
    
  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. Obtenez des informations sur les monuments reconnus

Si l'opération de reconnaissance du point de repère réussit, une réponse JSON de BatchAnnotateImagesResponse sera renvoyée dans le résultat de la tâche. Chaque objet du tableau landmarkAnnotations représente un point de repère qui a été reconnu dans l'image. Pour chaque point de repère, vous pouvez obtenir ses coordonnées de délimitation dans l'image d'entrée, le nom du point de repère, sa latitude et sa longitude, son identifiant d'entité Knowledge Graph (si disponible) et le score de confiance de la correspondance. Par exemple:

Rapide

if let labelArray = (result?.data as? [String: Any])?["landmarkAnnotations"] as? [[String:Any]] {
  for labelObj in labelArray {
    let landmarkName = labelObj["description"]
    let entityId = labelObj["mid"]
    let score = labelObj["score"]
    let bounds = labelObj["boundingPoly"]
    // Multiple locations are possible, e.g., the location of the depicted
    // landmark and the location the picture was taken.
    guard let locations = labelObj["locations"] as? [[String: [String: Any]]] else { continue }
    for location in locations {
      let latitude = location["latLng"]?["latitude"]
      let longitude = location["latLng"]?["longitude"]
    }
  }
}

Objectif c

NSArray *labelArray = result.data[@"landmarkAnnotations"];
for (NSDictionary *labelObj in labelArray) {
  NSString *landmarkName = labelObj[@"description"];
  NSString *entityId = labelObj[@"mid"];
  NSNumber *score = labelObj[@"score"];
  NSArray *bounds = labelObj[@"boundingPoly"];
  // Multiple locations are possible, e.g., the location of the depicted
  // landmark and the location the picture was taken.
  NSArray *locations = labelObj[@"locations"];
  for (NSDictionary *location in locations) {
    NSNumber *latitude = location[@"latLng"][@"latitude"];
    NSNumber *longitude = location[@"latLng"][@"longitude"];
  }
}