Reconnaître des points de repère de façon sécurisée avec Cloud Vision à l'aide de Firebase Auth et de Firebase Functions sur les plates-formes Apple

Pour appeler une API Google Cloud depuis votre application, vous devez créer un pipeline API REST qui gère les autorisations 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.

Pour créer cette API REST, vous pouvez utiliser Firebase Authentication and Functions, qui vous offre une passerelle gérée et sans serveur vers Les API Google Cloud qui gèrent l'authentification et peuvent être appelées depuis votre application mobile avec SDK prédéfinis.

Ce guide explique 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 de Cloud Vision via votre projet Cloud. Déterminez si ce mécanisme d'authentification est suffisant pour votre cas d'utilisation avant de continuer.

Avant de commencer

Configurer votre projet

Si vous n'avez pas encore ajouté Firebase à votre application, suivez les les étapes décrites dans le guide de démarrage.

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

  1. Dans Xcode, à partir de votre projet d'application ouvert, accédez à File > Add Packages (Fichier > Ajouter des packages).
  2. Lorsque vous y êtes invité, ajoutez le dépôt du SDK des plates-formes Firebase pour Apple :
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. Sélectionnez la bibliothèque Firebase ML.
  5. Ajoutez l'indicateur -ObjC à la section Other Linker Flags (Autres indicateurs Linker) des paramètres de compilation de votre cible.
  6. Lorsque vous avez terminé, Xcode commence à résoudre et à télécharger automatiquement vos dépendances en arrière-plan.

Ensuite, effectuez la configuration dans l'application:

  1. Dans votre application, importez Firebase :

    Swift

    import FirebaseMLModelDownloader

    Objective-C

    @import FirebaseMLModelDownloader;

Plus que quelques étapes de configuration et c'est parti:

  1. Si vous n'avez pas encore activé les API dans le cloud pour votre projet, faites-le dès maintenant:

    1. Ouvrez le Firebase ML page des API de la console Firebase.
    2. Si vous n'avez pas encore fait passer votre projet au forfait Blaze, cliquez sur Pour ce faire, effectuez une mise à niveau. (Vous ne serez invité à effectuer la mise à niveau projet n'est pas inclus dans la formule Blaze.)

      Seuls les projets de niveau Blaze peuvent utiliser des API dans le cloud.

    3. Si les API dans le cloud ne sont pas déjà activées, cliquez sur Activer les services API.
  2. Configurez vos clés API Firebase existantes pour interdire l'accès au cloud API Vision:
    1. Ouvrez la page Identifiants de la console Cloud.
    2. Pour chaque clé API de la liste, ouvrez la vue d'édition, puis dans la vue Section "Restrictions", ajouter toutes les API disponibles à l'exception de Cloud Vision à la liste.

Déployer la fonction appelable

Ensuite, déployez la fonction Cloud que vous utiliserez pour établir un pont entre votre application et l'API Cloud Vision. Le dépôt functions-samples contient un exemple que vous pouvez utiliser.

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

Pour déployer la fonction, procédez comme suit :

  1. Clonez ou téléchargez le dépôt "functions-samples". Accédez au répertoire Node-1st-gen/vision-annotate-image:
    git clone https://github.com/firebase/functions-samples
    cd Node-1st-gen/vision-annotate-image
    
  2. Installez les dépendances :
    cd functions
    npm install
    cd ..
  3. Si vous ne disposez pas de la CLI Firebase, installez-la.
  4. Initialiser un projet Firebase dans 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 requête provenant d'une source non authentifiée les utilisateurs de votre application. Si vous ne l'avez pas déjà fait, vous devez ajouter Firebase Authentifiez-vous dans 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éparer l'image d'entrée

Pour que vous puissiez appeler Cloud Vision, l'image doit être encodée en base64 . Pour traiter une UIImage:

Swift

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

Objective-C

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

2. Appeler la fonction appelable pour reconnaître les points de repère

Pour reconnaître les points de repère dans une image, appelez la fonction appelable en transmettant une Requête Cloud Vision au format JSON.

  1. Commencez par initialiser une instance de Cloud Functions:

    Swift

    lazy var functions = Functions.functions()
    

    Objective-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. Créez une requête en définissant Type sur LANDMARK_DETECTION :

    Swift

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

    Objective-C

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"maxResults": @5, @"type": @"LANDMARK_DETECTION"}
    };
    
  3. Enfin, appelez la fonction :

    Swift

    do {
      let result = try await functions.httpsCallable("annotateImage").call(requestData)
      print(result)
    } catch {
      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]
        }
        // ...
      }
    }
    

    Objective-C

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

3. Obtenir des informations sur les points de repère reconnus

Si l'opération de reconnaissance des points de repère réussit, une réponse JSON de BatchAnnotateImagesResponse est renvoyé dans le résultat de la tâche. Chaque objet du tableau landmarkAnnotations représente un repère 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 ID d'entité Knowledge Graph (le cas échéant) et le score de confiance du match. Exemple :

Swift

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"]
    }
  }
}

Objective-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"];
  }
}