Para chamar uma API do Google Cloud usando seu app, crie uma API REST intermediária que gerencie a autorização e proteja valores secretos, como chaves de API. Em seguida, escreva o código no seu app para dispositivos móveis a fim de autenticar e se comunicar com esse serviço intermediário.
Uma maneira de criar essa API REST é usar o Firebase Authentication e o Functions, que oferecem um gateway gerenciado sem servidor para as APIs do Google Cloud, que processa a autenticação e pode ser chamado no seu app para dispositivos móveis com SDKs pré-criados.
Neste guia, você verá como usar essa técnica para chamar a API Cloud Vision do seu app. Esse método permitirá que todos os usuários autenticados acessem os serviços faturados do Cloud Vision no projeto do Cloud. Sendo assim, considere se esse mecanismo de autenticação é suficiente para seu caso de uso antes de continuar.
Antes de começar
Configurar seu projeto
Se você ainda não adicionou o Firebase ao seu app, siga as etapas no Guia explicativo.Use o Swift Package Manager para instalar e gerenciar as dependências do Firebase.
- No Xcode, com seu projeto do app aberto, navegue até File > Add Packages.
- Quando solicitado, adicione o repositório do SDK do Firebase para as plataformas Apple:
- Escolha a biblioteca Firebase ML.
- Adicione a sinalização
-ObjC
à seção Outras sinalizações do vinculador das configurações de compilação do destino. - Quando terminar, o Xcode começará a resolver e fazer o download das dependências em segundo plano automaticamente.
https://github.com/firebase/firebase-ios-sdk.git
Em seguida, faça algumas configurações no app:
- Importe o Firebase para seu app:
Swift
import FirebaseMLModelDownloader
Objective-C
@import FirebaseMLModelDownloader;
Mais algumas etapas de configuração e estaremos prontos para começar:
-
Se você ainda não ativou APIs baseadas em nuvem para seu projeto, siga estas etapas:
- Abra a página de APIs do Firebase ML do console do Firebase.
-
Se você ainda não fez o upgrade do seu projeto para o plano de preços Blaze, clique em Fazer upgrade. Você só vai receber uma mensagem para fazer upgrade se o projeto não estiver no plano Blaze.
Apenas projetos no nível Blaze podem usar APIs baseadas na nuvem.
- Caso as APIs baseadas na nuvem ainda não estejam ativadas, clique em Ativar APIs baseadas na nuvem.
- Configure as chaves de API do Firebase para proibir o acesso à API
Cloud Vision:
- Abra a página Credenciais do Console do Cloud.
- 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.
Como implantar a função chamável
Agora, você implantará a função do Cloud que será usada para conectar seu app e a API
Cloud Vision. O repositório functions-samples
contém um exemplo que
pode ser usado.
Por padrão, essa função permitirá que apenas usuários autenticados do seu app acessem a API Cloud Vision. É possível modificar a função para requisitos diferentes.
Para implantar a função, siga estas etapas:
- Clone ou faça o download do repositório functions-samples
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
- Instale as dependências:
cd functions
npm install
cd ..
- Se você não tiver a CLI do Firebase, faça a instalação.
- Inicialize um novo projeto do Firebase no diretório
vision-annotate-image
. Quando solicitado, selecione o projeto na lista.firebase init
- Implante a função:
firebase deploy --only functions:annotateImage
Adicionar o Firebase Auth ao seu app
A função chamável implementada acima rejeitará qualquer solicitação de usuários não autenticados do seu app. Adicione o Firebase Authentication ao app, caso ainda não tenha feito isso.
Adicionar as dependências necessárias ao app
Use o Swift Package Manager para instalar a biblioteca do Cloud Functions para Firebase.
Agora você já pode reconhecer texto em imagens.
1. Preparar a imagem de entrada
Para chamar o Cloud Vision, a imagem precisa ser formatada como uma string codificada em base64. Para processar umUIImage
:
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. Invocar a função chamável para reconhecer texto
Para reconhecer pontos de referência em uma imagem, invoque a função chamável transmitindo uma solicitação JSON do Cloud Vision.Inicialize uma instância do Cloud Functions:
Swift
lazy var functions = Functions.functions()
Objective-C
@property(strong, nonatomic) FIRFunctions *functions;
Crie a solicitação. A API Cloud Vision é compatível com dois tipos de detecção de texto:
TEXT_DETECTION
eDOCUMENT_TEXT_DETECTION
. Consulte os Documentos do OCR do Cloud Vision para ver a diferença entre os dois casos de uso.Swift
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"]} };
Por fim, invoque a função:
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. Extrair texto de blocos de texto reconhecido
Se a operação de reconhecimento de texto for bem-sucedida, uma resposta JSON de
BatchAnnotateImagesResponse
será retornada no resultado da tarefa. As anotações de texto podem ser encontradas no
objeto fullTextAnnotation
.
É possível conseguir o texto reconhecido como uma string no campo text
. Exemplo:
Swift
let annotation = result.flatMap { $0.data as? [String: Any] }
.flatMap { $0["fullTextAnnotation"] }
.flatMap { $0 as? [String: Any] }
guard let annotation = annotation else { return }
if let text = annotation["text"] as? String {
print("Complete annotation: \(text)")
}
Objective-C
NSDictionary *annotation = result.data[@"fullTextAnnotation"];
if (!annotation) { return; }
NSLog(@"\nComplete annotation:");
NSLog(@"\n%@", annotation[@"text"]);
Também é possível receber informações específicas das regiões da imagem. Para cada objeto block
,
paragraph
, word
e symbol
, é possível receber o texto reconhecido na região
e as coordenadas delimitadoras da região. Exemplo:
Swift
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];
}
}