Reconnaître du texte dans des images avec ML Kit sur iOS

Vous pouvez utiliser ML Kit pour reconnaître du texte dans des images. ML Kit propose une API à usage général adaptée à la reconnaissance de texte dans des images, comme le texte d'un panneau de signalisation, ainsi qu'une API optimisée pour la reconnaissance de texte dans des documents. L'API à usage général dispose de modèles sur l'appareil et dans le cloud. La reconnaissance du texte dans les documents n'est disponible que sous forme de modèle basé sur le cloud. Pour comparer les modèles cloud et sur l'appareil, consultez la présentation.

Avant de commencer

  1. Si vous n'avez pas encore ajouté Firebase à votre application, faites-le en suivant les étapes du guide de démarrage.
  2. Incluez les bibliothèques ML Kit dans votre fichier Podfile :
    pod 'Firebase/MLVision', '6.25.0'
    # If using an on-device API:
    pod 'Firebase/MLVisionTextModel', '6.25.0'
    
    Après avoir installé ou mis à jour les pods de votre projet, veillez à ouvrir votre projet Xcode à l'aide de son fichier .xcworkspace.
  3. Dans votre application, importez Firebase :

    Swift

    import Firebase

    Objective-C

    @import Firebase;
  4. Si vous souhaitez utiliser le modèle basé sur le cloud et que vous n'avez pas encore activé les API basées sur le cloud pour votre projet, faites-le maintenant :

    1. Ouvrez la page API ML Kit de la console Firebase.
    2. Si vous n'avez pas encore migré votre projet vers un forfait Blaze, cliquez sur Mettre à niveau pour le faire. (Vous serez invité à effectuer la mise à niveau uniquement si votre projet n'est pas associé au forfait Blaze.)

      Seuls les projets de niveau Blaze peuvent utiliser les API basées sur le cloud.

    3. Si les API basées sur le cloud ne sont pas déjà activées, cliquez sur Activer les API basées sur le cloud.

    Si vous ne souhaitez utiliser que le modèle sur l'appareil, vous pouvez ignorer cette étape.

Vous êtes maintenant prêt à commencer à reconnaître du texte dans des images.

Consignes concernant les images d'entrée

  • Pour que ML Kit reconnaisse le texte avec précision, les images d'entrée doivent contenir du texte représenté par suffisamment de données de pixels. Dans l'idéal, pour le texte latin, chaque caractère doit mesurer au moins 16x16 pixels. Pour le texte en chinois, en japonais et en coréen (uniquement pris en charge par les API cloud), chaque caractère doit mesurer 24 x 24 pixels. Pour toutes les langues, il n'y a généralement aucun avantage en termes de précision à ce que les caractères soient plus grands que 24 x 24 pixels.

    Par exemple, une image de 640 x 480 peut être idéale pour numériser une carte de visite qui occupe toute la largeur de l'image. Pour numériser un document imprimé sur du papier au format Letter, une image de 720 x 1 280 pixels peut être requise.

  • Une image floue peut nuire à la précision de la reconnaissance du texte. Si vous n'obtenez pas de résultats acceptables, demandez à l'utilisateur de reprendre la photo.

  • Si vous reconnaissez du texte dans une application en temps réel, vous pouvez également tenir compte des dimensions globales des images d'entrée. Les images plus petites peuvent être traitées plus rapidement. Pour réduire la latence, capturez des images à des résolutions inférieures (en gardant à l'esprit les exigences de précision ci-dessus) et assurez-vous que le texte occupe la plus grande partie possible de l'image. Consultez également Conseils pour améliorer les performances en temps réel.


Détectez du texte dans des images

Pour reconnaître du texte dans une image à l'aide d'un modèle sur l'appareil ou dans le cloud, exécutez le module de reconnaissance de texte comme décrit ci-dessous.

1. Exécuter l'outil de reconnaissance de texte

Transmettez l'image en tant que `UIImage` ou `CMSampleBufferRef` à la méthode `process(_:completion:)` de `VisionTextRecognizer` :
  1. Obtenez une instance de VisionTextRecognizer en appelant onDeviceTextRecognizer ou cloudTextRecognizer :

    Swift

    Pour utiliser le modèle sur l'appareil :

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

    Pour utiliser le modèle cloud :

    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

    Pour utiliser le modèle sur l'appareil :

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

    Pour utiliser le modèle cloud :

    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. Créez un objet VisionImage à l'aide d'un UIImage ou d'un CMSampleBufferRef.

    Pour utiliser une UIImage :

    1. Si nécessaire, faites pivoter l'image pour que sa propriété imageOrientation soit définie sur .up.
    2. Créez un objet VisionImage à l'aide de l'objet UIImage correctement orienté. Ne spécifiez aucune métadonnée de rotation. La valeur par défaut, .topLeft, doit être utilisée.

      Swift

      let image = VisionImage(image: uiImage)

      Objective-C

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

    Pour utiliser une CMSampleBufferRef :

    1. Créez un objet VisionImageMetadata qui spécifie l'orientation des données d'image contenues dans le tampon CMSampleBufferRef.

      Pour obtenir l'orientation de l'image :

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

      Créez ensuite l'objet de métadonnées :

      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];
    2. Créez un objet VisionImage à l'aide de l'objet CMSampleBufferRef et des métadonnées de rotation :

      Swift

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

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Transmettez ensuite l'image à la méthode 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. Extraire du texte à partir de blocs de texte reconnus

