Rozpoznawanie tekstu na obrazach za pomocą ML Kit na iOS

Za pomocą pakietu ML Kit możesz rozpoznawać tekst na obrazach lub w filmach, na przykład i znaku z nazwą ulicy. Główne cechy tej funkcji:

Interfejs Text Recognition API w wersji 2
OpisRozpoznawanie tekstu na obrazach i filmach, obsługa pismo łacińskie, chińskie, dewanagari, japońskie i koreańskie oraz wiele języków.
Nazwy pakietów SDKGoogleMLKit/TextRecognition
GoogleMLKit/TextRecognitionChinese
GoogleMLKit/TextRecognitionDevanagari
GoogleMLKit/TextRecognitionJapanese
GoogleMLKit/TextRecognitionKorean
ImplementacjaZasoby są statycznie połączone z aplikacją w momencie kompilacji.
Wpływ rozmiaru aplikacjiOkoło 38 MB na pakiet SDK skryptu
Wynikiw czasie rzeczywistym na większości urządzeń w przypadku pakietu SDK w języku łacińskim, a w przypadku innych – wolniej.

Wypróbuj

  • Wypróbuj przykładową aplikację, aby: zobaczysz przykład użycia tego interfejsu API.
  • Wypróbuj kod samodzielnie za pomocą

Zanim zaczniesz

  1. W pliku Podfile umieść te pody ML Kit:
    # To recognize Latin script
    pod 'GoogleMLKit/TextRecognition', '3.2.0'
    # To recognize Chinese script
    pod 'GoogleMLKit/TextRecognitionChinese', '3.2.0'
    # To recognize Devanagari script
    pod 'GoogleMLKit/TextRecognitionDevanagari', '3.2.0'
    # To recognize Japanese script
    pod 'GoogleMLKit/TextRecognitionJapanese', '3.2.0'
    # To recognize Korean script
    pod 'GoogleMLKit/TextRecognitionKorean', '3.2.0'
    
  2. Po zainstalowaniu lub zaktualizowaniu podów projektu otwórz projekt Xcode za pomocą .xcworkspace ML Kit jest obsługiwany w Xcode w wersji 12.4 lub nowszej.

1. Tworzenie instancji maszyny wirtualnej TextRecognizer

Utwórz instancję TextRecognizer, wywołując +textRecognizer(options:), przekazując opcje związane z pakietem SDK zadeklarowanym jako w zależności od powyższego:

Swift

// When using Latin script recognition SDK
let latinOptions = TextRecognizerOptions()
let latinTextRecognizer = TextRecognizer.textRecognizer(options:options)

// When using Chinese script recognition SDK
let chineseOptions = ChineseTextRecognizerOptions()
let chineseTextRecognizer = TextRecognizer.textRecognizer(options:options)

// When using Devanagari script recognition SDK
let devanagariOptions = DevanagariTextRecognizerOptions()
let devanagariTextRecognizer = TextRecognizer.textRecognizer(options:options)

// When using Japanese script recognition SDK
let japaneseOptions = JapaneseTextRecognizerOptions()
let japaneseTextRecognizer = TextRecognizer.textRecognizer(options:options)

// When using Korean script recognition SDK
let koreanOptions = KoreanTextRecognizerOptions()
let koreanTextRecognizer = TextRecognizer.textRecognizer(options:options)

Objective-C

// When using Latin script recognition SDK
MLKTextRecognizerOptions *latinOptions = [[MLKTextRecognizerOptions alloc] init];
MLKTextRecognizer *latinTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

// When using Chinese script recognition SDK
MLKChineseTextRecognizerOptions *chineseOptions = [[MLKChineseTextRecognizerOptions alloc] init];
MLKTextRecognizer *chineseTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

// When using Devanagari script recognition SDK
MLKDevanagariTextRecognizerOptions *devanagariOptions = [[MLKDevanagariTextRecognizerOptions alloc] init];
MLKTextRecognizer *devanagariTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

// When using Japanese script recognition SDK
MLKJapaneseTextRecognizerOptions *japaneseOptions = [[MLKJapaneseTextRecognizerOptions alloc] init];
MLKTextRecognizer *japaneseTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

// When using Korean script recognition SDK
MLKKoreanTextRecognizerOptions *koreanOptions = [[MLKKoreanTextRecognizerOptions alloc] init];
MLKTextRecognizer *koreanTextRecognizer = [MLKTextRecognizer textRecognizerWithOptions:options];

