É possível usar o Kit de ML para reconhecimento de texto em imagens. Esse Kit tem uma API de uso geral que reconhece texto em imagens, como o texto de uma placa de rua, e uma API otimizada para reconhecer texto de documentos. A API de uso geral tem modelos baseados no dispositivo e na nuvem. O reconhecimento de texto em documentos está disponível apenas como modelo baseado na nuvem. Consulte a visão geral para uma comparação entre esses dois tipos de modelos.
Antes de começar
- Se você ainda não adicionou o Firebase ao seu app, siga as etapas no guia de iniciação.
- Inclua as bibliotecas do kit de ML no seu Podfile:
pod 'Firebase/MLVision', '6.25.0' # If using an on-device API: pod 'Firebase/MLVisionTextModel', '6.25.0'
Depois de instalar ou atualizar os pods do seu projeto, abra o projeto do Xcode usando o.xcworkspace
. - Importe o Firebase para seu app:
Swift
import Firebase
Objective-C
@import Firebase;
-
Se você quiser usar o modelo baseado em nuvem e ainda não tiver ativado as APIs baseadas em nuvem para seu projeto, siga estas etapas:
- Abra a página APIs do Kit de ML no Console do Firebase.
-
Se você ainda não fez o upgrade de seu projeto para um plano de preços do Blaze, clique em Fazer upgrade para fazer isso. 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.
Se você quiser usar apenas o modelo no dispositivo, pule esta etapa.
Agora você já pode reconhecer texto em imagens.
Diretrizes de imagens de entrada
-
Para que o Kit de ML reconheça o texto com precisão, as imagens de entrada devem conter texto representado por dados de pixel suficientes. O ideal é que, para texto em latim, cada caractere tenha pelo menos 16 x 16 pixels. Para texto em chinês, japonês e coreano (com suporte somente para APIs baseadas em nuvem), cada caractere deve ter 24 x 24 pixels. Para todos os idiomas, geralmente não há melhorias de precisão em usar caracteres maiores que 24 x 24 pixels.
Por exemplo, uma imagem de 640 x 480 pixels pode funcionar para digitalizar um cartão de visita que ocupe toda a largura da imagem. Para digitalizar um documento impresso em papel de tamanho carta, talvez seja necessária uma imagem de 720 x 1280 pixels.
-
O foco inadequado da imagem pode prejudicar a precisão do reconhecimento de texto. Se você não está conseguindo resultados aceitáveis, peça para o usuário recapturar a imagem.
-
Se você estiver fazendo reconhecimento de texto em um aplicativo em tempo real, considere as dimensões gerais das imagens de entrada. Já que imagens menores podem ser processadas mais rapidamente, para reduzir a latência, capture imagens em resoluções mais baixas, tendo em mente os requisitos de precisão acima, e verifique se o texto está ocupando o máximo possível da imagem. Consulte também Dicas para melhorar o desempenho em tempo real.
Reconhecer texto em imagens
Para reconhecer texto em imagens usando o modelo baseado no dispositivo ou na nuvem, execute o reconhecedor de texto conforme descrito nas etapas a seguir.
1. Executar o reconhecedor de texto
Transmita a imagem como "UIImage" ou "CMSampleBufferRef" para o método process(_:completion:) de "VisionTextRecognizer":- Receba uma instância de
VisionTextRecognizer
chamandoonDeviceTextRecognizer
oucloudTextRecognizer
:Swift
Para usar o modelo no dispositivo:
let vision = Vision.vision() let textRecognizer = vision.onDeviceTextRecognizer()
Para usar o modelo de nuvem:
let vision = Vision.vision() let textRecognizer = vision.cloudTextRecognizer() // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages let options = VisionCloudTextRecognizerOptions() options.languageHints = ["en", "hi"] let textRecognizer = vision.cloudTextRecognizer(options: options)
Objective-C
Para usar o modelo no dispositivo:
FIRVision *vision = [FIRVision vision]; FIRVisionTextRecognizer *textRecognizer = [vision onDeviceTextRecognizer];
Para usar o modelo de nuvem:
FIRVision *vision = [FIRVision vision]; FIRVisionTextRecognizer *textRecognizer = [vision cloudTextRecognizer]; // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages FIRVisionCloudTextRecognizerOptions *options = [[FIRVisionCloudTextRecognizerOptions alloc] init]; options.languageHints = @[@"en", @"hi"]; FIRVisionTextRecognizer *textRecognizer = [vision cloudTextRecognizerWithOptions:options];
-
Crie um objeto
VisionImage
usando umUIImage
ou umCMSampleBufferRef
.Para usar um
UIImage
:- Se necessário, gire a imagem para que a propriedade
imageOrientation
seja.up
. - Crie um objeto
VisionImage
usando aUIImage
com a rotação correta. Não especifique metadados de rotação: o valor padrão,.topLeft
, precisa ser usado.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Para usar um
CMSampleBufferRef
:-
Crie um objeto
VisionImageMetadata
que especifique a orientação dos dados da imagem contidos no bufferCMSampleBufferRef
.Para ver a orientação da imagem:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Objective-C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Em seguida, crie o objeto de metadados:
Swift
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Crie um objeto
VisionImage
usando o objetoCMSampleBufferRef
e os metadados de rotação:Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Se necessário, gire a imagem para que a propriedade
-
Em seguida, transmita a imagem para o método
process(_:completion:)
:Swift
textRecognizer.process(visionImage) { result, error in guard error == nil, let result = result else { // ... return } // Recognized text }
Objective-C
[textRecognizer processImage:image completion:^(FIRVisionText *_Nullable result, NSError *_Nullable error) { if (error != nil || result == nil) { // ... return; } // Recognized text }];
2. Extrair texto de blocos de texto reconhecido
Se a operação de reconhecimento de texto for bem-sucedida, ela retornará um objeto [`VisionText`][VisionText]. Um objeto "VisionText" contém o texto completo reconhecido na imagem e zero ou mais objetos [`VisionTextBlock`][VisionTextBlock]. Cada "VisionTextBlock" representa um bloco de texto retangular, que contém zero ou mais objetos ["VisionTextLine"] [VisionTextLine]. Cada objeto "VisionTextLine" contém zero ou mais objetos [`VisionTextElement`][VisionTextElement], que representam palavras e entidades semelhantes (datas, números e assim por diante). Para cada "VisionTextBlock", "VisionTextLine" e "VisionTextElement", você pode obter o texto reconhecido na região e as coordenadas delimitadoras da região. Exemplo:Swift
let resultText = result.text for block in result.blocks { let blockText = block.text let blockConfidence = block.confidence let blockLanguages = block.recognizedLanguages let blockCornerPoints = block.cornerPoints let blockFrame = block.frame for line in block.lines { let lineText = line.text let lineConfidence = line.confidence let lineLanguages = line.recognizedLanguages let lineCornerPoints = line.cornerPoints let lineFrame = line.frame for element in line.elements { let elementText = element.text let elementConfidence = element.confidence let elementLanguages = element.recognizedLanguages let elementCornerPoints = element.cornerPoints let elementFrame = element.frame } } }
Objective-C
NSString *resultText = result.text; for (FIRVisionTextBlock *block in result.blocks) { NSString *blockText = block.text; NSNumber *blockConfidence = block.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *blockLanguages = block.recognizedLanguages; NSArray<NSValue *> *blockCornerPoints = block.cornerPoints; CGRect blockFrame = block.frame; for (FIRVisionTextLine *line in block.lines) { NSString *lineText = line.text; NSNumber *lineConfidence = line.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *lineLanguages = line.recognizedLanguages; NSArray<NSValue *> *lineCornerPoints = line.cornerPoints; CGRect lineFrame = line.frame; for (FIRVisionTextElement *element in line.elements) { NSString *elementText = element.text; NSNumber *elementConfidence = element.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *elementLanguages = element.recognizedLanguages; NSArray<NSValue *> *elementCornerPoints = element.cornerPoints; CGRect elementFrame = element.frame; } } }
Dicas para melhorar o desempenho em tempo real
Se você quiser usar o modelo no dispositivo para reconhecer texto em um aplicativo em tempo real, siga estas diretrizes para conseguir as melhores taxas de quadros:
- Limite as chamadas ao reconhecedor de texto. Se um novo quadro de vídeo ficar disponível durante a execução do reconhecedor de texto, descarte esse quadro.
- Se você estiver usando a saída do reconhecedor de texto para sobrepor elementos gráficos na imagem de entrada, primeiro acesse o resultado do Kit de ML e, em seguida, renderize a imagem e a sobreposição em uma única etapa. Ao fazer isso, você renderiza a superfície de exibição apenas uma vez para cada quadro de entrada. Consulte as classes previewOverlayView e FIRDetectionOverlayView no app de amostra da demonstração para ver um exemplo.
- Capture imagens em uma resolução menor. No entanto, lembre-se também dos requisitos de dimensão de imagem da API.
Próximas etapas
- Antes de implantar em produção um aplicativo que usa uma API do Cloud, é preciso seguir mais algumas etapas para evitar ou atenuar o efeito do acesso não autorizado à API.
Reconhecer texto em imagens de documentos
Para reconhecer o texto de um documento, configure e execute o documento baseado na nuvem conforme descrito nas instruções abaixo.
A API de reconhecimento de texto em documentos descrita abaixo tem uma interface desenvolvida para trabalhar com imagens de documentos. No entanto, se você preferir a interface fornecida pela API de texto em imagem, poderá usá-la para digitalizar documentos. Para fazer isso, basta configurar o reconhecedor de texto em nuvem para usar o modelo de texto denso.
Para usar a API de reconhecimento de texto em documentos, siga estas etapas:
1. Executar o reconhecedor de texto
Transmita a imagem como umUIImage
ou um CMSampleBufferRef
para o método process(_:completion:)
do VisionDocumentTextRecognizer
:
- Para receber uma instância de
VisionDocumentTextRecognizer
, chamecloudDocumentTextRecognizer
.Swift
let vision = Vision.vision() let textRecognizer = vision.cloudDocumentTextRecognizer() // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages let options = VisionCloudDocumentTextRecognizerOptions() options.languageHints = ["en", "hi"] let textRecognizer = vision.cloudDocumentTextRecognizer(options: options)
Objective-C
FIRVision *vision = [FIRVision vision]; FIRVisionDocumentTextRecognizer *textRecognizer = [vision cloudDocumentTextRecognizer]; // Or, to provide language hints to assist with language detection: // See https://cloud.google.com/vision/docs/languages for supported languages FIRVisionCloudDocumentTextRecognizerOptions *options = [[FIRVisionCloudDocumentTextRecognizerOptions alloc] init]; options.languageHints = @[@"en", @"hi"]; FIRVisionDocumentTextRecognizer *textRecognizer = [vision cloudDocumentTextRecognizerWithOptions:options];
-
Crie um objeto
VisionImage
usando umUIImage
ou umCMSampleBufferRef
.Para usar um
UIImage
:- Se necessário, gire a imagem para que a propriedade
imageOrientation
seja.up
. - Crie um objeto
VisionImage
usando aUIImage
com a rotação correta. Não especifique metadados de rotação: o valor padrão,.topLeft
, precisa ser usado.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Para usar um
CMSampleBufferRef
:-
Crie um objeto
VisionImageMetadata
que especifique a orientação dos dados da imagem contidos no bufferCMSampleBufferRef
.Para ver a orientação da imagem:
Swift
func imageOrientation( deviceOrientation: UIDeviceOrientation, cameraPosition: AVCaptureDevice.Position ) -> VisionDetectorImageOrientation { switch deviceOrientation { case .portrait: return cameraPosition == .front ? .leftTop : .rightTop case .landscapeLeft: return cameraPosition == .front ? .bottomLeft : .topLeft case .portraitUpsideDown: return cameraPosition == .front ? .rightBottom : .leftBottom case .landscapeRight: return cameraPosition == .front ? .topRight : .bottomRight case .faceDown, .faceUp, .unknown: return .leftTop } }
Objective-C
- (FIRVisionDetectorImageOrientation) imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation cameraPosition:(AVCaptureDevicePosition)cameraPosition { switch (deviceOrientation) { case UIDeviceOrientationPortrait: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationLeftTop; } else { return FIRVisionDetectorImageOrientationRightTop; } case UIDeviceOrientationLandscapeLeft: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationBottomLeft; } else { return FIRVisionDetectorImageOrientationTopLeft; } case UIDeviceOrientationPortraitUpsideDown: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationRightBottom; } else { return FIRVisionDetectorImageOrientationLeftBottom; } case UIDeviceOrientationLandscapeRight: if (cameraPosition == AVCaptureDevicePositionFront) { return FIRVisionDetectorImageOrientationTopRight; } else { return FIRVisionDetectorImageOrientationBottomRight; } default: return FIRVisionDetectorImageOrientationTopLeft; } }
Em seguida, crie o objeto de metadados:
Swift
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-C
FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init]; AVCaptureDevicePosition cameraPosition = AVCaptureDevicePositionBack; // Set to the capture device you used. metadata.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
- Crie um objeto
VisionImage
usando o objetoCMSampleBufferRef
e os metadados de rotação:Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Se necessário, gire a imagem para que a propriedade
-
Em seguida, transmita a imagem para o método
process(_:completion:)
:Swift
textRecognizer.process(visionImage) { result, error in guard error == nil, let result = result else { // ... return } // Recognized text }
Objective-C
[textRecognizer processImage:image completion:^(FIRVisionDocumentText *_Nullable result, NSError *_Nullable error) { if (error != nil || result == nil) { // ... return; } // Recognized text }];
2. Extrair texto de blocos de texto reconhecido
Se a operação de reconhecimento de texto for bem-sucedida, ela retornará um objetoVisionDocumentText
. Um objeto VisionDocumentText
contém o texto completo reconhecido na imagem e uma hierarquia de objetos que refletem a estrutura do documento reconhecido:
Para cada objeto VisionDocumentTextBlock
, VisionDocumentTextParagraph
, VisionDocumentTextWord
e VisionDocumentTextSymbol
, é possível obter o texto reconhecido na região e as coordenadas delimitadoras da região.
Exemplo:
Swift
let resultText = result.text for block in result.blocks { let blockText = block.text let blockConfidence = block.confidence let blockRecognizedLanguages = block.recognizedLanguages let blockBreak = block.recognizedBreak let blockCornerPoints = block.cornerPoints let blockFrame = block.frame for paragraph in block.paragraphs { let paragraphText = paragraph.text let paragraphConfidence = paragraph.confidence let paragraphRecognizedLanguages = paragraph.recognizedLanguages let paragraphBreak = paragraph.recognizedBreak let paragraphCornerPoints = paragraph.cornerPoints let paragraphFrame = paragraph.frame for word in paragraph.words { let wordText = word.text let wordConfidence = word.confidence let wordRecognizedLanguages = word.recognizedLanguages let wordBreak = word.recognizedBreak let wordCornerPoints = word.cornerPoints let wordFrame = word.frame for symbol in word.symbols { let symbolText = symbol.text let symbolConfidence = symbol.confidence let symbolRecognizedLanguages = symbol.recognizedLanguages let symbolBreak = symbol.recognizedBreak let symbolCornerPoints = symbol.cornerPoints let symbolFrame = symbol.frame } } } }
Objective-C
NSString *resultText = result.text; for (FIRVisionDocumentTextBlock *block in result.blocks) { NSString *blockText = block.text; NSNumber *blockConfidence = block.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *blockRecognizedLanguages = block.recognizedLanguages; FIRVisionTextRecognizedBreak *blockBreak = block.recognizedBreak; CGRect blockFrame = block.frame; for (FIRVisionDocumentTextParagraph *paragraph in block.paragraphs) { NSString *paragraphText = paragraph.text; NSNumber *paragraphConfidence = paragraph.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *paragraphRecognizedLanguages = paragraph.recognizedLanguages; FIRVisionTextRecognizedBreak *paragraphBreak = paragraph.recognizedBreak; CGRect paragraphFrame = paragraph.frame; for (FIRVisionDocumentTextWord *word in paragraph.words) { NSString *wordText = word.text; NSNumber *wordConfidence = word.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *wordRecognizedLanguages = word.recognizedLanguages; FIRVisionTextRecognizedBreak *wordBreak = word.recognizedBreak; CGRect wordFrame = word.frame; for (FIRVisionDocumentTextSymbol *symbol in word.symbols) { NSString *symbolText = symbol.text; NSNumber *symbolConfidence = symbol.confidence; NSArray<FIRVisionTextRecognizedLanguage *> *symbolRecognizedLanguages = symbol.recognizedLanguages; FIRVisionTextRecognizedBreak *symbolBreak = symbol.recognizedBreak; CGRect symbolFrame = symbol.frame; } } } }
Próximas etapas
- Antes de implantar em produção um aplicativo que usa uma API do Cloud, é preciso seguir mais algumas etapas para evitar ou atenuar o efeito do acesso não autorizado à API.