Si l'opération de reconnaissance de texte réussit, elle renvoie un objet [`VisionText`][VisionText]. Un objet `VisionText` contient l'intégralité du texte reconnu dans l'image et zéro ou plusieurs objets [`VisionTextBlock`][VisionTextBlock]. Chaque `VisionTextBlock` représente un bloc de texte rectangulaire contenant zéro ou plusieurs objets [`VisionTextLine`][VisionTextLine]. Chaque objet `VisionTextLine` contient zéro ou plusieurs objets [`VisionTextElement`][VisionTextElement], qui représentent des mots et des entités de type mot (dates, nombres, etc.). Pour chaque objet `VisionTextBlock`, `VisionTextLine` et `VisionTextElement`, vous pouvez obtenir le texte reconnu dans la région et les coordonnées du cadre de délimitation de la région. Exemple :

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

Conseils pour améliorer les performances en temps réel

Si vous souhaitez utiliser le modèle sur l'appareil pour reconnaître du texte dans une application en temps réel, suivez ces consignes pour obtenir les meilleures fréquences d'images :

  • Limitez les appels au module de reconnaissance de texte. Si une nouvelle image vidéo devient disponible pendant l'exécution du module de reconnaissance de texte, supprimez l'image.
  • Si vous utilisez la sortie du module de reconnaissance de texte pour superposer des éléments graphiques sur l'image d'entrée, commencez par obtenir le résultat de ML Kit, puis affichez l'image et la superposition en une seule étape. Vous n'avez ainsi besoin d'effectuer le rendu sur la surface d'affichage qu'une seule fois pour chaque frame d'entrée. Pour obtenir un exemple, consultez les classes previewOverlayView et FIRDetectionOverlayView dans l'application exemple Showcase.
  • Envisagez de prendre des photos à une résolution inférieure. Cependant, gardez également à l'esprit les exigences de cette API concernant les dimensions des images.

Étapes suivantes


Reconnaître le texte dans les images de documents

Pour reconnaître le texte d'un document, configurez et exécutez le module de reconnaissance de texte de document basé sur le cloud, comme décrit ci-dessous.

L'API de reconnaissance de texte dans les documents, décrite ci-dessous, fournit une interface plus pratique pour travailler avec des images de documents. Toutefois, si vous préférez l'interface fournie par l'API Sparse Text, vous pouvez l'utiliser à la place pour analyser des documents en configurant le module de reconnaissance de texte dans le cloud pour utiliser le modèle de texte dense.

Pour utiliser l'API de reconnaissance de texte dans les documents :

1. Exécuter l'outil de reconnaissance de texte

Transmettez l'image en tant que UIImage ou CMSampleBufferRef à la méthode process(_:completion:) de VisionDocumentTextRecognizer :

  1. Obtenez une instance de VisionDocumentTextRecognizer en appelant cloudDocumentTextRecognizer :

    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];
  2. Créez un objet VisionImage à l'aide d'un UIImage ou d'un CMSampleBufferRef.

    Pour utiliser une UIImage :

    1. Si nécessaire, faites pivoter l'image pour que sa propriété imageOrientation soit définie sur .up.
    2. Créez un objet VisionImage à l'aide de l'objet UIImage correctement orienté. Ne spécifiez aucune métadonnée de rotation. La valeur par défaut, .topLeft, doit être utilisée.

      Swift

      let image = VisionImage(image: uiImage)

      Objective-C

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

    Pour utiliser une CMSampleBufferRef :

    1. Créez un objet VisionImageMetadata qui spécifie l'orientation des données d'image contenues dans le tampon CMSampleBufferRef.

      Pour obtenir l'orientation de l'image :

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

      Créez ensuite l'objet de métadonnées :

      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];
    2. Créez un objet VisionImage à l'aide de l'objet CMSampleBufferRef et des métadonnées de rotation :

      Swift

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

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. Transmettez ensuite l'image à la méthode 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. Extraire du texte à partir de blocs de texte reconnus

Si l'opération de reconnaissance de texte réussit, elle renvoie un objet VisionDocumentText. Un objet VisionDocumentText contient le texte intégral reconnu dans l'image et une hiérarchie d'objets qui reflètent la structure du document reconnu :

Pour chaque objet VisionDocumentTextBlock, VisionDocumentTextParagraph, VisionDocumentTextWord et VisionDocumentTextSymbol, vous pouvez obtenir le texte reconnu dans la région et les coordonnées du cadre de sélection de la région.

Exemple :

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

Étapes suivantes