iOS'te AutoML ile eğitilmiş bir model kullanarak görüntüleri etiketleme

AutoML Vision Edge'i kullanarak kendi modelinizi eğittikten sonra, bu modeli uygulamanızda kullanarak görüntüleri etiketleyebilirsiniz.

AutoML Vision Edge'de eğitilen modelleri entegre etmenin iki yolu vardır. Modelin dosyalarını Xcode projenize kopyalayarak modeli paketleyebilir veya Firebase'den dinamik olarak indirebilirsiniz.

Model paketleme seçenekleri
Uygulamanızda paket halinde
  • Model, paketin bir parçasıdır
  • Model, iOS cihaz çevrimdışıyken bile hemen kullanılabilir.
  • Firebase projesine gerek yoktur
Firebase ile barındırılan
  • Modeli Firebase Makine Öğrenimi'ne yükleyerek barındırın.
  • Uygulama paketi boyutunu küçültür
  • Model, istek üzerine indirilir
  • Uygulamanızı yeniden yayınlamadan model güncellemelerini yayınlama
  • Firebase Remote Config ile kolay A/B testi
  • Firebase projesi gerekir

Deneyin

Başlamadan önce

1. ML Kit kitaplıklarını Pod dosyanıza ekleyin:

Bir modeli uygulamanızla paketlemek için:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    
Firebase'den dinamik olarak model indirmek için LinkFirebase bağımlılığını ekleyin:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    pod 'GoogleMLKit/LinkFirebase'
    
2. Projenizin Pod'larını yükledikten veya güncelledikten sonra, .xcworkspacekodu> kullanarak Xcode projenizi açın. ML Kit, Xcode 13.2.1 veya sonraki sürümlerde desteklenir. 3. Bir model indirmek istiyorsanız, henüz yapmadıysanız Firebase'i iOS projenize eklediğinizden emin olun. Modeli paketlediğinizde bu işlem gerekli değildir.

1. Modeli yükleme

Yerel model kaynağını yapılandırma

Modeli uygulamanızla paket haline getirmek için:

1. Modeli ve meta verilerini, Firebase konsolundan indirdiğiniz zip arşivinden bir klasöre ayıklayın:
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
Bu üç dosya aynı klasörde olmalıdır. Dosyaları, indirdiğiniz şekilde (dosya adları dahil) değiştirmeden kullanmanızı öneririz.

2. Klasörü Xcode projenize kopyalarken Klasör referansı oluştur'u seçtiğinizden emin olun. Model dosyası ve meta veriler uygulama paketine dahil edilir ve ML Kit tarafından kullanılabilir.

3. Model manifest dosyasının yolunu belirterek AutoMLImageLabelerLocalModel nesnesi oluşturun:
SwiftObjective-C
guard let manifestPath = Bundle.main.path(
    forResource: "manifest",
    ofType: "json",
    inDirectory: "your_model_directory"
) else { return }
let localModel = AutoMLImageLabelerLocalModel(manifestPath: manifestPath)
NSString *manifestPath =
    [NSBundle.mainBundle pathForResource:@"manifest"
                                  ofType:@"json"
                             inDirectory:@"your_model_directory"];
MLKAutoMLImageLabelerLocalModel *localModel =
    [[MLKAutoMLImageLabelerLocalModel alloc] initWithManifestPath:manifestPath];

Firebase tarafından barındırılan bir model kaynağını yapılandırma

Uzaktan barındırılan modeli kullanmak için modeli yayınlarken atadığınız adı belirten bir AutoMLImageLabelerRemoteModel nesnesi oluşturun:

SwiftObjective-C
let remoteModel = AutoMLImageLabelerRemoteModel(
    name: "your_remote_model"  // The name you assigned in
                               // the Firebase console.
)
MLKAutoMLImageLabelerRemoteModel *remoteModel =
    [[MLKAutoMLImageLabelerRemoteModel alloc]
        initWithName:@"your_remote_model"];  // The name you assigned in
                                             // the Firebase console.

Ardından, indirmeye izin vermek istediğiniz koşulları belirterek model indirme görevini başlatın. Model cihazda yoksa veya modelin daha yeni bir sürümü varsa görev, modeli Firebase'den eşzamansız olarak indirir:

SwiftObjective-C
let downloadConditions = ModelDownloadConditions(
  allowsCellularAccess: true,
  allowsBackgroundDownloading: true
)

let downloadProgress = ModelManager.modelManager().download(
  remoteModel,
  conditions: downloadConditions
)
MLKModelDownloadConditions *downloadConditions =
    [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
                                         allowsBackgroundDownloading:YES];

NSProgress *downloadProgress =
    [[MLKModelManager modelManager] downloadModel:remoteModel
                                       conditions:downloadConditions];

Birçok uygulama, indirme görevini başlatma kodunda başlatır ancak modeli kullanmadan önce istediğiniz zaman bu işlemi yapabilirsiniz.

Modelinizden resim etiketleyici oluşturma

Model kaynaklarınızı yapılandırdıktan sonra bunlardan birinde ImageLabeler nesnesi oluşturun.

