iOS-এ ML Kit-এর মাধ্যমে সেলফি সেগমেন্টেশন

ML Kit সেলফি সেগমেন্টেশনের জন্য অপ্টিমাইজ করা SDK প্রদান করে। বিল্ড করার সময় সেলফি সেগমেন্টার অ্যাসেট আপনার অ্যাপের সাথে স্ট্যাটিক লিঙ্ক করা হয়। এর ফলে আপনার অ্যাপের সাইজ সর্বাধিক ২৪ এমবি বাড়বে এবং iPhone X-এ পরিমাপ করা ইনপুট ছবির সাইজের উপর নির্ভর করে API লেটেন্সি ~৭ms থেকে ~১২ms পর্যন্ত হতে পারে।

এটি ব্যবহার করে দেখুন

শুরু করার আগে

  1. আপনার Podfile-এ নিম্নলিখিত ML Kit লাইব্রেরি অন্তর্ভুক্ত করুন:

    pod 'GoogleMLKit/SegmentationSelfie', '8.0.0'
    
  2. আপনার প্রোজেক্টের Pod ইনস্টল বা আপডেট করার পরে, এর .xcworkspace ব্যবহার করে আপনার Xcode প্রোজেক্ট খুলুন। ML Kit Xcode ভার্সন 13.2.1 বা তার পরবর্তী যেকোনও ভার্সনে কাজ করে।

১. Segmenter-এর একটি ইনস্ট্যান্স তৈরি করুন

সেলফি ছবিতে সেগমেন্টেশন পারফর্ম করতে, প্রথমে Segmenter-এর একটি ইনস্ট্যান্স তৈরি করুন SelfieSegmenterOptions এবং ঐচ্ছিকভাবে সেগমেন্টেশন সেটিংস নির্দিষ্ট করুন।

সেগমেন্টার বিকল্প

সেগমেন্টার মোড

Segmenter দুটি মোডে কাজ করে। আপনার ব্যবহারের ক্ষেত্রে যেটি প্রযোজ্য সেটিই বেছে নিয়েছেন কিনা তা নিশ্চিত করুন।

STREAM_MODE (default)

ভিডিও বা ক্যামেরা থেকে ফ্রেম স্ট্রিম করার জন্য এই মোড ডিজাইন করা হয়েছে। এই মোডে, আরও মসৃণ সেগমেন্টেশন ফলাফল পেতে সেগমেন্টার আগের ফ্রেমের ফলাফল ব্যবহার করবে।

SINGLE_IMAGE_MODE (default)

এই মোডটি এমন সিঙ্গেল ছবির জন্য ডিজাইন করা হয়েছে যেগুলি একে অপরের সাথে সম্পর্কিত নয়। এই মোডে, সেগমেন্টার প্রতিটি ছবি আলাদাভাবে প্রসেস করবে, ফ্রেমের উপর কোনও স্মুথিং প্রয়োগ করা হবে না।

র সাইজ মাস্ক চালু করা

মডেল আউটপুট সাইজের সাথে ম্যাচ করে এমন র সাইজ মাস্ক রিটার্ন করার জন্য সেগমেন্টারকে বলে।

কাঁচা মাস্কের সাইজ (যেমন, ২৫৬x২৫৬) সাধারণত ইনপুট ছবির সাইজের চেয়ে ছোট হয়।

এই বিকল্প উল্লেখ না করলে, ইনপুট ছবির সাইজের সাথে ম্যাচ করাতে সেগমেন্টার, র মাস্কের সাইজ পরিবর্তন করবে। আপনি যদি কাস্টমাইজ করা রিস্কেল করার লজিক প্রয়োগ করতে চান অথবা আপনার ব্যবহারের ক্ষেত্রে রিস্কেল করার প্রয়োজন না হয়, তাহলে এই বিকল্প ব্যবহার করার কথা বিবেচনা করুন।

সেগমেন্টার বিকল্প নির্দিষ্ট করুন:

Swift

let options = SelfieSegmenterOptions()
options.segmenterMode = .singleImage
options.shouldEnableRawSizeMask = true

Objective-C

MLKSelfieSegmenterOptions *options = [[MLKSelfieSegmenterOptions alloc] init];
options.segmenterMode = MLKSegmenterModeSingleImage;
options.shouldEnableRawSizeMask = YES;

সবশেষে, Segmenter-এর একটি ইনস্ট্যান্স পান। আপনার উল্লেখ করা বিকল্পগুলি পাস করুন:

