راهنمای تقسیم بندی تصویر برای iOS

وظیفه Image Segmenter به شما امکان می دهد تصاویر را بر اساس دسته های از پیش تعریف شده به مناطق تقسیم کنید و جلوه های بصری مانند محو کردن پس زمینه را اعمال کنید. این دستورالعمل‌ها به شما نشان می‌دهند که چگونه از Image Segmenter با برنامه‌های iOS استفاده کنید.

نمونه کد شرح داده شده در این دستورالعمل ها در GitHub موجود است.

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

نمونه کد

مثال کد MediaPipe Tasks شامل اجرای ساده یک برنامه Image Segmenter برای iOS است.

این مثال یک قطعه‌ساز تصویر را پیاده‌سازی می‌کند که ماسک‌های دسته‌بندی را خروجی می‌دهد. از دوربین یک دستگاه فیزیکی iOS برای انجام بخش‌بندی تصویر در فید دوربین زنده یا روی تصاویر و ویدیوها از گالری دستگاه استفاده می‌کند.

می‌توانید از برنامه به‌عنوان نقطه شروع برای برنامه iOS خودتان استفاده کنید، یا هنگام تغییر یک برنامه موجود به آن مراجعه کنید. کد نمونه Image Segmenter در GitHub میزبانی می شود.

کد را دانلود کنید

دستورالعمل های زیر به شما نشان می دهد که چگونه با استفاده از ابزار خط فرمان git یک کپی محلی از کد مثال ایجاد کنید.

برای دانلود کد نمونه:

  1. با استفاده از دستور زیر مخزن git را کلون کنید:

    git clone https://github.com/google-ai-edge/mediapipe-samples/
    
  2. به صورت اختیاری، نمونه git خود را برای استفاده از پرداخت پراکنده پیکربندی کنید، بنابراین فقط فایل‌های برنامه نمونه Image Segmenter را در اختیار داشته باشید:

    cd mediapipe
    git sparse-checkout init --cone
    git sparse-checkout set examples/image_segmentation/ios/
    

پس از ایجاد یک نسخه محلی از کد نمونه، می توانید کتابخانه وظایف MediaPipe را نصب کنید، پروژه را با استفاده از Xcode باز کنید و برنامه را اجرا کنید. برای دستورالعمل‌ها، به راهنمای راه‌اندازی برای iOS مراجعه کنید.

اجزای کلیدی

فایل های زیر حاوی کد حیاتی برای برنامه نمونه Image Segmenter هستند:

  • ImageSegmenterService.swift : Image Segmenter را راه اندازی می کند، انتخاب مدل را مدیریت می کند و استنتاج را روی داده های ورودی اجرا می کند.
  • CameraViewController.swift : رابط کاربری را برای حالت ورودی تغذیه زنده دوربین پیاده سازی می کند و نتایج را به تصویر می کشد.
  • MediaLibraryViewController.swift رابط کاربری را برای حالت ورودی تصویر ثابت و فایل ویدیویی پیاده‌سازی می‌کند و نتایج را تجسم می‌کند.

راه اندازی

این بخش مراحل کلیدی را برای راه اندازی محیط توسعه و پروژه های کد برای استفاده از Image Segmenter توضیح می دهد. برای اطلاعات کلی در مورد تنظیم محیط توسعه خود برای استفاده از وظایف MediaPipe، از جمله الزامات نسخه پلت فرم، به راهنمای راه اندازی برای iOS مراجعه کنید.

وابستگی ها

Image Segmenter از کتابخانه MediaPipeTasksVision استفاده می کند که باید با استفاده از CocoaPods نصب شود. این کتابخانه با هر دو برنامه Swift و Objective-C سازگار است و نیازی به تنظیمات زبان خاصی ندارد.

برای دستورالعمل‌های نصب CocoaPods در macOS، به راهنمای نصب CocoaPods مراجعه کنید. برای دستورالعمل‌های نحوه ایجاد یک Podfile با پادهای لازم برای برنامه خود، به استفاده از CocoaPods مراجعه کنید.

با استفاده از کد زیر، MediaPipeTasksVision pod را در Podfile اضافه کنید:

target 'MyImageSegmenterApp' do
  use_frameworks!
  pod 'MediaPipeTasksVision'
end

