با ML Kit در iOS اشیاء را شناسایی و ردیابی کنید

می توانید از کیت ML برای شناسایی و ردیابی اشیاء در فریم های ویدیویی متوالی استفاده کنید.

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

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

قبل از شروع

  1. پادهای کیت ML زیر را در فایل پادفایل خود قرار دهید:
    pod 'GoogleMLKit/ObjectDetection', '3.2.0'
    
  2. پس از نصب یا به روز رسانی Pods پروژه خود، پروژه Xcode خود را با استفاده از .xcworkspace . آن باز کنید. کیت ML در Xcode نسخه 12.4 یا بالاتر پشتیبانی می شود.

1. آشکارساز شی را پیکربندی کنید

برای شناسایی و ردیابی اشیا، ابتدا یک نمونه از ObjectDetector ایجاد کنید و به صورت اختیاری تنظیمات آشکارساز را که می خواهید از حالت پیش فرض تغییر دهید، مشخص کنید.

  1. با یک شی ObjectDetectorOptions آشکارساز شی را برای مورد استفاده خود پیکربندی کنید. می توانید تنظیمات زیر را تغییر دهید:

    تنظیمات آشکارساز شی
    حالت تشخیص .stream (پیش فرض) | .singleImage

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

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

    چندین اشیاء را شناسایی و ردیابی کنید false (پیش فرض) | true

    آیا برای شناسایی و ردیابی حداکثر پنج شی یا فقط برجسته ترین شی (پیش فرض).

    طبقه بندی اشیاء false (پیش فرض) | true

    اینکه آیا اشیاء شناسایی شده در دسته های درشت طبقه بندی شوند یا نه. هنگامی که آشکارساز شیء فعال باشد، اشیاء را به دسته‌های زیر طبقه‌بندی می‌کند: کالاهای مد، غذا، کالاهای خانگی، مکان‌ها و گیاهان.

    API تشخیص و ردیابی شی برای این دو مورد اصلی بهینه شده است:

    • تشخیص زنده و ردیابی برجسته ترین شی در منظره یاب دوربین.
    • تشخیص چندین شی در یک تصویر ثابت

    برای پیکربندی API برای این موارد استفاده:

سویفت

// Live detection and tracking
let options = ObjectDetectorOptions()
options.shouldEnableClassification = true

// Multiple object detection in static images
let options = ObjectDetectorOptions()
options.detectorMode = .singleImage
options.shouldEnableMultipleObjects = true
options.shouldEnableClassification = true

هدف-C

// Live detection and tracking
MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init];
options.shouldEnableClassification = YES;

// Multiple object detection in static images
MLKObjectDetectorOptions *options = [[MLKOptions alloc] init];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableMultipleObjects = YES;
options.shouldEnableClassification = YES;
  1. نمونه ای از ObjectDetector را دریافت کنید:

سویفت

let objectDetector = ObjectDetector.objectDetector()

// Or, to change the default settings:
let objectDetector = ObjectDetector.objectDetector(options: options)

هدف-C

MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector];

// Or, to change the default settings:
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];

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

برای شناسایی و ردیابی اشیاء، برای هر تصویر یا فریم ویدیو، موارد زیر را انجام دهید. اگر حالت استریم را فعال کرده اید، باید اشیاء VisionImage از CMSampleBuffer s ایجاد کنید.

با استفاده از 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. تصویر را پردازش کنید

VisionImage به یکی از روش های پردازش تصویر آشکارساز شی منتقل کنید. می توانید از روش process(image:) یا results() استفاده کنید.

برای تشخیص اشیاء به صورت ناهمزمان:

سویفت

objectDetector.process(image) { objects, error in
  guard error == nil else {
    // Error.
    return
  }
  guard !objects.isEmpty else {
    // No objects detected.
    return
  }

  // Success. Get object info here.
  // ...
}

هدف-C

[objectDetector processImage:image
                  completion:^(NSArray * _Nullable objects,
                               NSError * _Nullable error) {
                    if (error == nil) {
                      return;
                    }
                    if (objects.count == 0) {
                      // No objects detected.
                      return;
                    }

                    // Success. Get object info here.
                  }];

برای تشخیص همزمان اشیا:

سویفت

var objects: [Object]
do {
  objects = try objectDetector.results(in: image)
} catch let error {
  print("Failed to detect object with error: \(error.localizedDescription).")
  return
}
guard !objects.isEmpty else {
  print("Object detector returned no results.")
  return
}

// Success. Get object info here.

هدف-C

NSError *error;
NSArray *objects = [objectDetector resultsInImage:image error:&error];
if (error == nil) {
  return;
}
if (objects.count == 0) {
  // No objects detected.
  return;
}

// Success. Get object info here.

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

اگر فراخوانی پردازشگر تصویر با موفقیت انجام شود، بسته به اینکه روش ناهمزمان یا همزمان را فراخوانی کرده اید، فهرستی از Object را به کنترل کننده تکمیل ارسال می کند یا لیست را برمی گرداند.

هر Object شامل ویژگی های زیر است:

frame یک CGRect که موقعیت شی را در تصویر نشان می دهد.
trackingID یک عدد صحیح که شی را در بین تصاویر شناسایی می کند، یا "nil" در حالت تک تصویری.
labels آرایه‌ای از برچسب‌ها که شی بازگردانده شده توسط آشکارساز را توصیف می‌کنند. اگر گزینه آشکارساز shouldEnableClassification روی false تنظیم شود، ویژگی خالی است.

سویفت

// objects contains one item if multiple object detection wasn't enabled.
for object in objects {
  let frame = object.frame
  let trackingID = object.trackingID

  // If classification was enabled:
  let description = object.labels.enumerated().map { (index, label) in
    "Label \(index): \(label.text), \(label.confidence)"
    }.joined(separator:"\n")

}

هدف-C

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (MLKObject *object in objects) {
  CGRect frame = object.frame;
  NSNumber *trackingID = object.trackingID;
  for (MLKObjectLabel *label in object.labels) {
    NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu",
      label.text, label.confidence, (unsigned long)label.index];
    ...
  }
}

بهبود قابلیت استفاده و عملکرد

برای بهترین تجربه کاربری، این دستورالعمل ها را در برنامه خود دنبال کنید:

  • تشخیص موفق شی به پیچیدگی بصری شی بستگی دارد. برای شناسایی، اشیاء با تعداد کمی از ویژگی های بصری ممکن است نیاز داشته باشند که بخش بیشتری از تصویر را اشغال کنند. شما باید راهنمایی هایی را در مورد گرفتن ورودی به کاربران ارائه دهید که به خوبی با نوع اشیایی که می خواهید شناسایی کنید کار می کند.
  • هنگامی که از طبقه بندی استفاده می کنید، اگر می خواهید اشیایی را شناسایی کنید که به طور واضح در دسته های پشتیبانی شده قرار نمی گیرند، مدیریت ویژه ای را برای اشیاء ناشناخته اجرا کنید.

همچنین، مجموعه الگوهای طراحی مواد را برای مجموعه ویژگی‌های مبتنی بر یادگیری ماشین بررسی کنید.

هنگامی که از حالت پخش در یک برنامه بلادرنگ استفاده می کنید، برای دستیابی به بهترین نرخ فریم، این دستورالعمل ها را دنبال کنید:

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