Oznaczanie obrazów za pomocą ML Kit na iOS

Za pomocą pakietu ML Kit możesz oznaczać etykietami obiekty rozpoznawane na obrazie. Model domyślny udostępniany w ramach ML Kit obsługuje ponad 400 różnych etykiet.

Wypróbuj

Zanim zaczniesz

  1. W pliku Podfile uwzględnij te pody ML Kit:
    pod 'GoogleMLKit/ImageLabeling', '3.2.0'
    
  2. Po zainstalowaniu lub zaktualizowaniu podów w projekcie otwórz projekt Xcode, korzystając z jego polecenia .xcworkspace. ML Kit obsługuje Xcode w wersji 12.4 lub nowszej.

Teraz możesz oznaczyć obrazy etykietami.

1. Przygotuj obraz wejściowy

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

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

  • Utwórz obiekt VisionImage za pomocą UIImage. Pamiętaj, aby podać prawidłową wartość .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 urządzenia CMSampleBuffer, wykonaj te czynności:

  • Określ orientację danych obrazu w elemencie CMSampleBuffer.

    Aby pobrać orientację:

    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, używając obiektu i orientacji 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];

2. Konfigurowanie i uruchamianie narzędzia do etykietowania obrazów

Aby oznaczyć etykietami obiekty na obrazie, przekaż obiekt VisionImage do metody processImage() metody ImageLabeler.

  1. Najpierw pobierz instancję ImageLabeler.

Swift

let labeler = ImageLabeler.imageLabeler()

// Or, to set the minimum confidence required:
// let options = ImageLabelerOptions()
// options.confidenceThreshold = 0.7
// let labeler = ImageLabeler.imageLabeler(options: options)

Objective-C

MLKImageLabeler *labeler = [MLKImageLabeler imageLabeler];

// Or, to set the minimum confidence required:
// MLKImageLabelerOptions *options =
//         [[MLKImageLabelerOptions alloc] init];
// options.confidenceThreshold = 0.7;
// MLKImageLabeler *labeler =
//         [MLKImageLabeler imageLabelerWithOptions:options];
  1. Następnie przekaż obraz do metody processImage():

Swift

labeler.process(image) { labels, error in
    guard error == nil, let labels = labels else { return }

    // Task succeeded.
    // ...
}

Objective-C

[labeler processImage:image
completion:^(NSArray *_Nullable labels,
            NSError *_Nullable error) {
   if (error != nil) { return; }

   // Task succeeded.
   // ...
}];

3. Pobieranie informacji o obiektach z etykietami

Jeśli oznaczenie obrazów zakończy się powodzeniem, moduł obsługi ukończenia otrzyma tablicę obiektów ImageLabel. Każdy obiekt ImageLabel reprezentuje coś, co zostało oznaczone etykietą na obrazie. Model podstawowy obsługuje ponad 400 różnych etykiet. Możesz uzyskać opis tekstowy każdej etykiety, indeks wszystkich etykiet obsługiwanych przez model oraz wskaźnik ufności dopasowania. Na przykład:

Swift

for label in labels {
    let labelText = label.text
    let confidence = label.confidence
    let index = label.index
}

Objective-C

for (MLKImageLabel *label in labels) {
   NSString *labelText = label.text;
   float confidence = label.confidence;
   NSInteger index = label.index;
}

Wskazówki dotyczące poprawy skuteczności w czasie rzeczywistym

Jeśli chcesz oznaczać etykietami obrazy w aplikacji przesyłającej dane w czasie rzeczywistym, postępuj zgodnie z tymi wytycznymi, aby uzyskać najlepszą liczbę klatek na sekundę:

  • Do przetwarzania klatek wideo użyj synchronicznego interfejsu API results(in:) twórcy etykiet obrazów. Wywołaj tę metodę z funkcji captureOutput(_, didOutput:from:) obiektu AVCaptureVideoDataOutputSampleBufferDelegate, aby synchronicznie pobierać wyniki z danej klatki wideo. Zachowaj alwaysDiscardsLateVideoFrames elementu AVCaptureVideoDataOutput jako true, aby ograniczyć wywołania osoby oznaczającej obrazy. Jeśli podczas działania etykiety obrazów pojawi się nowa ramka wideo, zostanie ona usunięta.
  • Jeśli używasz danych wyjściowych narzędzia do etykietowania obrazów do nałożenia grafiki na obraz wejściowy, najpierw pobierz wynik z pakietu ML Kit, a następnie w jednym kroku wyrenderuj obraz i nakładkę. Dzięki temu na każdą przetworzoną klatkę wejściową renderujesz się tylko raz. Przykład znajdziesz w sekcji updatePreviewOverlayViewWithLastFrame w przykładowym krótkim wprowadzeniu do ML Kit.