اگر برنامه شما شامل اهداف تست واحد است، برای اطلاعات بیشتر در مورد راه‌اندازی Podfile ، به راهنمای تنظیم برای iOS مراجعه کنید.

مدل

وظیفه MediaPipe Image Segmenter به یک مدل آموزش دیده نیاز دارد که با این کار سازگار باشد. برای اطلاعات بیشتر در مورد مدل‌های آموزش‌دیده موجود برای Image Segmenter، بخش مدل‌های نمای کلی کار را ببینید.

یک مدل را انتخاب و دانلود کنید و با استفاده از Xcode آن را به فهرست پروژه خود اضافه کنید. برای دستورالعمل‌هایی درباره نحوه افزودن فایل‌ها به پروژه Xcode، به مدیریت فایل‌ها و پوشه‌ها در پروژه Xcode خود مراجعه کنید.

از ویژگی BaseOptions.modelAssetPath برای تعیین مسیر مدل در بسته نرم افزاری خود استفاده کنید. برای مثال کد، بخش بعدی را ببینید.

کار را ایجاد کنید

شما می توانید وظیفه Image Segmenter را با فراخوانی یکی از اولیه سازهای آن ایجاد کنید. آغازگر ImageSegmenter(options:) مقادیری را برای گزینه های پیکربندی می پذیرد.

اگر نیازی به یک ImageSegmenter راه اندازی شده با گزینه های پیکربندی سفارشی ندارید، می توانید از مقداردهی اولیه ImageSegmenter(modelPath:) برای ایجاد یک Image Segmenter با گزینه های پیش فرض استفاده کنید. برای اطلاعات بیشتر درباره گزینه‌های پیکربندی، به نمای کلی پیکربندی مراجعه کنید.

وظیفه Image Segmenter از 3 نوع داده ورودی پشتیبانی می کند: تصاویر ثابت، فایل های ویدیویی و جریان های ویدیویی زنده. به طور پیش فرض، ImageSegmenter(modelPath:) یک کار را برای تصاویر ثابت مقداردهی اولیه می کند. اگر می‌خواهید وظیفه شما برای پردازش فایل‌های ویدیویی یا پخش جریانی زنده ویدیویی اولیه شود، از ImageSegmenter(options:) برای مشخص کردن حالت اجرای ویدیو یا پخش زنده استفاده کنید. حالت پخش زنده همچنین به گزینه پیکربندی imageSegmenterLiveStreamDelegate اضافی نیاز دارد که به Image Segmenter امکان می دهد نتایج تقسیم بندی تصویر را به صورت ناهمزمان به نماینده ارائه دهد.

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

سویفت

تصویر

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .image
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

let imageSegmenter = try ImageSegmenter(options: options)
    

ویدئو

import MediaPipeTasksVision

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

let imageSegmenter = try ImageSegmenter(options: options)
    

پخش زنده

import MediaPipeTasksVision

// Class that conforms to the `imageSegmenterLiveStreamDelegate` protocol and
// implements the method that the image segmenter calls once it finishes
// performing segmentation of each input frame.
class ImageSegmenterResultProcessor: NSObject, ImageSegmenterLiveStreamDelegate {

  func imageSegmenter(
    _ imageSegmenter: ImageSegmenter,
    didFinishSegmentation result: ImageSegmenterResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the image segmentation result or errors here.

  }
}

let modelPath = Bundle.main.path(forResource: "model",
                                      ofType: "tflite")

let options = ImageSegmenterOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.shouldOutputCategoryMask = true
options.shouldOutputConfidenceMasks = false

// Set `imageSegmenterLiveStreamDelegate` to the object of the class that
// confirms to the `ImageSegmenterLiveStreamDelegate` protocol.
let processor = ImageSegmenterResultProcessor()
options.imageSegmenterLiveStreamDelegate = processor

let imageSegmenter = try ImageSegmenter(options: options)
    

هدف-C

تصویر

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    

ویدئو

@import MediaPipeTasksVision;

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    

پخش زنده

@import MediaPipeTasksVision;

// Class that conforms to the `MPPImageSegmenterLiveStreamDelegate` protocol
// and implements the method that the image segmenter calls once it finishes
// performing segmentation of each input frame.

@interface APPImageSegmenterResultProcessor : NSObject 

@end