Swift

let segmenter = Segmenter.segmenter(options: options)

Objective-C

MLKSegmenter *segmenter = [MLKSegmenter segmenterWithOptions:options];

২. ইনপুট ছবি প্রস্তুত করুন

সেলফি সেগমেন্ট করতে, ভিডিওর প্রতিটি ছবি বা ফ্রেমের জন্য নিম্নলিখিত কাজগুলি করুন। আপনি স্ট্রিম মোড চালু করলে, আপনাকে অবশ্যই CMSampleBuffer থেকে VisionImage অবজেক্ট তৈরি করতে হবে।

UIImage বা CMSampleBuffer ব্যবহার করে VisionImage অবজেক্ট তৈরি করুন।

আপনি UIImage ব্যবহার করলে, এইসব ধাপ অনুসরণ করুন:

  • UIImage-এর সাহায্যে VisionImage অবজেক্ট তৈরি করুন। সঠিক .orientation উল্লেখ করতে ভুলবেন না।

    Swift

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

    Objective-C

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

আপনি CMSampleBuffer ব্যবহার করলে, এইসব ধাপ অনুসরণ করুন:

  • CMSampleBuffer-এ থাকা ইমেজ ডেটার ওরিয়েন্টেশন নির্দিষ্ট করুন।

    ছবির ওরিয়েন্টেশন পেতে:

    Swift

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

    Objective-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;
      }
    }
          
  • CMSampleBuffer অবজেক্ট ও ওরিয়েন্টেশন ব্যবহার করে VisionImage অবজেক্ট তৈরি করুন:

    Swift

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

    Objective-C

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

৩. ছবি প্রসেস করুন

VisionImage অবজেক্টটি Segmenter-এর ইমেজ প্রসেসিং পদ্ধতির একটিতে পাস করুন। আপনি অ্যাসিঙ্ক্রোনাস process(image:) পদ্ধতি বা সিঙ্ক্রোনাস results(in:) পদ্ধতি ব্যবহার করতে পারেন।

সেলফি ছবিতে সিঙ্ক্রোনাসভাবে সেগমেন্টেশন করতে:

Swift

var mask: [SegmentationMask]
do {
  mask = try segmenter.results(in: image)
} catch let error {
  print("Failed to perform segmentation with error: \(error.localizedDescription).")
  return
}

// Success. Get a segmentation mask here.

Objective-C

NSError *error;
MLKSegmentationMask *mask =
    [segmenter resultsInImage:image error:&error];
if (error != nil) {
  // Error.
  return;
}

// Success. Get a segmentation mask here.

সেলফি ইমেজে অ্যাসিঙ্ক্রোনাস সেগমেন্টেশন পারফর্ম করতে:

Swift

