iOS-এ একটি কাস্টম মডেল সহ চিত্রগুলিকে লেবেল করুন৷

আপনি একটি ছবির মধ্যে থাকা সত্তাগুলো শনাক্ত করতে এবং সেগুলোকে লেবেল করতে এমএল কিট (ML Kit) ব্যবহার করতে পারেন। এই এপিআই (API) বিভিন্ন ধরনের কাস্টম ইমেজ ক্লাসিফিকেশন মডেল সমর্থন করে। মডেলের সামঞ্জস্যতার প্রয়োজনীয়তা, প্রি-ট্রেইনড মডেল কোথায় পাবেন এবং কীভাবে আপনার নিজের মডেলকে ট্রেইন করবেন, সে সম্পর্কে নির্দেশনার জন্য ‘এমএল কিট-এর সাথে কাস্টম মডেল’ (Custom models with ML Kit) অংশটি দেখুন।

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

বান্ডেল মডেল হোস্টেড মডেল
মডেলটি আপনার অ্যাপের APK-এর একটি অংশ, যা এর আকার বাড়িয়ে দেয়। মডেলটি আপনার APK-এর অংশ নয়। এটি ক্লাউড স্টোরেজে আপলোড করে হোস্ট করা হয়। আমরা Firebase-এর জন্য ক্লাউড স্টোরেজ ব্যবহার করার পরামর্শ দিই।
অ্যান্ড্রয়েড ডিভাইসটি অফলাইনে থাকলেও মডেলটি তাৎক্ষণিকভাবে পাওয়া যায়। আপনার অ্যাপে চাহিদা অনুযায়ী মডেল ডাউনলোড করার কোড অবশ্যই অন্তর্ভুক্ত থাকতে হবে।
ফায়ারবেস প্রজেক্টের প্রয়োজন নেই একটি Firebase প্রজেক্ট প্রয়োজন (যদি Cloud Storage for Firebase ব্যবহার করা হয়)।
মডেলটি আপডেট করতে আপনাকে অবশ্যই আপনার অ্যাপটি পুনরায় প্রকাশ করতে হবে। আপনার অ্যাপ পুনরায় প্রকাশ না করেই মডেল আপডেটগুলি পাঠান।
অন্তর্নির্মিত A/B টেস্টিং নেই ফায়ারবেস রিমোট কনফিগ ব্যবহার করে এ/বি টেস্টিং

চেষ্টা করে দেখুন

শুরু করার আগে

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

    pod 'GoogleMLKit/ImageLabelingCustom', '8.0.0'
    
  2. আপনার প্রোজেক্টের পডগুলো ইনস্টল বা আপডেট করার পর, সেটির .xcworkspace ব্যবহার করে আপনার Xcode প্রোজেক্টটি খুলুন। ML Kit, Xcode ভার্সন 13.2.1 বা তার উচ্চতর সংস্করণে সমর্থিত।

  3. আপনি যদি ক্লাউড স্টোরেজ ফর ফায়ারবেস ব্যবহার করে কোনো মডেল ডাউনলোড করতে চান , তাহলে আপনার iOS প্রজেক্টে ফায়ারবেস যোগ করে নিন , যদি আগে থেকে তা করা না থাকে। মডেলটি বান্ডল করার সময় এটি করার প্রয়োজন নেই।

১. মডেলটি লোড করুন

একটি স্থানীয় মডেল উৎস কনফিগার করুন

আপনার অ্যাপের সাথে মডেলটি বান্ডল করতে:

  1. মডেল ফাইলটি (সাধারণত .tflite বা .lite এক্সটেনশনযুক্ত) আপনার Xcode প্রজেক্টে কপি করুন এবং কপি করার সময় Copy bundle resources অপশনটি নির্বাচন করতে ভুলবেন না। মডেল ফাইলটি অ্যাপ বান্ডেলে অন্তর্ভুক্ত হবে এবং ML Kit-এর জন্য উপলব্ধ থাকবে।

  2. মডেল ফাইলের পাথ উল্লেখ করে LocalModel অবজেক্ট তৈরি করুন:

    সুইফট

    let localModel = LocalModel(path: localModelFilePath)

    উদ্দেশ্য-সি

    MLKLocalModel *localModel =
        [[MLKLocalModel alloc] initWithPath:localModelFilePath];

দূরবর্তীভাবে হোস্ট করা মডেল উৎস কনফিগার করুন

রিমোটলি-হোস্টেড মডেল ব্যবহার করার জন্য, আপনাকে অবশ্যই আপনার নিজস্ব অ্যাপ লজিক ব্যবহার করে মডেল ফাইলটি ডিভাইসের লোকাল স্টোরেজে ডাউনলোড করতে হবে এবং তারপরে এটিকে একটি লোকাল মডেল হিসাবে লোড করতে হবে। আমরা একটি মডেল হোস্ট করার জন্য ক্লাউড স্টোরেজ ফর ফায়ারবেস (Cloud Storage for Firebase) ব্যবহার করার পরামর্শ দিই। বাস্তবায়নের বিস্তারিত তথ্যের জন্য, ফায়ারবেস এমএল টু ক্লাউড স্টোরেজ মাইগ্রেশন গাইড (Firebase ML to Cloud Storage migration guide ) দেখুন।

