راهنمای جاسازی تصویر برای iOS

وظیفه MediaPipe Image Embedder به شما امکان می دهد داده های تصویر را به یک نمایش عددی تبدیل کنید تا وظایف پردازش تصویر مربوط به ML را انجام دهید، مانند مقایسه شباهت دو تصویر.

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

نمونه کد

کد مثال MediaPipe Tasks یک پیاده سازی اساسی از یک برنامه Image Embedder برای iOS است. این مثال از دوربین یک دستگاه فیزیکی iOS برای جاسازی مداوم تصاویر استفاده می کند و همچنین می تواند جاسازی را روی فایل های تصویری از گالری دستگاه اجرا کند.

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

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

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

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

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

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

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

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

اجزای کلیدی

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

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

راه اندازی

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

وابستگی ها

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

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

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

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

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

مدل

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

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

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

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

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

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

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

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

سویفت

تصویر

import MediaPipeTasksVision

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

let options = ImageEmbedderOptions()
options.baseOptions.modelAssetPath = modelPath
options.quantize = true
options.l2Normalize = true

let imageEmbedder = try ImageEmbedder(options: options)
    

ویدئو

import MediaPipeTasksVision

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

let options = ImageEmbedderOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .video
options.quantize = true
options.l2Normalize = true

let imageEmbedder = try ImageEmbedder(options: options)
    

پخش زنده

import MediaPipeTasksVision

// Class that conforms to the `ImageEmbedderLiveStreamDelegate` protocol and
// implements the method that the image embedder calls once it finishes
// embedding each input frame.
class ImageEmbedderResultProcessor: NSObject, ImageEmbedderLiveStreamDelegate {

  func imageEmbedder(
    _ imageEmbedder: ImageEmbedder,
    didFinishEmbedding result: ImageEmbedderResult?,
    timestampInMilliseconds: Int,
    error: Error?) {

    // Process the image embedder result or errors here.

  }
}

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

let options = ImageEmbedderOptions()
options.baseOptions.modelAssetPath = modelPath
options.runningMode = .liveStream
options.quantize = true
options.l2Normalize = true

// Assign an object of the class to the `imageEmbedderLiveStreamDelegate`
// property.
let processor = ImageEmbedderResultProcessor()
options.imageEmbedderLiveStreamDelegate = processor

let imageEmbedder = try ImageEmbedder(options: options)
    

هدف-C

تصویر

@import MediaPipeTasksVision;

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

MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeImage;
options.quantize = YES;
options.l2Normalize = YES;