segmenter.process(image) { mask, error in
  guard error == nil else {
    // Error.
    return
  }
  // Success. Get a segmentation mask here.

Objective-C

[segmenter processImage:image
             completion:^(MLKSegmentationMask * _Nullable mask,
                          NSError * _Nullable error) {
               if (error != nil) {
                 // Error.
                 return;
               }
               // Success. Get a segmentation mask here.
             }];

৪. সেগমেন্টেশন মাস্ক পাওয়া

আপনি নিম্নলিখিতভাবে সেগমেন্টেশন ফলাফল পেতে পারেন:

Swift

let maskWidth = CVPixelBufferGetWidth(mask.buffer)
let maskHeight = CVPixelBufferGetHeight(mask.buffer)

CVPixelBufferLockBaseAddress(mask.buffer, CVPixelBufferLockFlags.readOnly)
let maskBytesPerRow = CVPixelBufferGetBytesPerRow(mask.buffer)
var maskAddress =
    CVPixelBufferGetBaseAddress(mask.buffer)!.bindMemory(
        to: Float32.self, capacity: maskBytesPerRow * maskHeight)

for _ in 0...(maskHeight - 1) {
  for col in 0...(maskWidth - 1) {
    // Gets the confidence of the pixel in the mask being in the foreground.
    let foregroundConfidence: Float32 = maskAddress[col]
  }
  maskAddress += maskBytesPerRow / MemoryLayout<Float32>.size
}

Objective-C

size_t width = CVPixelBufferGetWidth(mask.buffer);
size_t height = CVPixelBufferGetHeight(mask.buffer);

CVPixelBufferLockBaseAddress(mask.buffer, kCVPixelBufferLock_ReadOnly);
size_t maskBytesPerRow = CVPixelBufferGetBytesPerRow(mask.buffer);
float *maskAddress = (float *)CVPixelBufferGetBaseAddress(mask.buffer);

for (int row = 0; row < height; ++row) {
  for (int col = 0; col < width; ++col) {
    // Gets the confidence of the pixel in the mask being in the foreground.
    float foregroundConfidence = maskAddress[col];
  }
  maskAddress += maskBytesPerRow / sizeof(float);
}

সেগমেন্টেশন ফলাফল কীভাবে ব্যবহার করতে হয় তার সম্পূর্ণ উদাহরণ দেখতে, ML Kit ক্যুইকস্টার্ট স্যাম্পেল দেখুন।

পারফর্ম্যান্স উন্নত করার ব্যাপারে পরামর্শ

আপনার ফলাফলের কোয়ালিটি ইনপুট ছবির কোয়ালিটির উপর নির্ভর করে:

  • ML Kit-এর মাধ্যমে সঠিক সেগমেন্টেশন ফলাফল পেতে, ছবির সাইজ অন্তত ২৫৬x২৫৬ পিক্সেল হতে হবে।
  • আপনি যদি রিয়েল-টাইম অ্যাপ্লিকেশনে সেলফি সেগমেন্টেশন করেন, তাহলে আপনি ইনপুট ছবির সামগ্রিক ডাইমেনশনও বিবেচনা করতে চাইতে পারেন। ছোট ছবি দ্রুত প্রসেস করা যায়, তাই লেটেন্সি কমাতে, কম রেজোলিউশনে ছবি ক্যাপচার করুন, তবে উপরে উল্লেখ করা রেজোলিউশন সংক্রান্ত প্রয়োজনীয়তা মনে রাখবেন এবং নিশ্চিত করুন যে সাবজেক্টটি যতটা সম্ভব ছবির জায়গা জুড়ে আছে।
  • ছবির ফোকাস ভাল না হলে, তার প্রভাব নির্ভুলতার উপরেও পড়তে পারে। আপনি গ্রহণযোগ্য ফলাফল না পেলে, ব্যবহারকারীকে ছবিটি আবার তোলার জন্য বলুন।

আপনি যদি রিয়েল-টাইম অ্যাপ্লিকেশনে সেগমেন্টেশন ব্যবহার করতে চান, তাহলে সেরা ফ্রেম রেট পেতে এইসব নির্দেশিকা অনুসরণ করুন:

  • stream সেগমেন্টার মোড ব্যবহার করুন।
  • কম রেজোলিউশনে ছবি তোলার কথা বিবেচনা করুন। তবে, এই API-এর ছবির ডাইমেনশন সংক্রান্ত প্রয়োজনীয়তাও মনে রাখবেন।
  • ভিডিও ফ্রেম প্রসেস করার জন্য, সেগমেন্টারের results(in:) সিঙ্ক্রোনাস API ব্যবহার করুন। প্রদত্ত ভিডিও ফ্রেম থেকে সিঙ্ক্রোনাসভাবে ফলাফল পেতে AVCaptureVideoDataOutputSampleBufferDelegate-এর captureOutput(_, didOutput:from:) ফাংশন থেকে এই পদ্ধতি কল করুন। সেগমেন্টারকে কল থ্রটল করতে AVCaptureVideoDataOutput-এর alwaysDiscardsLateVideoFrames-কে true হিসেবে রাখুন। সেগমেন্টার চলাকালীন কোনও নতুন ভিডিও ফ্রেম উপলভ্য হলে, সেটি বাদ দেওয়া হবে।
  • ইনপুট ইমেজে গ্রাফিক্স ওভারলে করার জন্য সেগমেন্টারের আউটপুট ব্যবহার করলে, প্রথমে ML Kit থেকে ফলাফল পান, তারপর ইমেজ রেন্ডার করুন এবং একটি ধাপে ওভারলে করুন। এটি করার মাধ্যমে, প্রসেস করা প্রতিটি ইনপুট ফ্রেমের জন্য আপনি ডিসপ্লে সারফেসে শুধুমাত্র একবারই রেন্ডার করেন। উদাহরণ হিসেবে ML Kit কুইকস্টার্ট স্যাম্পেলে previewOverlayView ও CameraViewController ক্লাস দেখুন।