ইমেজ লেবেলার কনফিগার করুন

আপনার মডেল সোর্সগুলো কনফিগার করার পর, সেগুলোর যেকোনো একটি থেকে একটি ImageLabeler অবজেক্ট তৈরি করুন।

নিম্নলিখিত বিকল্পগুলি উপলব্ধ আছে:

বিকল্প
confidenceThreshold

শনাক্তকৃত লেবেলগুলির সর্বনিম্ন কনফিডেন্স স্কোর। যদি এটি সেট করা না থাকে, তাহলে মডেলের মেটাডেটা দ্বারা নির্দিষ্ট করা যেকোনো ক্লাসিফায়ার থ্রেশহোল্ড ব্যবহার করা হবে। যদি মডেলে কোনো মেটাডেটা না থাকে অথবা মেটাডেটাতে কোনো ক্লাসিফায়ার থ্রেশহোল্ড নির্দিষ্ট করা না থাকে, তাহলে ০.০-এর একটি ডিফল্ট থ্রেশহোল্ড ব্যবহার করা হবে।

maxResultCount

ফেরত দেওয়ার জন্য লেবেলের সর্বোচ্চ সংখ্যা। যদি সেট করা না থাকে, তাহলে ডিফল্ট মান ১০ ব্যবহার করা হবে।

আপনার কাছে যদি শুধুমাত্র একটি লোকালি-বান্ডেলড মডেল থাকে, তাহলে আপনার LocalModel অবজেক্ট থেকে একটি লেবেলার তৈরি করুন:

সুইফট

let options = CustomImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0)
let imageLabeler = ImageLabeler.imageLabeler(options: options)

উদ্দেশ্য-সি

MLKCustomImageLabelerOptions *options =
    [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = @(0.0);
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

আপনার মডেলটি যদি দূরবর্তী স্থানে হোস্ট করা থাকে, তবে সেটি চালানোর আগে আপনাকে যাচাই করে নিতে হবে যে সেটি ডাউনলোড হয়েছে কি না।

যদিও লেবেলার চালানোর আগে আপনাকে কেবল এটি নিশ্চিত করতে হবে, আপনার কাছে যদি একটি রিমোটলি-হোস্টেড মডেল এবং একটি লোকালি-বান্ডেলড মডেল উভয়ই থাকে, তবে ImageLabeler ইনস্ট্যানশিয়েট করার সময় এই চেকটি করে নেওয়া যুক্তিযুক্ত হতে পারে: যদি রিমোট মডেলটি ডাউনলোড করা হয়ে থাকে তবে সেখান থেকে লেবেলার তৈরি করুন, এবং অন্যথায় লোকাল মডেল থেকে তৈরি করুন।

সুইফট

// Path where your download logic saves the model
let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let localModelURL = documentDirectory.appendingPathComponent("my_remote_model.tflite")

let model: LocalModel
if FileManager.default.fileExists(atPath: localModelURL.path) {
  // Use the downloaded model
  model = LocalModel(path: localModelURL.path)
} else {
  // Fall back to bundled model
  guard let bundledModelPath = Bundle.main.path(forResource: "model", ofType: "tflite") else { return }
  model = LocalModel(path: bundledModelPath)
}

let options = CustomImageLabelerOptions(localModel: model)
let imageLabeler = ImageLabeler.imageLabeler(options: options)

উদ্দেশ্য-সি

NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *localModelPath = [documentsDirectory stringByAppendingPathComponent:@"my_remote_model.tflite"];

MLKLocalModel *model;
if ([NSFileManager.defaultManager fileExistsAtPath:localModelPath]) {
  // Use the downloaded model
  model = [[MLKLocalModel alloc] initWithPath:localModelPath];
} else {
  // Fall back to bundled model
  NSString *bundledModelPath = [NSBundle.mainBundle pathForResource:@"model" ofType:@"tflite"];
  model = [[MLKLocalModel alloc] initWithPath:bundledModelPath];
}

MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:model];
MLKImageLabeler *imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];

আপনার কাছে যদি শুধুমাত্র দূরবর্তী স্থানে হোস্ট করা কোনো মডেল থাকে, তাহলে মডেলটি ডাউনলোড হয়েছে কিনা তা নিশ্চিত না হওয়া পর্যন্ত মডেল-সম্পর্কিত কার্যকারিতা নিষ্ক্রিয় করে রাখা উচিত—যেমন, আপনার UI-এর কোনো অংশ ধূসর করে দেওয়া বা লুকিয়ে রাখা।

