Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Reconoce puntos de referencia de forma segura con Cloud Vision mediante Firebase Auth y Functions en iOS

Para llamar a una API de Google Cloud desde tu app, debes crear una API de REST intermedia que maneje la autorización y proteja los valores secretos, como las claves de API. Luego, debes escribir código en tu app para dispositivos móviles a fin de autenticarte en este servicio intermedio y comunicarte con él.

Una forma de crear esta API de REST es usar Firebase Authentication y Functions, lo que te brinda una puerta de enlace administrada y sin servidores a las API de Google Cloud que controla la autenticación y se puede llamar desde tu app para dispositivos móviles con SDK precompilados.

En esta guía, se muestra cómo usar esta técnica para llamar a la API de Cloud Vision desde tu app. Este método permitirá que todos los usuarios autenticados accedan a los servicios facturados de Cloud Vision a través de tu proyecto de Cloud, por lo que debes considerar si este mecanismo de autenticación es suficiente para tu caso de uso antes de continuar.

Antes de comenzar

Configura tu proyecto

  1. Si aún no has agregado Firebase a tu app, sigue los pasos en la guía de introducción para hacerlo.
  2. Incluye Firebase en el Podfile: Después de instalar o actualizar los Pods de tu proyecto, asegúrate de abrir el proyecto de Xcode con su .xcworkspace.
  3. En tu app, importa Firebase:

    Swift

    import Firebase

    Objective-C

    @import Firebase;
  4. Si aún no habilitaste las API basadas en la nube en tu proyecto, hazlo de la siguiente manera:

    1. Abre la página de API de AA de Firebase de Firebase console.
    2. Si todavía no actualizaste tu proyecto a un plan de precios Blaze, haz clic en Actualizar para hacerlo (se te pedirá que realices la actualización únicamente si tu proyecto no está en el plan Blaze).

      Solo los proyectos con un plan Blaze pueden usar las API de Cloud.

    3. Si las API de Cloud no están habilitadas, haz clic en Habilitar las API de Cloud.
  5. Configura tus claves de API de Firebase existentes para inhabilitar el acceso a la API de Cloud Vision siguiendo los pasos que se indican a continuación:
    1. Abre la página Credenciales de Cloud Console.
    2. Para cada clave de API de la lista, abre la vista de edición y, en la sección Restricciones de claves, agrega a la lista todas las API disponibles excepto la de Cloud Vision.

Implementa la función que admite llamadas

A continuación, implementa la Cloud Function que usarás para conectar tu app y la API de Cloud Vision. El repositorio functions-samples contiene un ejemplo que puedes usar.

De forma predeterminada, el acceso a la API de Cloud Vision a través de esta función permitirá que solo los usuarios autenticados de tu app accedan a la API de Cloud Vision. Puedes modificar la función para diferentes requisitos.

Sigue estos pasos para implementar la función:

  1. Clona o descarga functions-samples repo y cambia al directorio vision-annotate-image:
    git clone https://github.com/firebase/functions-samples
    cd vision-annotate-image
    
  2. Instala las dependencias:
    cd functions
    npm install
    cd ..
    
  3. Si no tienes Firebase CLI, instálalo.
  4. Inicializa un proyecto de Firebase en el directorio vision-annotate-image. Cuando se te solicite, selecciona tu proyecto en la lista.
    firebase init
  5. Sigue estos pasos para implementar la función:
    firebase deploy --only functions:annotateImage

Agrega Firebase Auth a tu app

La función que admite llamadas implementada anteriormente rechazará todas las solicitudes de usuarios no autenticados de tu app. Si aún no lo has hecho, tendrás que agregar Firebase Auth a tu app.

Agrega las dependencias necesarias a tu app

  1. Agrega las dependencias de la biblioteca de Firebase Functions a tu Podfile:
    pod 'Firebase/Functions'
  2. Instala las dependencias:
    pod install

1. Prepara la imagen de entrada

Para llamar a Cloud Vision, la imagen debe tener el formato de una string codificada en base64. Para procesar un UIImage, sigue estos pasos:

Swift

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. Invoca la función que admite llamadas para reconocer puntos de referencia

Para reconocer puntos de referencia en una imagen, invoca la función que admite llamadas pasando una solicitud de JSON de Cloud Vision.

  1. Primero, inicializa una instancia de Cloud Functions:

    Swift

    lazy var functions = Functions.functions()
    

    Objective-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. Luego, crea una solicitud con el Tipo configurado como 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. Finalmente, invoca la función:

    Swift

    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. Obtén información sobre los puntos de referencia reconocidos

Si la operación de reconocimiento de puntos de referencia se ejecuta correctamente, se mostrará una respuesta JSON de BatchAnnotateImagesResponse en el resultado de la tarea. Cada objeto en el array landmarkAnnotations representa un punto de referencia que se reconoció en la imagen. Por cada punto de referencia, puedes obtener las coordenadas de los límites en la imagen de entrada, el nombre, la latitud y la longitud, el ID de entidad del Gráfico de conocimiento (si está disponible) y la puntuación de confianza de la coincidencia. Por ejemplo:

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