Puedes usar el Kit de AA para reconocer texto en imágenes. El Kit de AA tiene una API de uso general que permite reconocer texto en imágenes, como en señales de tránsito, y una API optimizada para reconocer el texto de documentos. La API de uso general tiene modelos para dispositivos y en la nube. El reconocimiento de texto en documentos solo está disponible en el modelo para la nube. Consulta la descripción general a fin de comparar el modelo para dispositivos y el modelo para la nube.
Antes de comenzar
- Si aún no agregaste Firebase a tu app, sigue los pasos en la guía de introducción para hacerlo.
- Incluye las bibliotecas del ML Kit en tu Podfile:
pod 'Firebase/MLVision', '6.25.0' # If using an on-device API: pod 'Firebase/MLVisionTextModel', '6.25.0'
Después de instalar o actualizar los Pods de tu proyecto, asegúrate de abrir el proyecto de Xcode con su.xcworkspace
. - En tu app, importa Firebase:
Swift
import Firebase
Objective-C
@import Firebase;
-
Si deseas usar el modelo basado en la nube, pero todavía no habilitaste las API basadas en la nube para el proyecto, hazlo ahora:
- Abre la página de API del Kit de AA de Firebase console.
-
Si todavía no has actualizado tu proyecto al plan de precios Blaze, haz clic en Actualizar para hacerlo (se te pedirá que realices la actualización únicamente si tu proyecto no está en el plan Blaze).
Solo los proyectos con un plan Blaze pueden usar las API de Cloud.
- Si las API de Cloud no están habilitadas, haz clic en Habilitar las API de Cloud.
Si solo quieres usar el modelo en el dispositivo, puedes omitir este paso.
Ya estás listo para comenzar a reconocer texto en imágenes.
Lineamientos para imágenes de entrada
-
Para que el Kit de AA reconozca texto con exactitud, las imágenes de entrada deben contener texto representado con datos de píxeles suficientes. Lo ideal para el texto latino es que cada carácter sea de al menos 16 x 16 píxeles. Para el texto en chino, japonés y coreano (solo compatible con las API basadas en la nube), cada carácter debe ser de 24x24 píxeles. Generalmente, para todos los idiomas, no se obtiene un beneficio de exactitud cuando el tamaño de los caracteres es superior a 24x24 píxeles.
Por ejemplo, una imagen de 640 × 480 puede funcionar bien para escanear una tarjeta de presentación que ocupa todo el ancho de la imagen. Para escanear un documento impreso en tamaño de papel carta, es posible que se requiera una imagen de 720 × 1,280 píxeles.
-
Un enfoque de imagen deficiente puede afectar la exactitud del reconocimiento de texto. Si no obtienes resultados aceptables, intenta pedirle al usuario que vuelva a capturar la imagen.
-
Si reconoces texto en una aplicación en tiempo real, te recomendamos tener en cuenta las dimensiones generales de las imágenes de entrada. Las imágenes más pequeñas se pueden procesar más rápido. Así que, para reducir la latencia, captura las imágenes con resoluciones más bajas (teniendo en cuenta los requisitos de exactitud anteriores) y asegúrate de que el texto ocupe la mayor porción de la imagen que sea posible. Consulta también Sugerencias para mejorar el rendimiento en tiempo real.
Reconoce texto en imágenes
A fin de reconocer texto en una imagen con el modelo para el dispositivo o el correspondiente a la nube, ejecuta el reconocedor de texto como se describe a continuación:
1. Ejecuta el reconocedor de texto
Pasa la imagen como una “UIImage” o una “CMSampleBufferRef” al método “process(_:completion:)” de “VisionTextRecognizer”:- Obtén una instancia de
VisionTextRecognizer
a través de una llamada aonDeviceTextRecognizer
ocloudTextRecognizer
.Swift
Para usar el modelo en el dispositivo:
let vision = Vision.vision() let textRecognizer = vision.onDeviceTextRecognizer()
Para usar el modelo en la nube, haz lo siguiente:
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 el modelo en el dispositivo:
FIRVision *vision = [FIRVision vision]; FIRVisionTextRecognizer *textRecognizer = [vision onDeviceTextRecognizer];
Para usar el modelo en la nube, haz lo siguiente:
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];
-
Crea un objeto
VisionImage
mediante unaUIImage
oCMSampleBufferRef
.Para usar una
UIImage
, debes hacer lo siguiente:- Si es necesario, rota la imagen para que la propiedad
imageOrientation
sea.up
. - Crea un objeto
VisionImage
mediante unaUIImage
que se haya rotado adecuadamente. No especifiques los metadatos de rotación. Se debe usar el valor predeterminado.topLeft
.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Para usar una
CMSampleBufferRef
, debes hacer lo siguiente:-
Crea un objeto
VisionImageMetadata
que especifique la orientación de los datos de la imagen contenidos en el búferCMSampleBufferRef
.Para obtener la orientación de la imagen, haz lo siguiente:
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; } }
Luego crea el objeto de metadatos de esta manera:
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];
- Crea un objeto
VisionImage
a través del objetoCMSampleBufferRef
y los metadatos de rotación:Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Si es necesario, rota la imagen para que la propiedad
-
Por último, pasa la imagen al 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 Extrae texto de bloques de texto reconocido
Si la operación de reconocimiento de texto se ejecuta correctamente, se mostrará un objeto [“VisionText”][VisionText]. Un objeto “VisionText” contiene el texto completo reconocido en la imagen, y cero o más objetos [“VisionTextBlock”][VisionTextBlock]. Cada “VisionTextBlock” representa un bloque rectangular de texto que contiene cero o más objetos [“VisionTextLine”][VisionTextLine]. Cada objeto “VisionTextLine” contiene cero o más objetos [“VisionTextElement”][VisionTextElement], que representan palabras y entidades similares (fechas, números, etc.). Para cada objeto “VisionTextBlock”, “VisionTextLine” y “VisionTextElement”, puedes obtener el texto reconocido en la región y las coordenadas que limitan la región. Por ejemplo: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; } } }
Sugerencias para mejorar el rendimiento en tiempo real
Si quieres usar el modelo en el dispositivo para reconocer texto en una aplicación en tiempo real, sigue estos lineamientos para lograr las mejores velocidades de fotogramas:
- Regula las llamadas al reconocedor de texto. Si hay un fotograma de video nuevo disponible mientras se ejecuta el reconocedor de texto, ignora ese fotograma.
- Si estás usando la salida del reconocedor de texto para superponer gráficas en la imagen de entrada, primero obtén el resultado del Kit de AA y luego procesa la imagen y la superposición en un solo paso. De esta manera, procesas en la superficie de visualización solo una vez por cada fotograma de entrada. Consulta las clases previewOverlayView y FIRDetectionOverlayView en la app de muestra para ver un ejemplo.
- Captura imágenes con una resolución más baja. Sin embargo, también ten en cuenta los requisitos de dimensiones de imágenes de esta API.
Pasos siguientes
- Antes de implementar en producción una app que usa una API de Cloud, debes realizar algunos pasos adicionales para prevenir y mitigar el efecto del acceso no autorizado a la API.
Reconoce texto en imágenes de documentos
Para reconocer el texto de un documento, configura y ejecuta el reconocedor de texto en documentos en la nube como se describe a continuación.
La API de reconocimiento de texto en documentos, que se describe a continuación, proporciona una interfaz diseñada para facilitar el trabajo con imágenes en documentos. Sin embargo, si prefieres la interfaz que proporciona la API de texto escaso, puedes usarla para escanear documentos configurando el reconocedor de texto en la nube a fin de utilizar el modelo para mucho texto.
Para usar la API de reconocimiento de texto en documentos, haz lo siguiente:
1. Ejecuta el reconocedor de texto
Pasa la imagen como unaUIImage
o una CMSampleBufferRef
al método process(_:completion:)
de VisionDocumentTextRecognizer
:
- Llama a
cloudDocumentTextRecognizer
para obtener una instancia deVisionDocumentTextRecognizer
: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];
-
Crea un objeto
VisionImage
mediante unaUIImage
oCMSampleBufferRef
.Para usar una
UIImage
, debes hacer lo siguiente:- Si es necesario, rota la imagen para que la propiedad
imageOrientation
sea.up
. - Crea un objeto
VisionImage
mediante unaUIImage
que se haya rotado adecuadamente. No especifiques los metadatos de rotación. Se debe usar el valor predeterminado.topLeft
.Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
Para usar una
CMSampleBufferRef
, debes hacer lo siguiente:-
Crea un objeto
VisionImageMetadata
que especifique la orientación de los datos de la imagen contenidos en el búferCMSampleBufferRef
.Para obtener la orientación de la imagen, haz lo siguiente:
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; } }
Luego crea el objeto de metadatos de esta manera:
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];
- Crea un objeto
VisionImage
a través del objetoCMSampleBufferRef
y los metadatos de rotación:Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- Si es necesario, rota la imagen para que la propiedad
-
Por último, pasa la imagen al 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 Extrae texto de bloques de texto reconocido
Si la operación de reconocimiento de texto se ejecuta correctamente, se mostrará un objetoVisionDocumentText
. El objeto VisionDocumentText
contiene todo el texto reconocido en la imagen y una jerarquía de objetos que refleja la estructura del documento reconocido:
Para cada objeto VisionDocumentTextBlock
, VisionDocumentTextParagraph
, VisionDocumentTextWord
y VisionDocumentTextSymbol
, puedes obtener el texto reconocido en la región y las coordenadas que limitan la región.
Por ejemplo:
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; } } } }
Pasos siguientes
- Antes de implementar en producción una app que usa una API de Cloud, debes realizar algunos pasos adicionales para prevenir y mitigar el efecto del acceso no autorizado a la API.