تصاویر را با یک مدل آموزش دیده با AutoML در iOS برچسب گذاری کنید

بعد از اینکه مدل خود را با استفاده از AutoML Vision Edge آموزش دادید ، می‌توانید از آن در برنامه خود برای برچسب‌گذاری تصاویر استفاده کنید.

دو راه برای ادغام مدل های آموزش دیده از AutoML Vision Edge وجود دارد. می‌توانید با کپی کردن فایل‌های مدل در پروژه Xcode، مدل را باندل کنید یا می‌توانید آن را به صورت پویا از Firebase دانلود کنید.

گزینه های بسته بندی مدل
همراه با برنامه شما
  • مدل بخشی از بسته نرم افزاری است
  • این مدل بلافاصله در دسترس است، حتی زمانی که دستگاه iOS آفلاین است
  • بدون نیاز به پروژه Firebase
میزبانی شده با Firebase
  • مدل را با آپلود آن در Firebase Machine Learning میزبانی کنید
  • اندازه بسته نرم افزاری را کاهش می دهد
  • مدل در صورت تقاضا دانلود می شود
  • به روز رسانی مدل را بدون انتشار مجدد برنامه خود فشار دهید
  • تست آسان A/B با Firebase Remote Config
  • به پروژه Firebase نیاز دارد

آن را امتحان کنید

قبل از اینکه شروع کنی

1. کتابخانه های ML Kit را در پادفایل خود قرار دهید:

برای بسته‌بندی یک مدل با برنامه خود:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    
برای بارگیری پویا یک مدل از Firebase، وابستگی LinkFirebase را اضافه کنید:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    pod 'GoogleMLKit/LinkFirebase'
    
2. پس از نصب یا به‌روزرسانی Pods پروژه، پروژه Xcode خود را با استفاده از کد .xcworkspace . آن باز کنید. کیت ML در Xcode نسخه 13.2.1 یا بالاتر پشتیبانی می شود. 3. اگر می خواهید مدلی را دانلود کنید ، مطمئن شوید که Firebase را به پروژه iOS خود اضافه کرده اید ، اگر قبلاً این کار را انجام نداده اید. هنگامی که مدل را بسته بندی می کنید، این مورد نیاز نیست.

1. مدل را بارگذاری کنید

یک منبع مدل محلی را پیکربندی کنید

برای بسته‌بندی مدل با برنامه‌تان:

1. مدل و ابرداده آن را از بایگانی zip که از کنسول Firebase دانلود کرده اید در یک پوشه استخراج کنید:
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
هر سه فایل باید در یک پوشه باشند. توصیه می‌کنیم از فایل‌ها در حین دانلود، بدون تغییر (از جمله نام فایل) استفاده کنید.

2. پوشه را در پروژه Xcode خود کپی کنید، مراقب باشید که هنگام انجام این کار ، Create folder references را انتخاب کنید. فایل مدل و ابرداده در بسته برنامه گنجانده شده و برای ML Kit در دسترس خواهد بود.

3. شی AutoMLImageLabelerLocalModel را ایجاد کنید و مسیر فایل مانیفست مدل را مشخص کنید:

سریع

guard let manifestPath = Bundle.main.path(
    forResource: "manifest",
    ofType: "json",
    inDirectory: "your_model_directory"
) else { return }
let localModel = AutoMLImageLabelerLocalModel(manifestPath: manifestPath)

هدف-C

NSString *manifestPath =
    [NSBundle.mainBundle pathForResource:@"manifest"
                                  ofType:@"json"
                             inDirectory:@"your_model_directory"];
MLKAutoMLImageLabelerLocalModel *localModel =
    [[MLKAutoMLImageLabelerLocalModel alloc] initWithManifestPath:manifestPath];

یک منبع مدل میزبانی شده توسط Firebase را پیکربندی کنید

برای استفاده از مدل میزبانی شده از راه دور، یک شی AutoMLImageLabelerRemoteModel ایجاد کنید و نامی را که به مدل اختصاص داده اید هنگام انتشار آن مشخص کنید:

سریع

let remoteModel = AutoMLImageLabelerRemoteModel(
    name: "your_remote_model"  // The name you assigned in
                               // the Firebase console.
)

هدف-C

MLKAutoMLImageLabelerRemoteModel *remoteModel =
    [[MLKAutoMLImageLabelerRemoteModel alloc]
        initWithName:@"your_remote_model"];  // The name you assigned in
                                             // the Firebase console.

سپس، با مشخص کردن شرایطی که می‌خواهید اجازه دانلود را بدهید، کار دانلود مدل را شروع کنید. اگر مدل در دستگاه نباشد، یا اگر نسخه جدیدتری از مدل موجود باشد، این کار به صورت ناهمزمان مدل را از Firebase دانلود می‌کند:

سریع

let downloadConditions = ModelDownloadConditions(
  allowsCellularAccess: true,
  allowsBackgroundDownloading: true
)

let downloadProgress = ModelManager.modelManager().download(
  remoteModel,
  conditions: downloadConditions
)

هدف-C

MLKModelDownloadConditions *downloadConditions =
    [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
                                         allowsBackgroundDownloading:YES];

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

بسیاری از برنامه‌ها وظیفه دانلود را در کد اولیه خود شروع می‌کنند، اما شما می‌توانید این کار را در هر زمانی قبل از نیاز به استفاده از مدل انجام دهید.

یک برچسب تصویر از مدل خود ایجاد کنید