@implementation APPImageSegmenterResultProcessor

-   (void)imageSegmenter:(MPPImageSegmenter *)imageSegmenter
    didFinishSegmentationWithResult:(MPPImageSegmenterResult *)imageSegmenterResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the image segmentation result or errors here.

}

@end

NSString *modelPath = [[NSBundle mainBundle] pathForResource:@"model"
                                                      ofType:@"tflite"];

MPPImageSegmenterOptions *options = [[MPPImageSegmenterOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.shouldOutputCategoryMask = YES;
options.shouldOutputConfidenceMasks = NO;

// Set `imageSegmenterLiveStreamDelegate` to the object of the class that
// confirms to the `MPPImageSegmenterLiveStreamDelegate` protocol.
APPImageSegmenterResultProcessor *processor =
  [APPImageSegmenterResultProcessor new];
options.imageSegmenterLiveStreamDelegate = processor;

MPPImageSegmenter *imageSegmenter =
  [[MPPImageSegmenter alloc] initWithOptions:options error:nil];
    

اجرای کد نمونه Image Segmenter به کاربر اجازه می دهد تا بین حالت های پردازش جابجا شود. این رویکرد کد ایجاد کار را پیچیده‌تر می‌کند و ممکن است برای مورد استفاده شما مناسب نباشد.

گزینه های پیکربندی

این کار دارای گزینه های پیکربندی زیر برای برنامه های iOS است:

نام گزینه توضیحات محدوده ارزش مقدار پیش فرض
runningMode حالت اجرا را برای کار تنظیم می کند. سه حالت وجود دارد:

IMAGE: حالت برای ورودی های تک تصویر.

VIDEO: حالت برای فریم های رمزگشایی شده یک ویدیو.

LIVE_STREAM: حالت پخش زنده داده های ورودی، مانند دوربین. در این حالت، ImageSegmenterLiveStreamDelegate باید روی نمونه ای از کلاسی تنظیم شود که ImageSegmenterLiveStreamDelegate را برای دریافت نتایج تقسیم بندی به صورت ناهمزمان پیاده سازی می کند.
{ RunningMode.image, RunningMode.video, RunningMode.liveStream } RunningMode.image
shouldOutputCategoryMask اگر روی True تنظیم شود، خروجی شامل یک ماسک تقسیم بندی به عنوان یک تصویر uint8 است، که در آن هر مقدار پیکسل، مقدار دسته برنده را نشان می دهد. { True, False } False
shouldOutputConfidenceMasks اگر روی True تنظیم شود، خروجی شامل یک ماسک تقسیم‌بندی به‌عنوان تصویر مقدار شناور است، که در آن هر مقدار شناور نقشه امتیاز اطمینان دسته را نشان می‌دهد. { True, False } True
displayNamesLocale زبان برچسب‌ها را برای استفاده برای نام‌های نمایشی ارائه شده در فراداده مدل کار، در صورت وجود، تنظیم می‌کند. پیش فرض برای انگلیسی en است. با استفاده از TensorFlow Lite Metadata Writer API می‌توانید برچسب‌های محلی را به ابرداده یک مدل سفارشی اضافه کنید. کد محلی en
result_callback شنونده نتیجه را طوری تنظیم می‌کند که وقتی قطعه‌ساز تصویر در حالت LIVE_STREAM است، نتایج تقسیم‌بندی را به صورت ناهمزمان دریافت کند. فقط زمانی قابل استفاده است که حالت اجرا روی LIVE_STREAM تنظیم شده باشد N/A N/A

وقتی حالت در حال اجرا روی LIVE_STREAM تنظیم شده است، Image Segmenter به گزینه پیکربندی imageSegmenterLiveStreamDelegate اضافی نیاز دارد، که به Image Segmenter امکان می دهد نتایج تقسیم بندی تصویر را به صورت ناهمزمان ارائه دهد. نماینده باید متد imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) را پیاده سازی کند، که Image Segmenter پس از پردازش نتایج انجام تقسیم بندی در هر فریم آن را فراخوانی می کند.

نام گزینه توضیحات محدوده ارزش مقدار پیش فرض
imageSegmenterLiveStreamDelegate Image Segmenter را فعال می کند تا نتایج حاصل از انجام تقسیم بندی تصویر را به صورت ناهمزمان در حالت پخش زنده دریافت کند. کلاسی که نمونه آن روی این ویژگی تنظیم شده است باید متد imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) پیاده سازی کند. قابل اجرا نیست تنظیم نشده است

