Catch up on everything announced at Firebase Summit, and learn how Firebase can help you accelerate app development and run your app with confidence. Learn More

Reconocer texto en imágenes con ML Kit en iOS

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

Puede usar ML Kit para reconocer texto en imágenes. ML Kit tiene una API de propósito general adecuada para reconocer texto en imágenes, como el texto de un cartel de calle, y una API optimizada para reconocer el texto de los documentos. La API de uso general tiene modelos tanto en el dispositivo como en la nube. El reconocimiento de texto de documentos solo está disponible como modelo basado en la nube. Consulte la descripción general para ver una comparación de los modelos en la nube y en el dispositivo.

Antes de que empieces

  1. Si aún no ha agregado Firebase a su aplicación, hágalo siguiendo los pasos de la guía de inicio .
  2. Incluya las bibliotecas de ML Kit en su 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 su proyecto, asegúrese de abrir su proyecto Xcode usando su .xcworkspace .
  3. En su aplicación, importe Firebase:

    Rápido

    import Firebase

    C objetivo

    @import Firebase;
  4. Si desea utilizar el modelo basado en la nube y aún no ha habilitado las API basadas en la nube para su proyecto, hágalo ahora:

    1. Abra la página de las API del kit de aprendizaje automático de Firebase console.
    2. Si aún no ha actualizado su proyecto a un plan de precios de Blaze, haga clic en Actualizar para hacerlo. (Se le pedirá que actualice solo si su proyecto no está en el plan Blaze).

      Solo los proyectos de nivel Blaze pueden usar API basadas en la nube.

    3. Si las API basadas en la nube aún no están habilitadas, haga clic en Habilitar API basadas en la nube .

    Si desea utilizar solo el modelo en el dispositivo, puede omitir este paso.

Ahora está listo para comenzar a reconocer texto en imágenes.

Directrices de la imagen de entrada

  • Para que ML Kit reconozca el texto con precisión, las imágenes de entrada deben contener texto representado por suficientes datos de píxeles. Idealmente, para texto en latín, cada carácter debe tener al menos 16x16 píxeles. Para texto en chino, japonés y coreano (solo admitido por las API basadas en la nube), cada carácter debe tener 24x24 píxeles. Para todos los idiomas, generalmente no hay beneficio de precisión para que los caracteres tengan más de 24x24 píxeles.

    Entonces, por ejemplo, una imagen de 640x480 podría funcionar bien para escanear una tarjeta de presentación que ocupa todo el ancho de la imagen. Para escanear un documento impreso en papel tamaño carta, es posible que se requiera una imagen de 720 x 1280 píxeles.

  • Un mal enfoque de la imagen puede dañar la precisión del reconocimiento de texto. Si no obtiene resultados aceptables, intente pedirle al usuario que vuelva a capturar la imagen.

  • Si está reconociendo texto en una aplicación en tiempo real, también puede considerar las dimensiones generales de las imágenes de entrada. Las imágenes más pequeñas se pueden procesar más rápido, por lo tanto, para reducir la latencia, capture imágenes a resoluciones más bajas (teniendo en cuenta los requisitos de precisión anteriores) y asegúrese de que el texto ocupe la mayor parte posible de la imagen. Consulte también Sugerencias para mejorar el rendimiento en tiempo real .


Reconocer texto en imágenes.

Para reconocer texto en una imagen utilizando un modelo en el dispositivo o basado en la nube, ejecute el reconocedor de texto como se describe a continuación.

1. Ejecute el reconocedor de texto

