Oznaczanie obrazów za pomocą ML Kit na iOS

Za pomocą ML Kit możesz dodawać etykiety do obiektów rozpoznanych na obrazie. Domyślny model dostępny w systemie ML Kit obsługuje ponad 400 różnych etykiet.

Zanim zaczniesz

  1. Uwzględnij te pody ML Kit w pliku podfile:
    pod 'GoogleMLKit/ImageLabeling', '3.2.0'
    
  2. Po zainstalowaniu lub zaktualizowaniu podów w projekcie możesz otworzyć projekt Xcode za pomocą .xcworkspace. Pakiet ML Kit jest obsługiwany w Xcode w wersji 12.4 lub nowszej.

Możesz już dodawać etykiety do obrazów.

1. Przygotowanie obrazu wejściowego

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

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

  • Utwórz obiekt VisionImage z elementem UIImage. Podaj właściwy element .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 obrazu zawartych w: CMSampleBuffer.

    Aby uzyskać 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ą obiektu CMSampleBuffer i orientacji:

    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. Skonfiguruj i uruchom narzędzie do oznaczania obrazów

Aby oznaczyć obiekty obrazem, przekaż obiekt VisionImage do metody processImage() i ImageLabeler.

  1. Najpierw uzyskaj 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. Uzyskiwanie informacji o obiektach oznaczonych etykietą

Jeśli dodanie etykiet do obrazu powiedzie się, moduł obsługi ukończenia otrzymuje tablicę obiektów ImageLabel. Każdy obiekt ImageLabel reprezentuje coś, co zostało oznaczone na obrazie. Model podstawowy obsługuje ponad 400 etykiet. Można uzyskać opis tekstu każdej etykiety, indeks wszystkich etykiet obsługiwanych przez model oraz wskaźnik ufności dopasowania. 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, jak poprawić skuteczność w czasie rzeczywistym

Jeśli chcesz dodawać etykiety do obrazów w aplikacji w czasie rzeczywistym, postępuj zgodnie z tymi wskazówkami, aby uzyskać najlepszą liczbę klatek na sekundę:

  • Do przetwarzania ramek wideo użyj synchronicznego interfejsu API results(in:) etykiet obrazów. Wywołaj tę metodę z funkcji AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:), aby synchronicznie uzyskać wyniki z konkretnej klatki wideo. Zachowaj AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames jako true, aby ograniczyć wywołania do osoby oznaczającej obrazy. Jeśli nowa ramka wideo stanie się dostępna, gdy etykieta obrazu będzie aktywna, zostanie usunięta.
  • Jeśli używasz danych wyjściowych osoby oznaczającej obraz, aby nakładać grafikę na obraz wejściowy, najpierw uzyskaj wynik z ML Kit, a potem wyrenderuj obraz i nakładkę w jednym kroku. W ten sposób możesz wyświetlić na ekranie wyświetlacz tylko raz dla każdej przetworzonej klatki wejściowej. Przykład znajdziesz w przykładzie update PreviewNakładkaViewWithLastFrame w krótkim podsumowaniu dotyczącym ML Kit.