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

Reconozca texto en imágenes de forma segura con Cloud Vision mediante Firebase Auth y Functions en iOS

Para llamar a una API de Google Cloud desde su aplicación, debe crear una API REST intermedia que maneje la autorización y proteja los valores secretos, como las claves de la API. Luego, debe escribir código en su aplicación móvil para autenticarse y comunicarse con este servicio intermedio.

Una forma de crear esta API REST es mediante el uso de Firebase Authentication and Functions, que le brinda una puerta de enlace administrada y sin servidor a las API de Google Cloud que maneja la autenticación y se puede llamar desde su aplicación móvil con SDK prediseñados.

Esta guía demuestra cómo usar esta técnica para llamar a la API de Cloud Vision desde su aplicación. Este método permitirá que todos los usuarios autenticados accedan a los servicios facturados de Cloud Vision a través de su proyecto de Cloud, así que considere si este mecanismo de autenticación es suficiente para su caso de uso antes de continuar.

Antes de que empieces

Configura tu proyecto

  1. Si aún no lo ha añadido Firebase a su aplicación, hacerlo siguiendo los pasos de la guía de instalación inicial .
  2. Incluir en su Firebase PODFILE: Después de instalar o actualizar las vainas de su proyecto, asegúrese de abrir su proyecto Xcode utilizando su .xcworkspace .
  3. En su aplicación, importe Firebase:

    Rápido

    import Firebase

    C objetivo

    @import Firebase;
  4. Si aún no ha habilitado las API basadas en la nube para su proyecto, hágalo ahora:

    1. Abra la página Firebase ML API de la consola Firebase.
    2. Si todavía no ha actualizado su proyecto para el plan de precios Blaze, haga clic en Actualizar para hacerlo. (Se le pedirá que actualice solo si su proyecto no está en el plan Blaze).

      Solo los proyectos de nivel Blaze pueden usar API basadas en la nube.

    3. Si las API basadas en la nube ya no están habilitados, haga clic en Habilitar APIs basadas en la nube.
  5. Configura tus claves de API de Firebase existentes para no permitir el acceso a la API de Cloud Vision:
    1. Abra la Credenciales página de la consola de la nube.
    2. Para cada clave de API en la lista, abra la vista de edición, y en la sección Restricciones clave, agregar todas las APIs disponibles, excepto la API de la nube de la visión a la lista.

Implementar la función invocable

A continuación, implemente la función de la nube que usará para conectar su aplicación y la API de Cloud Vision. La functions-samples repositorio contiene un ejemplo que puede utilizar.

De forma predeterminada, acceder a la API de Cloud Vision a través de esta función permitirá que solo los usuarios autenticados de su aplicación accedan a la API de Cloud Vision. Puede modificar la función para diferentes requisitos.

Para implementar la función:

  1. Clon o descargar las funciones muestras repo y el cambio a la vision-annotate-image directorio:
    git clone https://github.com/firebase/functions-samples
    cd vision-annotate-image
    
  2. Instalar las dependencias:
    cd functions
    npm install
    cd ..
    
  3. Si usted no tiene la base del fuego CLI, instalarlo .
  4. Inicializar un proyecto Firebase en la vision-annotate-image directorio. Cuando se le solicite, seleccione su proyecto en la lista.
    firebase init
  5. Implementar la función:
    firebase deploy --only functions:annotateImage

Agrega Firebase Auth a tu aplicación

La función invocable implementada anteriormente rechazará cualquier solicitud de usuarios no autenticados de su aplicación. Si no lo ha hecho, tendrá que añadir Firebase de autenticación para su aplicación.

Agrega las dependencias necesarias a tu aplicación

  1. Añadir las dependencias de las funciones de biblioteca Firebase a su PODFILE:
    pod 'Firebase/Functions'
  2. Instalar las dependencias:
    pod install

Ahora está listo para comenzar a reconocer texto en imágenes.

1. Prepare la imagen de entrada

Para llamar a Cloud Vision, la imagen debe tener el formato de una cadena codificada en base64. Para procesar una UIImage :

Rápido

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

C objetivo

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

2. Invocar la función de llamada para reconocer texto

Reconocer puntos de referencia en una imagen, invocar la función exigible pasando una solicitud JSON Nube Vision .

  1. Primero, inicializa una instancia de Cloud Functions:

    Rápido

    lazy var functions = Functions.functions()
    

    C objetivo

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. Crea la solicitud. La API Nube Vision es compatible con dos tipos de detección de texto: TEXT_DETECTION y DOCUMENT_TEXT_DETECTION . Ver las nublan la vista de OCR Docs para la diferencia entre los dos casos de uso.

    Rápido

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

    C objetivo

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"type": @"TEXT_DETECTION"},
      @"imageContext": @{@"languageHints": @[@"en"]}
    };
    
  3. Finalmente, invoca la función:

    Rápido

    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
    }
    

    C objetivo

    [[_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. Extraiga texto de bloques de texto reconocido

Si la operación tiene éxito el reconocimiento de texto, una respuesta JSON de BatchAnnotateImagesResponse será devuelto en el resultado de la tarea. Las anotaciones de texto se pueden encontrar en el fullTextAnnotation objeto.

Usted puede obtener el texto reconocido como una cadena en el text de campo. Por ejemplo:

Rápido

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

C objetivo

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

También puede obtener información específica de las regiones de la imagen. Para cada block , paragraph , word y symbol , se puede obtener el texto reconocido en la región y las coordenadas límite de la región. Por ejemplo:

Rápido

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
}

C objetivo

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