Riconoscere il testo nelle immagini con ML Kit su iOS

Puoi utilizzare ML Kit per riconoscere il testo nelle immagini o nei video, ad esempio il testo di un cartello stradale. Le caratteristiche principali di questa funzionalità sono:

API di riconoscimento del testo
DescrizioneRiconosci il testo in latino in immagini o video.
Nome SDKGoogleMLKit/TextRecognition (version 2.2.0)
ImplementazioneGli asset vengono collegati in modo statico alla tua app al momento della creazione.
Impatto sulle dimensioni dell'appCirca 20 MB
PrestazioniIn tempo reale sulla maggior parte dei dispositivi.

Prova subito

Prima di iniziare

  1. Includi i seguenti pod di ML Kit nel tuo podfile:
    pod 'GoogleMLKit/TextRecognition','2.2.0'
    
  2. Dopo aver installato o aggiornato i pod del progetto, apri il progetto Xcode utilizzando .xcworkspace. ML Kit è supportato in Xcode versione 12.4 o successiva.

1. Crea un'istanza di TextRecognizer

Crea un'istanza di TextRecognizer chiamando +textRecognizer:

Swift

let textRecognizer = TextRecognizer.textRecognizer()
      

Objective-C

MLKTextRecognizer *textRecognizer = [MLKTextRecognizer textRecognizer];
      

2. Prepara l'immagine di input

Passa l'immagine come UIImage o CMSampleBufferRef al metodo process(_:completion:) di TextRecognizer:

Crea un oggetto VisionImage utilizzando un UIImage o un CMSampleBuffer.

Se utilizzi un UIImage, segui questi passaggi:

  • Crea un oggetto VisionImage con il UIImage. Assicurati di specificare il .orientation corretto.

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Se utilizzi un CMSampleBuffer, segui questi passaggi:

  • Specifica l'orientamento dei dati dell'immagine contenuti in CMSampleBuffer.

    Per ottenere l'orientamento dell'immagine:

    Swift

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • Crea un oggetto VisionImage utilizzando l'oggetto e l'orientamento CMSampleBuffer:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. Elabora immagine

Quindi, passa l'immagine al metodo process(_:completion:):

Swift

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

Objective-C

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

4. Estrazione del testo dai blocchi di testo riconosciuti

Se l'operazione di riconoscimento del testo ha esito positivo, restituisce un oggetto Text. Un oggetto Text contiene il testo completo riconosciuto nell'immagine e zero o più oggetti TextBlock.

Ogni TextBlock rappresenta un blocco di testo rettangolare, che contiene zero o più oggetti TextLine. Ogni oggetto TextLine contiene zero o più oggetti TextElement, che rappresentano parole ed entità simili a parole, come date e numeri.

Per ogni oggetto TextBlock, TextLine e TextElement, puoi riconoscere il testo nell'area geografica e le coordinate di delimitazione dell'area geografica.

Ad esempio:

Swift

let resultText = result.text
for block in result.blocks {
    let blockText = block.text
    let blockLanguages = block.recognizedLanguages
    let blockCornerPoints = block.cornerPoints
    let blockFrame = block.frame
    for line in block.lines {
        let lineText = line.text
        let lineLanguages = line.recognizedLanguages
        let lineCornerPoints = line.cornerPoints
        let lineFrame = line.frame
        for element in line.elements {
            let elementText = element.text
            let elementCornerPoints = element.cornerPoints
            let elementFrame = element.frame
        }
    }
}

Objective-C

NSString *resultText = result.text;
for (MLKTextBlock *block in result.blocks) {
  NSString *blockText = block.text;
  NSArray<MLKTextRecognizedLanguage *> *blockLanguages = block.recognizedLanguages;
  NSArray<NSValue *> *blockCornerPoints = block.cornerPoints;
  CGRect blockFrame = block.frame;
  for (MLKTextLine *line in block.lines) {
    NSString *lineText = line.text;
    NSArray<MLKTextRecognizedLanguage *> *lineLanguages = line.recognizedLanguages;
    NSArray<NSValue *> *lineCornerPoints = line.cornerPoints;
    CGRect lineFrame = line.frame;
    for (MLKTextElement *element in line.elements) {
      NSString *elementText = element.text;
      NSArray<NSValue *> *elementCornerPoints = element.cornerPoints;
      CGRect elementFrame = element.frame;
    }
  }
}

Linee guida sull'immagine di input

  • Affinché ML Kit possa riconoscere con precisione il testo, le immagini di input devono contenere testo rappresentato da dati pixel sufficienti. Idealmente, ogni carattere dovrebbe essere di almeno 16 x 16 pixel. In genere, la presenza di caratteri più grandi di 24 x 24 pixel non ha alcun vantaggio in termini di precisione.

    Ad esempio, un'immagine 640 x 480 potrebbe essere adatta alla scansione di un biglietto da visita che occupa l'intera larghezza dell'immagine. Per scansionare un documento stampato su carta in formato lettera, potrebbe essere necessaria un'immagine di 720 x 1280 pixel.

  • Una messa a fuoco dell'immagine scadente può influire sulla precisione del riconoscimento del testo. Se non ottieni risultati accettabili, prova a chiedere all'utente di riprendere l'immagine.

  • Se riconosci il testo in un'applicazione in tempo reale, devi considerare le dimensioni complessive delle immagini di input. Le immagini più piccole possono essere elaborate più rapidamente. Per ridurre la latenza, assicurati che il testo occupi la maggiore quantità possibile di immagini e acquisisci immagini a risoluzioni inferiori (ricordando i requisiti di accuratezza menzionati sopra). Per maggiori informazioni, consulta la pagina Suggerimenti per migliorare le prestazioni.

Suggerimenti per migliorare il rendimento

  • Per l'elaborazione dei frame video, utilizza l'API sincrona results(in:) del rilevatore. Richiama questo metodo dalla funzione captureOutput(_, didOutput:from:) di AVCaptureVideoDataOutputSampleBufferDelegate per ottenere in modo sincrono i risultati dal frame video specificato. Mantieni alwaysDiscardsLateVideoFrames di AVCaptureVideoDataOutput come true per limitare le chiamate al rilevatore. Se un nuovo video diventa disponibile mentre il rilevatore è in esecuzione, viene eliminato.
  • Se utilizzi l'output del rilevatore per sovrapporre la grafica all'immagine di input, prima ottieni il risultato da ML Kit, quindi visualizza l'immagine e l'overlay in un solo passaggio. In questo modo, visualizzerai nella piattaforma display solo una volta per ogni frame di input elaborato. Guarda un esempio di updateAnteprimaOverlayViewWithLastFrame nell'esempio della guida rapida di ML Kit.
  • Potresti acquisire immagini a una risoluzione inferiore. Tuttavia, tieni presente anche i requisiti relativi alle dimensioni delle immagini di questa API.