Pase la imagen como `UIImage` o `CMSampleBufferRef` al método `process(_:completion:)` de `VisionTextRecognizer`:
  1. Obtenga una instancia de VisionTextRecognizer llamando a cloudTextRecognizer onDeviceTextRecognizer

    Rápido

    Para usar el modelo en el dispositivo:

    let vision = Vision.vision()
    let textRecognizer = vision.onDeviceTextRecognizer()
    

    Para utilizar el modelo de nube:

    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)
    

    C objetivo

    Para usar el modelo en el dispositivo:

    FIRVision *vision = [FIRVision vision];
    FIRVisionTextRecognizer *textRecognizer = [vision onDeviceTextRecognizer];
    

    Para utilizar el modelo de nube:

    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];
    
  2. Cree un objeto VisionImage usando UIImage o CMSampleBufferRef .

    Para usar una UIImage :

    1. Si es necesario, gire la imagen para que su propiedad imageOrientation sea .up .
    2. Cree un objeto VisionImage usando la UIImage girada correctamente. No especifique ningún metadato de rotación; se debe usar el valor predeterminado, .topLeft .

      Rápido

      let image = VisionImage(image: uiImage)

      C objetivo

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    Para usar un CMSampleBufferRef :

    1. Cree un objeto VisionImageMetadata que especifique la orientación de los datos de imagen contenidos en el búfer CMSampleBufferRef .

      Para obtener la orientación de la imagen:

      Rápido

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

      C objetivo

      - (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:

      Rápido

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      C objetivo

      FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
      AVCaptureDevicePosition cameraPosition =
          AVCaptureDevicePositionBack;  // Set to the capture device you used.
      metadata.orientation =
          [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                       cameraPosition:cameraPosition];
    2. Cree un objeto VisionImage utilizando el objeto CMSampleBufferRef y los metadatos de rotación:

      Rápido

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      C objetivo

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Luego, pasa la imagen al método process(_:completion:) :

    Rápido

    textRecognizer.process(visionImage) { result, error in
      guard error == nil, let result = result else {
        // ...
        return
      }
    
      // Recognized text
    }
    

    C objetivo

    [textRecognizer processImage:image
                      completion:^(FIRVisionText *_Nullable result,
                                   NSError *_Nullable error) {
      if (error != nil || result == nil) {
        // ...
        return;
      }
    
      // Recognized text
    }];
    

2. Extraiga texto de bloques de texto reconocido

Si la operación de reconocimiento de texto tiene éxito, devolverá 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 a palabras (fechas, números, etc.). Para cada objeto `VisionTextBlock`, `VisionTextLine` y `VisionTextElement`, puede obtener el texto reconocido en la región y las coordenadas de límite de la región. Por ejemplo:

Rápido

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

C objetivo

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 desea utilizar el modelo en el dispositivo para reconocer texto en una aplicación en tiempo real, siga estas pautas para lograr las mejores velocidades de fotogramas:

  • Acelera las llamadas al reconocedor de texto. Si un nuevo cuadro de video está disponible mientras se ejecuta el reconocedor de texto, suelte el cuadro.
  • Si está utilizando la salida del reconocedor de texto para superponer gráficos en la imagen de entrada, primero obtenga el resultado de ML Kit, luego renderice la imagen y superponga en un solo paso. Al hacerlo, renderiza en la superficie de visualización solo una vez para cada cuadro de entrada. Consulte las clases previewOverlayView y FIRDetectionOverlayView en la aplicación de ejemplo de presentación para ver un ejemplo.
  • Considere capturar imágenes a una resolución más baja. Sin embargo, también tenga en cuenta los requisitos de dimensión de imagen de esta API.

Próximos pasos


Reconocer texto en imágenes de documentos

Para reconocer el texto de un documento, configure y ejecute el reconocedor de texto de documentos basado en la nube como se describe a continuación.

La API de reconocimiento de texto de documentos, que se describe a continuación, proporciona una interfaz que pretende ser más conveniente para trabajar con imágenes de documentos. Sin embargo, si prefiere la interfaz proporcionada por la API de texto disperso, puede usarla para escanear documentos configurando el reconocedor de texto en la nube para usar el modelo de texto denso .

Para utilizar la API de reconocimiento de texto de documentos:

1. Ejecute el reconocedor de texto

Pase la imagen como UIImage o CMSampleBufferRef al VisionDocumentTextRecognizer process(_:completion:) de VisionDocumentTextRecognizer:

  1. Obtenga una instancia de VisionDocumentTextRecognizer llamando a cloudDocumentTextRecognizer :

    Rápido

    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)
    

    C objetivo

    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];
    
  2. Cree un objeto VisionImage usando UIImage o CMSampleBufferRef .

    Para usar una UIImage :

    1. Si es necesario, gire la imagen para que su propiedad imageOrientation sea .up .
    2. Cree un objeto VisionImage usando la UIImage girada correctamente. No especifique ningún metadato de rotación; se debe usar el valor predeterminado, .topLeft .

      Rápido

      let image = VisionImage(image: uiImage)

      C objetivo

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    Para usar un CMSampleBufferRef :

    1. Cree un objeto VisionImageMetadata que especifique la orientación de los datos de imagen contenidos en el búfer CMSampleBufferRef .

      Para obtener la orientación de la imagen:

      Rápido

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

      C objetivo

      - (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:

      Rápido

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      C objetivo

      FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
      AVCaptureDevicePosition cameraPosition =
          AVCaptureDevicePositionBack;  // Set to the capture device you used.
      metadata.orientation =
          [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                       cameraPosition:cameraPosition];
    2. Cree un objeto VisionImage utilizando el objeto CMSampleBufferRef y los metadatos de rotación:

      Rápido

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      C objetivo

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Luego, pasa la imagen al método process(_:completion:) :

    Rápido

    textRecognizer.process(visionImage) { result, error in
      guard error == nil, let result = result else {
        // ...
        return
      }
    
      // Recognized text
    }
    

    C objetivo

    [textRecognizer processImage:image
                      completion:^(FIRVisionDocumentText *_Nullable result,
                                   NSError *_Nullable error) {
      if (error != nil || result == nil) {
        // ...
        return;
      }
    
        // Recognized text
    }];
    

2. Extraiga texto de bloques de texto reconocido

Si la operación de reconocimiento de texto tiene éxito, devolverá un objeto VisionDocumentText . Un objeto VisionDocumentText contiene el texto completo reconocido en la imagen y una jerarquía de objetos que reflejan la estructura del documento reconocido:

Para cada VisionDocumentTextBlock , VisionDocumentTextParagraph , VisionDocumentTextWord y VisionDocumentTextSymbol , puede obtener el texto reconocido en la región y las coordenadas de límite de la región.

Por ejemplo:

Rápido

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

C objetivo

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óximos pasos