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

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

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

  1. اگر قبلاً Firebase را به برنامه خود اضافه نکرده اید، این کار را با دنبال کردن مراحل راهنمای شروع کار انجام دهید.
  2. کتابخانه‌های ML Kit را در فایل پادفایل خود قرار دهید:
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionAutoML', '6.25.0'
    
    پس از نصب یا به‌روزرسانی Pods پروژه، حتماً پروژه Xcode خود را با استفاده از .xcworkspace آن باز کنید.
  3. در برنامه خود، Firebase را وارد کنید:

    سریع

    import Firebase

    هدف-C

    @import Firebase;

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

ML Kit مدل های تولید شده توسط AutoML شما را روی دستگاه اجرا می کند. با این حال، می‌توانید ML Kit را برای بارگیری مدل خود از راه دور از Firebase، از ذخیره‌سازی محلی یا هر دو پیکربندی کنید.

با میزبانی مدل در Firebase، می‌توانید مدل را بدون انتشار نسخه جدید برنامه به‌روزرسانی کنید و می‌توانید از Remote Config و A/B Testing برای ارائه پویا مدل‌های مختلف به مجموعه‌های مختلف کاربران استفاده کنید.

اگر ترجیح می‌دهید مدل را فقط با میزبانی آن در Firebase ارائه دهید، و آن را با برنامه خود همراه نکنید، می‌توانید حجم دانلود اولیه برنامه خود را کاهش دهید. البته به خاطر داشته باشید که اگر مدل با برنامه شما همراه نباشد، تا زمانی که برنامه شما برای اولین بار مدل را دانلود نکند، هیچ عملکرد مرتبط با مدل در دسترس نخواهد بود.

با بسته‌بندی مدل خود با برنامه‌تان، می‌توانید مطمئن شوید که ویژگی‌های ML برنامه‌تان همچنان در زمانی که مدل میزبانی شده توسط Firebase در دسترس نیست، کار می‌کنند.

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

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

سریع

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

هدف-C