সুইফট

let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let localModelURL = documentDirectory.appendingPathComponent("my_remote_model.tflite")
if FileManager.default.fileExists(atPath: localModelURL.path) {
  // Model is already cached, initialize immediately
  self.initializeLabeler(with: localModelURL)
} else {
  // Model is not yet available, show loading UI and start download
  self.showLoadingUI()
  let storage = Storage.storage()
  let modelRef = storage.reference(forURL: "gs://YOUR_BUCKET/path/to/model.tflite")
  modelRef.write(toFile: localModelURL) { url, error in
    self.hideLoadingUI()
    if let error = error {
      // Handle download error
      self.showErrorUI()
    } else if let modelURL = url {
      // Download success, initialize labeler
      self.initializeLabeler(with: modelURL)
    }
  }
}

func initializeLabeler(with modelURL: URL) {
  let localModel = LocalModel(path: modelURL.path)
  let options = CustomImageLabelerOptions(localModel: localModel)
  self.imageLabeler = ImageLabeler.imageLabeler(options: options)
  // Enable ML-related UI features here
  self.enableMLFeatures()
}

উদ্দেশ্য-সি

NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *localModelPath = [documentsDirectory stringByAppendingPathComponent:@"my_remote_model.tflite"];
NSURL *localModelURL = [NSURL fileURLWithPath:localModelPath];

if ([NSFileManager.defaultManager fileExistsAtPath:localModelPath]) {
  // Model is already cached, initialize immediately
  [self initializeLabelerWithURL:localModelURL];
} else {
  // Model is not yet available, show loading UI and start download
  [self showLoadingUI];

  FIRStorage *storage = [FIRStorage storage];
  FIRStorageReference *modelRef = [storage referenceForURL:@"gs://YOUR_BUCKET/path/to/model.tflite"];

  [modelRef writeToFile:localModelURL
             completion:^(NSURL * _Nullable URL, NSError * _Nullable error) {
               [self hideLoadingUI];
               if (error != nil) {
                 // Handle download error
                 [self showErrorUI];
               } else {
                 // Download success, initialize labeler
                 [self initializeLabelerWithURL:URL];
               }
             }];
}

- (void)initializeLabelerWithURL:(NSURL *)modelURL {
  MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:modelURL.path];
  MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel];
  self.imageLabeler = [MLKImageLabeler imageLabelerWithOptions:options];

  // Enable ML-related UI features here
  [self enableMLFeatures];
}

২. ইনপুট চিত্রটি প্রস্তুত করুন।

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

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

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

    সুইফট

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

    উদ্দেশ্য-সি

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

    উদ্দেশ্য-সি

    - (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 অবজেক্ট তৈরি করুন:

    সুইফট

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

    উদ্দেশ্য-সি

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

৩. ইমেজ লেবেলারটি চালান।

কোনো ইমেজের অবজেক্টগুলোকে লেবেল করতে, ImageLabeler এর process() মেথডে image অবজেক্টটি পাস করুন।

অ্যাসিঙ্ক্রোনাসভাবে:

সুইফট

imageLabeler.process(image) { labels, error in
    guard error == nil, let labels = labels, !labels.isEmpty else {
        // Handle the error.
        return
    }
    // Show results.
}

উদ্দেশ্য-সি

[imageLabeler
    processImage:image
      completion:^(NSArray *_Nullable labels,
                   NSError *_Nullable error) {
        if (label.count == 0) {
            // Handle the error.
            return;
        }
        // Show results.
     }];

একই সাথে:

সুইফট

var labels: [ImageLabel]
do {
    labels = try imageLabeler.results(in: image)
} catch let error {
    // Handle the error.
    return
}
// Show results.

উদ্দেশ্য-সি

NSError *error;
NSArray *labels =
    [imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.

৪. লেবেলযুক্ত সত্তাগুলো সম্পর্কে তথ্য সংগ্রহ করুন।

ইমেজ লেবেলিং অপারেশন সফল হলে, এটি ImageLabel এর একটি অ্যারে রিটার্ন করে। প্রতিটি ImageLabel ইমেজের লেবেল করা কোনো একটি বিষয়কে উপস্থাপন করে। আপনি প্রতিটি লেবেলের টেক্সট বিবরণ (যদি LiteRT মডেল ফাইলের মেটাডেটাতে উপলব্ধ থাকে), কনফিডেন্স স্কোর এবং ইনডেক্স পেতে পারেন। উদাহরণস্বরূপ:

সুইফট

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

উদ্দেশ্য-সি

for (MLKImageLabel *label in labels) {
  NSString *labelText = label.text;
  float confidence = label.confidence;
  NSInteger index = label.index;
}

রিয়েল-টাইম পারফরম্যান্স উন্নত করার টিপস

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

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