2. Przygotowywanie obrazu wejściowego

Przekaż obraz jako UIImage lub CMSampleBufferRef do Metoda process(_:completion:) TextRecognizer:

Utwórz obiekt VisionImage za pomocą UIImage lub CMSampleBuffer.

Jeśli używasz UIImage, wykonaj te czynności:

  • Utwórz obiekt VisionImage za pomocą UIImage. Pamiętaj, by określić prawidłowy .orientation.

    Swift

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

    Objective-C

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

Jeśli używasz CMSampleBuffer, wykonaj te czynności:

  • Określ orientację danych zdjęć zawartych w pliku CMSampleBuffer

    Aby sprawdzić orientację obrazu:

    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;
      }
    }
          
  • Utwórz obiekt VisionImage za pomocą CMSampleBuffer obiekt i orientacja:

    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. Przetwarzanie obrazu

Następnie przekaż obraz do metody 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. Wyodrębnianie tekstu z bloków rozpoznanego tekstu

Jeśli operacja rozpoznawania tekstu się powiedzie, wyświetli Text. Obiekt Text zawiera pełny tekst rozpoznane na obrazie i 0 lub więcej TextBlock obiektów.

Każdy element TextBlock to prostokątny blok tekstu, który nie zawierają żadnych obiektów TextLine ani ich więcej. Co TextLine obiekt nie zawiera żadnych obiektów TextElement, które reprezentują słowa i elementy słowne, takie jak daty i liczby.

Dla każdej kolumny TextBlock, TextLine i TextElement, możesz rozpoznać tekst w regionu i współrzędnych geograficznych regionu.

Na przykład:

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

Wytyczne dotyczące obrazu wejściowego

  • Aby ML Kit mógł dokładnie rozpoznawać tekst, obrazy wejściowe muszą zawierać który jest reprezentowany przez wystarczającą ilość danych pikseli. Najlepiej, każdy znak powinien mieć rozmiar co najmniej 16 x 16 pikseli. Nie ma w przypadku znaków większych niż 24 x 24 piksele.

    Na przykład obraz o wymiarach 640 x 480 może się sprawdzić do zeskanowania wizytówki zajmuje całą szerokość obrazu. Aby zeskanować dokument wydrukowany na na papierze w formacie letter, może być wymagany obraz o wymiarach 720 x 1280 pikseli.

  • Słaba ostrość obrazu może zmniejszyć dokładność rozpoznawania tekstu. Jeśli nim nie jesteś uzyskać akceptowalne wyniki, poproś użytkownika o ponowne przechwycenie obrazu.

  • Jeśli rozpoznajesz tekst w aplikacji działającej w czasie rzeczywistym, weź pod uwagę ogólne wymiary obrazów wejściowych. Mniejszy szybciej przetwarzać obrazy. Aby skrócić czas oczekiwania, tekst powinien zajmować jak najwięcej należy robić zdjęcia i robić zdjęcia w niższej rozdzielczości (pamiętając o dokładności powyższe wymagania). Więcej informacji: Wskazówki pozwalające zwiększyć wydajność.

Wskazówki dotyczące poprawy skuteczności

  • Do przetwarzania klatek wideo używaj synchronicznego interfejsu API results(in:) detektora. Zadzwoń do nas tę metodę z AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:), aby synchronicznie pobierać wyniki dotyczące danego filmu ramki. Zachowaj AVCaptureVideoDataOutput: alwaysDiscardsLateVideoFrames jako true, aby ograniczyć wywołania detektora. Jeśli nowy gdy klatka wideo jest dostępna, gdy jest uruchomiony detektor, zostanie usunięta.
  • Jeśli użyjesz danych wyjściowych detektora do nakładania grafiki na obrazu wejściowego, najpierw pobierz wynik z ML Kit, a następnie wyrenderuj obraz i nakładanie nakładek w jednym kroku. W ten sposób renderowanie na powierzchni tylko raz na każdą przetworzoną ramkę wejściową. Zobacz updatePreviewOverlayViewWithLastFrame. znajdziesz na przykład w krótkim wprowadzeniu do korzystania z ML Kit.
  • Rozważ robienie zdjęć w niższej rozdzielczości. Pamiętaj jednak, wymagania dotyczące wymiarów obrazów w tym interfejsie API.
  • Aby uniknąć potencjalnego pogorszenia wydajności, nie uruchamiaj jej wielokrotnie TextRecognizer instancje jednocześnie korzystające z różnych opcji skryptu.