داده ها را آماده کنید

قبل از ارسال آن به Image Segmenter باید تصویر یا فریم ورودی را به یک شی MPImage تبدیل کنید. MPImage از انواع فرمت های تصویر iOS پشتیبانی می کند و می تواند از آنها در هر حالت در حال اجرا برای استنتاج استفاده کند. برای اطلاعات بیشتر در مورد MPImage ، به MPImage API مراجعه کنید.

یک قالب تصویر iOS را بر اساس مورد استفاده خود و حالت اجرای مورد نیاز برنامه خود انتخاب کنید. MPImage فرمت‌های تصویر UIImage ، CVPixelBuffer ، و CMSampleBuffer را می‌پذیرد.

تصویر UII

فرمت UIImage برای حالت‌های اجرای زیر مناسب است:

  • تصاویر: تصاویر از یک بسته نرم افزاری، گالری کاربر یا سیستم فایل فرمت شده به عنوان تصاویر UIImage را می توان به یک شی MPImage تبدیل کرد.

  • ویدیوها: از AVAssetImageGenerator برای استخراج فریم های ویدیو به فرمت CGImage استفاده کنید، سپس آنها را به تصاویر UIImage تبدیل کنید.

سویفت

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(uiImage: image)
    

هدف-C

// Load an image on the user's device as an iOS `UIImage` object.

// Convert the `UIImage` object to a MediaPipe's Image object having the default
// orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

این مثال یک MPImage با جهت پیش‌فرض UIImage.Orientation.Up مقداردهی اولیه می‌کند. می توانید یک MPImage با هر یک از مقادیر UIImage.Orientation پشتیبانی شده مقداردهی کنید. Image Segmenter جهت گیری های آینه شده مانند .upMirrored ، .downMirrored ، .leftMirrored ، .rightMirrored را پشتیبانی نمی کند.

برای اطلاعات بیشتر در مورد UIImage ، به UIImage Apple Developer Documentation مراجعه کنید.

CVPixelBuffer

فرمت CVPixelBuffer برای برنامه هایی که فریم تولید می کنند و از چارچوب CoreImage iOS برای پردازش استفاده می کنند، مناسب است.

فرمت CVPixelBuffer برای حالت‌های اجرای زیر مناسب است:

  • تصاویر: برنامه‌هایی که تصاویر CVPixelBuffer پس از مدتی پردازش با استفاده از چارچوب CoreImage iOS تولید می‌کنند، می‌توانند در حالت اجرای تصویر به قسمت Image Segmenter ارسال شوند.

  • فیلم‌ها: فریم‌های ویدیو را می‌توان برای پردازش به فرمت CVPixelBuffer تبدیل کرد و سپس در حالت ویدیو به بخش تصویر ارسال کرد.

  • پخش زنده: برنامه هایی که از دوربین iOS برای تولید فریم استفاده می کنند ممکن است قبل از ارسال به بخش تصویر در حالت پخش زنده به فرمت CVPixelBuffer برای پردازش تبدیل شوند.

سویفت

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(pixelBuffer: pixelBuffer)
    

هدف-C

// Obtain a CVPixelBuffer.

// Convert the `CVPixelBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithUIImage:image error:nil];
    

برای اطلاعات بیشتر در مورد CVPixelBuffer ، به مستندات برنامه‌نویس اپل CVPixelBuffer مراجعه کنید.

CMSampleBuffer

فرمت CMSampleBuffer نمونه‌های رسانه‌ای از یک نوع رسانه یکنواخت را ذخیره می‌کند و برای حالت پخش زنده مناسب است. قاب‌های زنده دوربین‌های iOS به‌صورت ناهمزمان در قالب CMSampleBuffer توسط iOS AVCaptureVideoDataOutput ارائه می‌شوند.

سویفت

// Obtain a CMSampleBuffer.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the default
// orientation `UIImage.Orientation.up`.
let image = try MPImage(sampleBuffer: sampleBuffer)
    

هدف-C

// Obtain a `CMSampleBuffer`.