Yalnızca yerel olarak paketlenmiş bir modeliniz varsa AutoMLImageLabelerLocalModel nesnenizle bir etiketleyici oluşturup zorunlu tutmak istediğiniz güven puanı eşiğini yapılandırmanız yeterlidir (Modunuzu değerlendirme bölümüne bakın:

SwiftObjective-C
let options = AutoMLImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)
MLKAutoMLImageLabelerOptions *options =
    [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = @(0.0);  // Evaluate your model in the Firebase console
                                       // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

Uzaktan barındırılan bir modeliniz varsa çalıştırmadan önce modelin indirildiğinden emin olmanız gerekir. Model yöneticisinin isModelDownloaded(remoteModel:) yöntemini kullanarak model indirme görevinin durumunu kontrol edebilirsiniz.

Bunu yalnızca etiketleyiciyi çalıştırmadan önce onaylamanız gerekir. Ancak hem uzakta barındırılan hem de yerel olarak paketlenmiş bir modeliniz varsa ImageLabeler öğesini örneklendirirken bu kontrolü gerçekleştirmeniz mantıklı olabilir: İndirilmişse uzak modelden, aksi takdirde yerel modelden etiketleyici oluşturun.

SwiftObjective-C
var options: AutoMLImageLabelerOptions!
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = AutoMLImageLabelerOptions(remoteModel: remoteModel)
} else {
  options = AutoMLImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)
MLKAutoMLImageLabelerOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[MLKAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = @(0.0);  // Evaluate your model in the Firebase console
                                       // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

Yalnızca uzaktan barındırılan bir modeliniz varsa modelin indirildiğini onaylayana kadar modelle ilgili işlevleri devre dışı bırakmanız (ör. kullanıcı arayüzünüzün bir bölümünü devre dışı bırakmak veya gizlemek) gerekir.

Varsayılan bildirim merkezine gözlemciler ekleyerek model indirme durumunu öğrenebilirsiniz. İndirme işlemi biraz zaman alabileceği ve kaynak nesne, indirme işlemi tamamlanana kadar serbest bırakılabileceği için gözlemci bloğunda self için zayıf referans kullandığınızdan emin olun. Örneğin:

SwiftObjective-C
NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidSucceed,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel,
        model.name == "your_remote_model"
        else { return }
    // The model was downloaded and is available on the device
}

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidFail,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel
        else { return }
    let error = userInfo[ModelDownloadUserInfoKey.error.rawValue]
    // ...
}
__weak typeof(self) weakSelf = self;

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel];
              if ([model.name isEqualToString:@"your_remote_model"]) {
                // The model was downloaded and is available on the device
              }
            }];

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidFailNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError];
            }];

2. Giriş resmini hazırlama

UIImage veya CMSampleBuffer kullanarak bir VisionImage nesnesi oluşturun.

UIImage kullanıyorsanız şu adımları uygulayın:

  • UIImage ile bir VisionImage nesnesi oluşturun. Doğru .orientation değerini belirttiğinizden emin olun.
    SwiftObjective-C
    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation
    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

CMSampleBuffer kullanıyorsanız şu adımları uygulayın:

  • CMSampleBuffer içinde bulunan resim verilerinin yönünü belirtin.

    Resim yönünü almak için:

    SwiftObjective-C
    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
      }
    }
          
    - (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;
      }
    }
          
  • CMSampleBuffer nesnesini ve yönünü kullanarak bir VisionImage nesnesi oluşturun:
    SwiftObjective-C
    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)
     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. Resim etiketleyiciyi çalıştırma

Eşzamansız olarak:

SwiftObjective-C
imageLabeler.process(image) { labels, error in
    guard error == nil, let labels = labels, !labels.isEmpty else {
        // Handle the error.
        return
    }
    // Show results.
}
[imageLabeler
    processImage:image
      completion:^(NSArray *_Nullable labels,
                   NSError *_Nullable error) {
        if (labels.count == 0) {
            // Handle the error.
            return;
        }
        // Show results.
     }];

Eşzamanlı olarak:

SwiftObjective-C
var labels: [ImageLabel]
do {
    labels = try imageLabeler.results(in: image)
} catch let error {
    // Handle the error.
    return
}
// Show results.
NSError *error;
NSArray *labels =
    [imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.

4. Etiketlenmiş nesneler hakkında bilgi edinme

Görüntü etiketleme işlemi başarılı olursa ImageLabel dizisi döndürülür. Her ImageLabel, resimde etiketlenmiş bir öğeyi temsil eder. Her etiketin metin açıklamasını (TensorFlow Lite model dosyasının meta verilerinde varsa), güven puanını ve dizinini alabilirsiniz. Örneğin:
SwiftObjective-C
for label in labels {
  let labelText = label.text
  let confidence = label.confidence
  let index = label.index
}
for (MLKImageLabel *label in labels) {
  NSString *labelText = label.text;
  float confidence = label.confidence;
  NSInteger index = label.index;
}

Gerçek zamanlı performansı iyileştirmeye yönelik ipuçları

Gerçek zamanlı bir uygulamada resimleri etiketlemek istiyorsanız en iyi kare hızlarına ulaşmak için aşağıdaki yönergeleri uygulayın:

  • Video karelerini işlemek için dedektörün results(in:) senkron API'sini kullanın. Belirli bir video karesinden eşzamanlı olarak sonuç almak için bu yöntemi AVCaptureVideoDataOutputSampleBufferDelegate'ın captureOutput(_, didOutput:from:) işlevinden çağırın. Algılayıcıya gelen aramaları azaltmak için AVCaptureVideoDataOutput'nin alwaysDiscardsLateVideoFrames değerini true olarak tutun. Algılayıcı çalışırken yeni bir video karesi kullanılabilir hale gelirse bu kare atlanır.
  • Giriş resmine grafik yerleştirmek için algılayıcının çıkışını kullanıyorsanız önce ML Kit'ten sonucu alın, ardından resmi ve yer paylaşımını tek bir adımda oluşturun. Böylece, işlenen her giriş karesi için ekran yüzeyinde yalnızca bir kez oluşturma işlemi gerçekleştirirsiniz. Örnek için ML Kit hızlı başlangıç örneğindeki updatePreviewOverlayViewWithLastFrame işlevine bakın.