پس از پیکربندی منابع مدل خود، یک شی ImageLabeler از یکی از آنها ایجاد کنید.

اگر فقط یک مدل به صورت محلی دارید، فقط یک برچسب از شی AutoMLImageLabelerLocalModel خود ایجاد کنید و آستانه امتیاز اطمینان مورد نیاز خود را پیکربندی کنید (به ارزیابی حالت خود مراجعه کنید:

سریع

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)

هدف-C

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

اگر یک مدل با میزبانی از راه دور دارید، قبل از اجرای آن باید بررسی کنید که دانلود شده است. با استفاده از روش isModelDownloaded (RemoteModel:) مدیر مدل می توانید وضعیت وظیفه دانلود مدل را بررسی کنید.

اگرچه شما فقط باید قبل از اجرای برچسب‌گذار این موضوع را تأیید کنید، اگر هم یک مدل با میزبانی از راه دور و هم یک مدل همراه با محلی دارید، ممکن است این بررسی را هنگام نمونه‌برداری از ImageLabeler انجام دهید: اگر یک برچسب‌گذاری از مدل راه دور ایجاد کنید. دانلود شده است، و در غیر این صورت از مدل محلی.

سریع

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)

هدف-C

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

اگر فقط یک مدل با میزبانی از راه دور دارید، باید عملکردهای مربوط به مدل را غیرفعال کنید - به عنوان مثال، خاکستری کردن یا پنهان کردن بخشی از رابط کاربری خود - تا زمانی که تأیید کنید مدل دانلود شده است.

می‌توانید با پیوست کردن ناظران به مرکز اطلاع رسانی پیش‌فرض، وضعیت دانلود مدل را دریافت کنید. مطمئن شوید که از یک مرجع ضعیف به self در بلوک ناظر استفاده کنید، زیرا دانلودها ممکن است مدتی طول بکشد، و شی مبدا می‌تواند تا پایان دانلود آزاد شود. مثلا:

سریع

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]
    // ...
}

هدف-C

__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. تصویر ورودی را آماده کنید

با استفاده از UIImage یا CMSampleBuffer یک شی VisionImage ایجاد کنید.

اگر از UIImage استفاده می کنید، این مراحل را دنبال کنید:

  • با UIImage یک شی VisionImage ایجاد کنید. مطمئن شوید که جهت .orientation را مشخص کرده اید.

    سریع

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

    هدف-C

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

اگر از CMSampleBuffer استفاده می کنید، این مراحل را دنبال کنید:

  • جهت داده های تصویر موجود در CMSampleBuffer را مشخص کنید.

    برای دریافت جهت تصویر:

    سریع

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

    هدف-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;
      }
    }
          
  • یک شی VisionImage با استفاده از شی CMSampleBuffer و جهت گیری ایجاد کنید:

    سریع

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

    هدف-C

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

3. برچسب تصویر را اجرا کنید

به صورت ناهمزمان:

سریع

imageLabeler.process(image) { labels, error in
    guard error == nil, let labels = labels, !labels.isEmpty else {
        // Handle the error.
        return
    }
    // Show results.
}

هدف-C

[imageLabeler
    processImage:image
      completion:^(NSArray *_Nullable labels,
                   NSError *_Nullable error) {
        if (labels.count == 0) {
            // Handle the error.
            return;
        }
        // Show results.
     }];

به صورت همزمان:

سریع

var labels: [ImageLabel]
do {
    labels = try imageLabeler.results(in: image)
} catch let error {
    // Handle the error.
    return
}
// Show results.

هدف-C

NSError *error;
NSArray *labels =
    [imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.

4. اطلاعاتی در مورد اشیاء برچسب دار دریافت کنید

اگر عملیات برچسب‌گذاری تصویر با موفقیت انجام شود، آرایه‌ای از ImageLabel را برمی‌گرداند. هر ImageLabel چیزی را نشان می دهد که در تصویر برچسب گذاری شده است. می‌توانید توضیحات متنی هر برچسب (در صورت موجود بودن در فراداده فایل مدل TensorFlow Lite)، امتیاز اطمینان و فهرست را دریافت کنید. مثلا:

سریع

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

هدف-C

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

نکاتی برای بهبود عملکرد در زمان واقعی

اگر می خواهید تصاویر را در یک برنامه بلادرنگ برچسب گذاری کنید، این دستورالعمل ها را دنبال کنید تا به بهترین نرخ فریم برسید:

  • برای پردازش فریم‌های ویدئویی، از API همگام results(in:) آشکارساز استفاده کنید. این روش را از captureOutput(_, didOutput:from:) AVCaptureVideoDataOutputSampleBufferDelegate فراخوانی کنید تا به طور همزمان نتایج را از فریم ویدیوی داده شده دریافت کنید. قاب‌های AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames DiscardsLateVideoFrames را برای کاهش تماس‌های آشکارساز true نگه دارید. اگر یک قاب ویدیویی جدید در حالی که آشکارساز در حال کار است در دسترس باشد، حذف خواهد شد.
  • اگر از خروجی آشکارساز برای همپوشانی گرافیک روی تصویر ورودی استفاده می‌کنید، ابتدا نتیجه را از کیت ML بگیرید، سپس تصویر را در یک مرحله رندر کنید و همپوشانی کنید. با انجام این کار، برای هر فریم ورودی پردازش شده فقط یک بار به سطح نمایشگر رندر می دهید. به عنوان مثال به updatePreviewOverlayViewWithLastFrame در نمونه راه اندازی سریع ML Kit مراجعه کنید.