O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Reconhecer texto em imagens com segurança com o Cloud Vision usando Firebase Auth e Functions no iOS

Para chamar uma API do Google Cloud a partir do seu aplicativo, você precisa criar uma API REST intermediária que lida com a autorização e protege valores secretos, como chaves de API. Em seguida, você precisa escrever o código em seu aplicativo móvel para autenticar e se comunicar com esse serviço intermediário.

Uma maneira de criar essa API REST é usando Firebase Authentication and Functions, que oferece um gateway gerenciado e sem servidor para APIs do Google Cloud que lida com autenticação e pode ser chamado de seu aplicativo móvel com SDKs pré-construídos.

Este guia demonstra como usar essa técnica para chamar a API Cloud Vision do seu aplicativo. Este método permitirá que todos os usuários autenticados acessem os serviços faturados do Cloud Vision por meio do seu projeto do Cloud, portanto, antes de prosseguir, considere se esse mecanismo de autenticação é suficiente para seu caso de uso.

Antes de você começar

Configure seu projeto

  1. Se você ainda não tiver adicionado Firebase ao seu aplicativo, fazê-lo seguindo os passos do guia de introdução .
  2. Incluir Firebase em sua Podfile: Depois de instalar ou atualizar Pods do seu projeto, certifique-se para abrir o seu projeto Xcode usando seu .xcworkspace .
  3. Em seu aplicativo, importe o Firebase:

    Rápido

    import Firebase

    Objective-C

    @import Firebase;
  4. Se você ainda não ativou as APIs baseadas em nuvem para o seu projeto, faça-o agora:

    1. Abra a página Firebase ML APIs do console Firebase.
    2. Se você ainda não tiver atualizado o seu projeto para o plano de preços Blaze, clique em Atualizar para fazê-lo. (Você será solicitado a atualizar apenas se o seu projeto não estiver no plano Blaze.)

      Apenas projetos no nível do Blaze podem usar APIs baseadas em nuvem.

    3. Se APIs baseados em nuvem não estiverem ativados, clique em Ativar APIs baseados em nuvem.
  5. Configure suas chaves de API Firebase existentes para impedir o acesso à API Cloud Vision:
    1. Abra a Credenciais página do console Cloud.
    2. Para cada chave API na lista, abra a visualização de edição, e na seção Principais Restrições, adicionar todas as APIs disponíveis, exceto a API Visão da nuvem para a lista.

Implantar a função chamável

Em seguida, implante a função de nuvem que você usará para conectar seu aplicativo e a API Cloud Vision. O functions-samples repositório contém um exemplo que você pode usar.

Por padrão, acessar a API Cloud Vision por meio desta função permitirá que apenas usuários autenticados de seu aplicativo acessem a API Cloud Vision. Você pode modificar a função para diferentes requisitos.

Para implantar a função:

  1. Clone ou baixar as funções-amostras repo e mude para a vision-annotate-image diretório:
    git clone https://github.com/firebase/functions-samples
    cd vision-annotate-image
    
  2. Instalar dependências:
    cd functions
    npm install
    cd ..
    
  3. Se você não tem o Firebase CLI, instalá-lo .
  4. Inicializar um projeto Firebase na vision-annotate-image diretório. Quando solicitado, selecione seu projeto na lista.
    firebase init
  5. Implantar a função:
    firebase deploy --only functions:annotateImage

Adicionar Firebase Auth ao seu aplicativo

A função chamável implantada acima rejeitará qualquer solicitação de usuários não autenticados de seu aplicativo. Se você não tiver feito isso, você precisará adicionar Firebase Auth para a sua aplicação.

Adicione as dependências necessárias ao seu aplicativo

  1. Adicionar as dependências da biblioteca Funções Firebase ao seu Podfile:
    pod 'Firebase/Functions'
  2. Instalar as dependências:
    pod install

Agora você está pronto para começar a reconhecer texto em imagens.

1. Prepare a imagem de entrada

Para chamar o Cloud Vision, a imagem deve ser formatada como uma string codificada em base64. Para processar um UIImage :

Rápido

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. Invoque a função chamável para reconhecer o texto

Para reconhecer marcos em uma imagem, invocar a função que pode ser chamado a passagem de um pedido JSON Visão da nuvem .

  1. Primeiro, inicialize uma instância do Cloud Functions:

    Rápido

    lazy var functions = Functions.functions()
    

    Objective-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. Crie a solicitação. A API Visão da nuvem suporta dois tipos de detecção de texto: TEXT_DETECTION e DOCUMENT_TEXT_DETECTION . Veja as Visão da nuvem de OCR Docs para a diferença entre os dois casos de uso.

    Rápido

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

    Objective-C

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"type": @"TEXT_DETECTION"},
      @"imageContext": @{@"languageHints": @[@"en"]}
    };
    
  3. Finalmente, invoque a função:

    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
    }
    

    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. Extraia texto de blocos de texto reconhecido

Se a operação de reconhecimento de texto bem-sucedido, uma resposta JSON de BatchAnnotateImagesResponse serão devolvidos no resultado da tarefa. As anotações de texto podem ser encontrados na fullTextAnnotation objeto.

Você pode obter o texto reconhecido como uma string no text campo. Por exemplo:

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

Objective-C

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

Você também pode obter informações específicas para regiões da imagem. Para cada block , paragraph , word e symbol , você pode obter o texto reconhecido na região e as coordenadas delimitadoras da região. Por exemplo:

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
}

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