// Convert the `CMSampleBuffer` object to a MediaPipe's Image object having the
// default orientation `UIImageOrientationUp`.
MPImage *image = [[MPPImage alloc] initWithSampleBuffer:sampleBuffer error:nil];
    

برای اطلاعات بیشتر در مورد CMSampleBuffer ، به مستندات توسعه دهنده Apple CMSampleBuffer مراجعه کنید.

وظیفه را اجرا کنید

برای اجرای Image Segmenter، از متد segment() مخصوص حالت اجرای اختصاص داده شده استفاده کنید:

  • تصویر ثابت: segment(image:)
  • ویدیو: segment(videoFrame:timestampInMilliseconds:)
  • پخش زنده: segmentAsync(image:timestampInMilliseconds:)

نمونه کد زیر نمونه های ساده ای از نحوه اجرای Image Segmenter در این حالت های مختلف اجرا را نشان می دهد:

سویفت

تصویر

let result = try imageSegmenter.segment(image: image)
    

ویدئو

let result = try imageSegmenter.segment(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

پخش زنده

try imageSegmenter.segmentAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

هدف-C

تصویر

MPPImageSegmenterResult *result =
  [imageSegmenter segmentImage:image error:nil];
    

ویدئو

MPPImageSegmenterResult *result =
  [imageSegmenter segmentVideoFrame:image
            timestampInMilliseconds:timestamp
                              error:nil];
    

پخش زنده

BOOL success =
  [imageSegmenter segmentAsyncImage:image
            timestampInMilliseconds:timestamp
                              error:nil];
    

مثال کد Image Segmenter پیاده سازی هر یک از این حالت ها را با جزئیات بیشتر segment(image:) ، segment(videoFrame:timestampInMilliseconds:) و segmentAsync(image:timestampInMilliseconds:) نشان می دهد.

به موارد زیر توجه کنید:

  • هنگام اجرا در حالت ویدیو یا حالت پخش زنده، باید مُهر زمانی فریم ورودی را نیز به وظیفه Image Segmenter ارائه دهید.

  • وقتی در حالت تصویر یا ویدیو اجرا می شود، وظیفه Image Segmenter رشته فعلی را مسدود می کند تا زمانی که پردازش تصویر یا فریم ورودی به پایان برسد. برای جلوگیری از مسدود کردن رشته فعلی، پردازش را در یک رشته پس‌زمینه با استفاده از چارچوب‌های iOS Dispatch یا NSOperation انجام دهید.

  • هنگامی که در حالت پخش زنده اجرا می شود، وظیفه Image Segmenter بلافاصله برمی گردد و رشته فعلی را مسدود نمی کند. پس از پردازش هر فریم ورودی، متد imageSegmenter(_:didFinishSegmentation:timestampInMilliseconds:error:) را با قطعه‌ساز تصویر فراخوانی می‌کند. Image Segmenter این روش را به صورت ناهمزمان در یک صف پخش سریال اختصاصی فراخوانی می کند. برای نمایش نتایج در رابط کاربری، پس از پردازش نتایج، نتایج را به صف اصلی ارسال کنید. اگر زمانی که وظیفه Image Segmenter مشغول پردازش فریم دیگری است، تابع segmentAsync فراخوانی شود، Image Segmenter قاب ورودی جدید را نادیده می گیرد.

کنترل و نمایش نتایج

پس از اجرای استنتاج، وظیفه Image Segmenter یک شی ImageSegmenterResult را برمی گرداند که حاوی نتایج کار تقسیم بندی است. محتوای خروجی به نوع خروجی بستگی دارد که هنگام پیکربندی کار تنظیم کرده اید.

تصاویر زیر تصویری از خروجی کار را برای ماسک مقدار دسته نشان می دهد. محدوده ماسک دسته [0, 255] است و هر مقدار پیکسل نشان دهنده شاخص دسته برنده خروجی مدل است. شاخص دسته برنده بالاترین امتیاز را در بین دسته هایی دارد که مدل می تواند تشخیص دهد.

خروجی ماسک تصویر اصلی و دسته. تصویر منبع از مجموعه داده پاسکال VOC 2012 .

کد نمونه Image Segmenter نحوه نمایش نتایج Image Segmenter را نشان می دهد، برای جزئیات به مثال کد مراجعه کنید.