FIRAutoMLRemoteModel *remoteModel = [[FIRAutoMLRemoteModel 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

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

NSProgress *downloadProgress =
    [[FIRModelManager modelManager] downloadRemoteModel:remoteModel
                                             conditions:downloadConditions];

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

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

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

  1. مدل و ابرداده‌های آن را از آرشیو فشرده‌ای که از کنسول Firebase دانلود کرده‌اید در یک پوشه استخراج کنید:
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
    هر سه فایل باید در یک پوشه باشند. توصیه می‌کنیم از فایل‌ها در حین دانلود، بدون تغییر (از جمله نام فایل) استفاده کنید.
  2. پوشه را در پروژه Xcode خود کپی کنید، مراقب باشید که هنگام انجام این کار ، Create folder references را انتخاب کنید. فایل مدل و ابرداده در بسته برنامه گنجانده شده و برای ML Kit در دسترس خواهد بود.
  3. یک شی AutoMLLocalModel ایجاد کنید و مسیر فایل مانیفست مدل را مشخص کنید:

    سریع

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

    هدف-C

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

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

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

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

سریع

let options = VisionOnDeviceAutoMLImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = 0  // Evaluate your model in the Firebase console
                                 // to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: options)

هدف-C

FIRVisionOnDeviceAutoMLImageLabelerOptions *options =
    [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = 0;  // Evaluate your model in the Firebase console
                                  // to determine an appropriate value.
FIRVisionImageLabeler *labeler =
    [[FIRVision vision] onDeviceAutoMLImageLabelerWithOptions:options];

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

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

سریع

var options: VisionOnDeviceAutoMLImageLabelerOptions?
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = VisionOnDeviceAutoMLImageLabelerOptions(remoteModel: remoteModel)
} else {
  options = VisionOnDeviceAutoMLImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = 0  // Evaluate your model in the Firebase console
                                 // to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: options)

هدف-C

VisionOnDeviceAutoMLImageLabelerOptions *options;
if ([[FIRModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = 0.0f;  // Evaluate your model in the Firebase console
                                     // to determine an appropriate value.
FIRVisionImageLabeler *labeler = [[FIRVision vision] onDeviceAutoMLImageLabelerWithOptions:options];

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

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

سریع

NotificationCenter.default.addObserver(
    forName: .firebaseMLModelDownloadDidSucceed,
    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: .firebaseMLModelDownloadDidFail,
    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:FIRModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

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

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

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

2. تصویر ورودی را آماده کنید

سپس، برای هر تصویری که می خواهید برچسب گذاری کنید، با استفاده از یکی از گزینه های توضیح داده شده در این بخش، یک شی VisionImage ایجاد کنید و آن را به نمونه ای از VisionImageLabeler (که در قسمت بعدی توضیح داده شد) ارسال کنید.

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

برای استفاده از UIImage :

  1. در صورت لزوم، تصویر را بچرخانید تا ویژگی imageOrientation آن .up باشد.
  2. یک شی VisionImage با استفاده از UIImage با چرخش صحیح ایجاد کنید. هیچ ابرداده چرخشی را مشخص نکنید—مقدار پیش‌فرض، .topLeft . باید استفاده شود.

    سریع

    let image = VisionImage(image: uiImage)

    هدف-C

    FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

برای استفاده از CMSampleBufferRef :

  1. یک شی VisionImageMetadata ایجاد کنید که جهت داده های تصویر موجود در بافر CMSampleBufferRef را مشخص می کند.

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

    سریع

    func imageOrientation(
        deviceOrientation: UIDeviceOrientation,
        cameraPosition: AVCaptureDevice.Position
        ) -> VisionDetectorImageOrientation {
        switch deviceOrientation {
        case .portrait:
            return cameraPosition == .front ? .leftTop : .rightTop
        case .landscapeLeft:
            return cameraPosition == .front ? .bottomLeft : .topLeft
        case .portraitUpsideDown:
            return cameraPosition == .front ? .rightBottom : .leftBottom
        case .landscapeRight:
            return cameraPosition == .front ? .topRight : .bottomRight
        case .faceDown, .faceUp, .unknown:
            return .leftTop
        }
    }

    هدف-C

    - (FIRVisionDetectorImageOrientation)
        imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                               cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationLeftTop;
          } else {
            return FIRVisionDetectorImageOrientationRightTop;
          }
        case UIDeviceOrientationLandscapeLeft:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationBottomLeft;
          } else {
            return FIRVisionDetectorImageOrientationTopLeft;
          }
        case UIDeviceOrientationPortraitUpsideDown:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationRightBottom;
          } else {
            return FIRVisionDetectorImageOrientationLeftBottom;
          }
        case UIDeviceOrientationLandscapeRight:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationTopRight;
          } else {
            return FIRVisionDetectorImageOrientationBottomRight;
          }
        default:
          return FIRVisionDetectorImageOrientationTopLeft;
      }
    }

    سپس، شی فوق داده را ایجاد کنید:

    سریع

    let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
    let metadata = VisionImageMetadata()
    metadata.orientation = imageOrientation(
        deviceOrientation: UIDevice.current.orientation,
        cameraPosition: cameraPosition
    )

    هدف-C

    FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
    AVCaptureDevicePosition cameraPosition =
        AVCaptureDevicePositionBack;  // Set to the capture device you used.
    metadata.orientation =
        [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                     cameraPosition:cameraPosition];
  2. یک شی VisionImage با استفاده از شی CMSampleBufferRef و ابرداده چرخش ایجاد کنید:

    سریع

    let image = VisionImage(buffer: sampleBuffer)
    image.metadata = metadata

    هدف-C

    FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
    image.metadata = metadata;

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

برای برچسب گذاری اشیاء در یک تصویر، شی VisionImage را به متد process() VisionImageLabeler ارسال کنید:

سریع

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

    // Task succeeded.
    // ...
}

هدف-C

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

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

اگر برچسب‌گذاری تصویر با موفقیت انجام شود، آرایه‌ای از اشیاء VisionImageLabel به کنترل‌کننده تکمیل ارسال می‌شود. از هر شی، می توانید اطلاعاتی در مورد ویژگی شناسایی شده در تصویر دریافت کنید.

مثلا:

سریع

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

هدف-C

for (FIRVisionImageLabel *label in labels) {
  NSString *labelText = label.text;
  NSNumber *confidence = label.confidence;
}

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

  • دریچه گاز به آشکارساز زنگ می زند. اگر یک قاب ویدیویی جدید در حین کار کردن آشکارساز در دسترس قرار گرفت، قاب را رها کنید.
  • اگر از خروجی آشکارساز برای همپوشانی گرافیک روی تصویر ورودی استفاده می‌کنید، ابتدا نتیجه را از کیت ML دریافت کنید، سپس تصویر را رندر کنید و در یک مرحله همپوشانی کنید. با انجام این کار، برای هر فریم ورودی فقط یک بار به سطح نمایشگر رندر می دهید. به عنوان مثال، کلاس‌های previewOverlayView و FIRDetectionOverlayView را در برنامه نمونه ویترینی ببینید.