MPPImageEmbedder *imageEmbedder =
  [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
    

ویدئو

@import MediaPipeTasksVision;

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

MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeVideo;
options.quantize = YES;
options.l2Normalize = YES;

MPPImageEmbedder *imageEmbedder =
  [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
    

پخش زنده

@import MediaPipeTasksVision;

// Class that conforms to the `MPPImageEmbedderLiveStreamDelegate` protocol
// and implements the method that the image embedder calls once it finishes
// embedding each input frame.
@interface APPImageEmbedderResultProcessor : NSObject 

@end

@implementation APPImageEmbedderResultProcessor

-   (void)imageEmbedder:(MPPImageEmbedder *)imageEmbedder
    didFinishEmbeddingWithResult:(MPPImageEmbedderResult *)imageEmbedderResult
         timestampInMilliseconds:(NSInteger)timestampInMilliseconds
                           error:(NSError *)error {

    // Process the image embedder result or errors here.

}

@end

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

MPPImageEmbedderOptions *options = [[MPPImageEmbedderOptions alloc] init];
options.baseOptions.modelAssetPath = modelPath;
options.runningMode = MPPRunningModeLiveStream;
options.quantize = YES;
options.l2Normalize = YES;

// Assign an object of the class to the `imageEmbedderLiveStreamDelegate`
// property.
APPImageEmbedderResultProcessor *processor =
  [APPImageEmbedderResultProcessor new];
options.imageEmbedderLiveStreamDelegate = processor;

MPPImageEmbedder *imageEmbedder =
  [[MPPImageEmbedder alloc] initWithOptions:options error:nil];
    

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

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

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

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

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

LIVE_STREAM: حالت پخش زنده داده های ورودی، مانند دوربین. در این حالت، imageEmbedderLiveStreamDelegate باید روی نمونه ای از کلاسی تنظیم شود که ImageEmbedderLiveStreamDelegate را برای دریافت نتایج تعبیه فریم های تصویر به صورت ناهمزمان اجرا می کند.
{RunningMode.image، RunningMode.video، RunningMode.liveStream} {RunningMode.image}
l2Normalize آیا باید بردار ویژگی بازگشتی را با نرمال L2 عادی سازی کرد. فقط در صورتی از این گزینه استفاده کنید که مدل از قبل دارای یک L2_NORMALIZATION TFLite Op بومی نباشد. در بیشتر موارد، این قبلاً وجود دارد و بنابراین عادی سازی L2 از طریق استنتاج TFLite بدون نیاز به این گزینه حاصل می شود. بول نادرست
quantize اینکه آیا تعبیه برگشتی باید از طریق کوانتیزه کردن اسکالر به بایت تبدیل شود یا خیر. تعبیه‌ها به طور ضمنی واحد هنجار فرض می‌شوند و بنابراین هر بعد تضمین می‌شود که مقداری در [-1.0، 1.0] داشته باشد. اگر اینطور نیست از گزینه l2Normalize استفاده کنید. بول نادرست

هنگامی که حالت در حال اجرا روی پخش زنده تنظیم می شود، Image Embedder به گزینه پیکربندی imageEmbedderLiveStreamDelegate اضافی نیاز دارد، که به Image Embedder امکان می دهد نتایج جاسازی تصویر را به صورت ناهمزمان ارائه دهد. نماینده باید متد imageEmbedder(_:didFinishEmbedding:timestampInMilliseconds:error:) پیاده سازی کند، که Image Embedder پس از پردازش نتایج جاسازی هر فریم تصویر ورودی، آن را فراخوانی می کند.

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

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

شما باید تصویر یا فریم ورودی را قبل از ارسال آن به Image Embedder به یک شی 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 Embedder از جهت گیری های آینه شده مانند .upMirrored ، .downMirrored ، .leftMirrored ، .rightMirrored پشتیبانی نمی کند.

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

CVPixelBuffer

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

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

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

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

  • پخش زنده: برنامه هایی که از دوربین iOS برای تولید فریم استفاده می کنند ممکن است قبل از ارسال به Image Embedder در حالت پخش زنده به فرمت 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 ، به مستندات توسعه دهنده Apple 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 Embedder، از متد embed() مخصوص حالت اجرای اختصاص داده شده استفاده کنید:

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

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

سویفت

تصویر

let result = try imageEmbedder.embed(image: image)
    

ویدئو

let result = try imageEmbedder.embed(
  videoFrame: image,
  timestampInMilliseconds: timestamp)
    

پخش زنده

try imageEmbedder.embedAsync(
  image: image,
  timestampInMilliseconds: timestamp)
    

هدف-C

تصویر

MPPImageEmbedderResult *result =
  [imageEmbedder embedImage:image error:nil];
    

ویدئو

MPPImageEmbedderResult *result =
  [imageEmbedder embedVideoFrame:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

پخش زنده

BOOL success =
  [imageEmbedder embedAsyncImage:image
           timestampInMilliseconds:timestamp
                             error:nil];
    

مثال کد Image Embedder اجرای هر یک از این حالت‌ها را با جزئیات بیشتری نشان می‌دهد embed(image:) , embed(videoFrame:timestampInMilliseconds:) و embedAsync(image:timestampInMilliseconds:) . کد مثال به کاربر اجازه می دهد تا بین حالت های پردازشی که ممکن است برای مورد استفاده شما مورد نیاز نباشد جابجا شود.

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

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

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

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

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

پس از اجرای استنتاج، Image Embedder یک شی ImageEmbedderResult را برمی‌گرداند که حاوی فهرستی از جاسازی‌ها (اعم از ممیز شناور یا اسکالر کوانتیزه) برای تصویر ورودی است.

شکل زیر نمونه ای از داده های خروجی از این کار را نشان می دهد:

ImageEmbedderResult:
  Embedding #0 (sole embedding head):
    float_embedding: {0.0, 0.0, ..., 0.0, 1.0, 0.0, 0.0, 2.0}
    head_index: 0

این نتیجه با قرار دادن تصویر زیر به دست آمد:

می توانید شباهت دو جاسازی را با استفاده از تابع ImageEmbedder.cosineSimilarity مقایسه کنید.

سویفت

let similarity = try ImageEmbedder.cosineSimilarity(
  embedding1: result.embeddingResult.embeddings[0],
  embedding2: otherResult.embeddingResult.embeddings[0])
    

هدف-C

NSNumber *similarity = [MPPImageEmbedder
      cosineSimilarityBetweenEmbedding1:result.embeddingResult.embeddings[0]
                          andEmbedding2:otherResult.embeddingResult.embeddings[0]
                                  error:nil];