Reconheça pontos de referência com segurança com o Cloud Vision usando Firebase Auth e Functions em plataformas Apple

Para chamar uma API do Google Cloud no seu aplicativo, você precisa criar uma API REST intermediária que processe a autorização e proteja 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 é usar o Firebase Authentication and Functions, que oferece um gateway gerenciado e sem servidor para APIs do Google Cloud que gerenciam a autenticação e podem ser chamados de seu aplicativo móvel com SDKs pré-criados.

Este guia demonstra como usar essa técnica para chamar a API Cloud Vision do seu aplicativo. Esse 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, considere se esse mecanismo de autenticação é suficiente para seu caso de uso antes de continuar.

Antes de você começar

Configure seu projeto

Se você ainda não adicionou o Firebase ao seu aplicativo, faça isso seguindo as etapas do guia de primeiros passos .

Use o Swift Package Manager para instalar e gerenciar dependências do Firebase.

  1. No Xcode, com o projeto do seu aplicativo aberto, navegue até File > Add Packages .
  2. Quando solicitado, adicione o repositório SDK das plataformas Apple do Firebase:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. Escolha a biblioteca Firebase ML.
  5. Adicione o sinalizador -ObjC à seção Outros sinalizadores de vinculador das configurações de compilação do seu destino.
  6. Quando terminar, o Xcode começará automaticamente a resolver e baixar suas dependências em segundo plano.

Em seguida, execute algumas configurações no aplicativo:

  1. No seu aplicativo, importe o Firebase:

    Rápido

    import FirebaseMLModelDownloader

    Objetivo-C

    @import FirebaseMLModelDownloader;

Mais algumas etapas de configuração e estamos prontos para começar:

  1. Se você ainda não habilitou APIs baseadas em nuvem para seu projeto, faça-o agora:

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

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

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

Implantar a função que pode ser chamada

Em seguida, implante a função do Cloud que você usará para conectar seu aplicativo e a API Cloud Vision. O repositório de functions-samples 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 do seu aplicativo acessem a API Cloud Vision. Você pode modificar a função para diferentes requisitos.

Para implantar a função:

  1. Clone ou baixe o repositório de amostras de funções e mude para o diretório Node-1st-gen/vision-annotate-image :
    git clone https://github.com/firebase/functions-samples
    cd Node-1st-gen/vision-annotate-image
    
  2. Instale dependências:
    cd functions
    npm install
    cd ..
    
  3. Se você não tiver a CLI do Firebase, instale-a .
  4. Inicialize um projeto do Firebase no diretório vision-annotate-image . Quando solicitado, selecione seu projeto na lista.
    firebase init
  5. Implante a função:
    firebase deploy --only functions:annotateImage

Adicione o Firebase Auth ao seu aplicativo

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

Adicione as dependências necessárias ao seu aplicativo

Use o Swift Package Manager para instalar a biblioteca Cloud Functions para Firebase.

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.0) else { return }
let base64encodedImage = imageData.base64EncodedString()

Objetivo-C

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

2. Invoque a função que pode ser chamada para reconhecer pontos de referência

Para reconhecer pontos de referência em uma imagem, invoque a função que pode ser chamada passando uma solicitação JSON Cloud Vision .

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

    Rápido

    lazy var functions = Functions.functions()
    

    Objetivo-C

    @property(strong, nonatomic) FIRFunctions *functions;
    
  2. Crie uma solicitação com Type definido como LANDMARK_DETECTION :

    Rápido

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

    Objetivo-C

    NSDictionary *requestData = @{
      @"image": @{@"content": base64encodedImage},
      @"features": @{@"maxResults": @5, @"type": @"LANDMARK_DETECTION"}
    };
    
  3. Finalmente, invoque a função:

    Rápido

    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]
        }
        // ...
      }
    }
    

    Objetivo-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. Obtenha informações sobre os pontos de referência reconhecidos

Se a operação de reconhecimento de ponto de referência for bem-sucedida, uma resposta JSON de BatchAnnotateImagesResponse será retornada no resultado da tarefa. Cada objeto na landmarkAnnotations representa um ponto de referência que foi reconhecido na imagem. Para cada ponto de referência, você pode obter suas coordenadas delimitadoras na imagem de entrada, o nome do ponto de referência, sua latitude e longitude, seu ID de entidade do Knowledge Graph (se disponível) e a pontuação de confiança da correspondência. Por exemplo:

Rápido

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

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