iOS-এ ML Kit-এর মাধ্যমে বারকোড স্ক্যান করা

বারকোড শনাক্ত ও ডিকোড করার জন্য আপনি ML Kit ব্যবহার করতে পারবেন।

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

শুরু করার আগে

  1. আপনার Podfile-এ নিম্নলিখিত ML Kit পড অন্তর্ভুক্ত করুন:
    pod 'GoogleMLKit/BarcodeScanning', '8.0.0'
    
  2. আপনার প্রোজেক্টের Pods ইনস্টল বা আপডেট করার পরে, .xcworkspace ব্যবহার করে আপনার Xcode প্রোজেক্ট খুলুন। Xcode ভার্সন 12.4 বা তার পরের যেকোনও ভার্সনে ML Kit কাজ করে।

ইনপুট ছবি সংক্রান্ত নির্দেশিকা

  • ML Kit-এর মাধ্যমে বারকোড সঠিকভাবে রিড করার জন্য, ইনপুট ছবিতে পর্যাপ্ত পিক্সেল ডেটা দ্বারা উপস্থাপিত বারকোড থাকতে হবে।

    নির্দিষ্ট পিক্সেল ডেটা সংক্রান্ত প্রয়োজনীয়তা বারকোডের ধরন এবং সেটিতে এনকোড করা ডেটার পরিমাণের উপর নির্ভর করে, কারণ অনেক বারকোড পরিবর্তনযোগ্য সাইজের পে-লোড সাপোর্ট করে। সাধারণত, বারকোডের সবচেয়ে ছোট অর্থপূর্ণ ইউনিট কমপক্ষে ২ পিক্সেল চওড়া এবং ২-ডাইমেনশনাল কোডের ক্ষেত্রে ২ পিক্সেল লম্বা হতে হবে।

    যেমন, EAN-13 বারকোড, ১, ২, ৩ বা ৪ ইউনিট চওড়া বার ও স্পেস দিয়ে তৈরি হয়, তাই EAN-13 বারকোড ইমেজে আদর্শভাবে এমন বার ও স্পেস থাকে যেগুলি কমপক্ষে ২, ৪, ৬ ও ৮ পিক্সেল চওড়া হয়। কারণ, EAN-13 বারকোড মোট ৯৫ ইউনিট চওড়া হয়, তাই বারকোডটি কমপক্ষে ১৯০ পিক্সেল চওড়া হওয়া উচিত।

    PDF417-এর মতো আরও ঘন ফর্ম্যাটের ক্ষেত্রে, ML Kit-কে সেগুলি নির্ভরযোগ্যভাবে রিড করার জন্য আরও বড় পিক্সেল ডাইমেনশন প্রয়োজন। যেমন, একটি PDF417 কোডে একটি সারিতে সর্বাধিক ৩৪টি ১৭-ইউনিট চওড়া "শব্দ" থাকতে পারে, যা আদর্শভাবে কমপক্ষে ১১৫৬ পিক্সেল চওড়া হবে।

  • ছবির ফোকাস ভাল না হলে স্ক্যানিংয়ের নির্ভুলতা প্রভাবিত হতে পারে। আপনার অ্যাপ যদি গ্রহণযোগ্য ফলাফল না পায়, তাহলে ব্যবহারকারীকে ছবিটি আবার তোলার জন্য বলুন।

  • সাধারণ অ্যাপ্লিকেশনের জন্য, আরও বেশি রেজোলিউশনের ছবি প্রদান করার সাজেশন দেওয়া হয়, যেমন ১২৮০x৭২০ বা ১৯২০x১০৮০, যা ক্যামেরা থেকে আরও বেশি দূরত্ব থেকে বারকোড স্ক্যান করার সুবিধা প্রদান করে।

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

১. বারকোড স্ক্যানার কনফিগার করা

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

যেমন, শুধুমাত্র Aztec কোড ও QR কোড স্ক্যান করতে, নিম্নলিখিত উদাহরণে দেখানো মতো একটি BarcodeScannerOptions অবজেক্ট তৈরি করুন:

Swift

let format = .all
let barcodeOptions = BarcodeScannerOptions(formats: format)
  

নিম্নলিখিত ফর্ম্যাট কাজ করে:

  • code128
  • code39
  • code93
  • codaBar
  • dataMatrix
  • EAN13
  • EAN8
  • ITF
  • qrCode
  • UPCA
  • UPCE
  • PDF417
  • aztec

Objective-C

MLKBarcodeScannerOptions *options =
  [[MLKBarcodeScannerOptions alloc]
   initWithFormats: MLKBarcodeFormatQRCode | MLKBarcodeFormatAztec];

নিম্নলিখিত ফর্ম্যাট কাজ করে:

  • Code-128 (MLKBarcodeFormatCode128)
  • Code-39 (MLKBarcodeFormatCode39)
  • Code-93 (MLKBarcodeFormatCode93)
  • Codabar (MLKBarcodeFormatCodaBar)
  • Data Matrix (MLKBarcodeFormatDataMatrix)
  • EAN-13 (MLKBarcodeFormatEAN13)
  • EAN-8 (MLKBarcodeFormatEAN8)
  • ITF (MLKBarcodeFormatITF)
  • QR কোড (MLKBarcodeFormatQRCode)
  • UPC-A (MLKBarcodeFormatUPCA)
  • UPC-E (MLKBarcodeFormatUPCE)
  • PDF-417 (MLKBarcodeFormatPDF417)
  • Aztec Code (MLKBarcodeFormatAztec)

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

কোনও ছবিতে বারকোড স্ক্যান করতে, BarcodeScanner-এর process() বা results(in:) পদ্ধতিতে UIImage বা CMSampleBufferRef হিসেবে ছবিটি পাস করুন:

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];

৩. BarcodeScanner-এর একটি ইনস্ট্যান্স পাওয়া

BarcodeScanner-এর ইনস্ট্যান্স পান:

Swift

let barcodeScanner = BarcodeScanner.barcodeScanner()
// Or, to change the default settings:
// let barcodeScanner = BarcodeScanner.barcodeScanner(options: barcodeOptions)

Objective-C

MLKBarcodeScanner *barcodeScanner = [MLKBarcodeScanner barcodeScanner];
// Or, to change the default settings:
// MLKBarcodeScanner *barcodeScanner =
//     [MLKBarcodeScanner barcodeScannerWithOptions:options];

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

তারপর, process() পদ্ধতিতে ছবিটি পাস করুন:

Swift

barcodeScanner.process(visionImage) { features, error in
  guard error == nil, let features = features, !features.isEmpty else {
    // Error handling
    return
  }
  // Recognized barcodes
}

Objective-C

[barcodeScanner processImage:image
                  completion:^(NSArray<MLKBarcode *> *_Nullable barcodes,
                               NSError *_Nullable error) {
  if (error != nil) {
    // Error handling
    return;
  }
  if (barcodes.count > 0) {
    // Recognized barcodes
  }
}];

৫. বারকোড থেকে তথ্য পাওয়া

বারকোড স্ক্যান করার অপারেশন সফল হলে, স্ক্যানার Barcode অবজেক্টের একটি অ্যারে রিটার্ন করে। প্রতিটি Barcode অবজেক্ট একটি বারকোডকে উপস্থাপন করে যা ছবিতে শনাক্ত করা হয়েছে। প্রতিটি বারকোডের জন্য, আপনি ইনপুট ছবিতে এর বাউন্ডিং কোঅর্ডিনেট এবং বারকোড দ্বারা এনকোড করা কাঁচা ডেটা পেতে পারেন। এছাড়াও, বারকোড স্ক্যানার যদি বারকোড দ্বারা এনকোড করা ডেটার ধরন নির্ধারণ করতে পারে, তাহলে আপনি পার্স করা ডেটা সহ একটি অবজেক্ট পেতে পারেন।

যেমন:

Swift

for barcode in barcodes {
  let corners = barcode.cornerPoints

  let displayValue = barcode.displayValue
  let rawValue = barcode.rawValue

  let valueType = barcode.valueType
  switch valueType {
  case .wiFi:
    let ssid = barcode.wifi?.ssid
    let password = barcode.wifi?.password
    let encryptionType = barcode.wifi?.type
  case .URL:
    let title = barcode.url!.title
    let url = barcode.url!.url
  default:
    // See API reference for all supported value types
  }
}

Objective-C

for (MLKBarcode *barcode in barcodes) {
   NSArray *corners = barcode.cornerPoints;

   NSString *displayValue = barcode.displayValue;
   NSString *rawValue = barcode.rawValue;

   MLKBarcodeValueType valueType = barcode.valueType;
   switch (valueType) {
     case MLKBarcodeValueTypeWiFi:
       ssid = barcode.wifi.ssid;
       password = barcode.wifi.password;
       encryptionType = barcode.wifi.type;
       break;
     case MLKBarcodeValueTypeURL:
       url = barcode.URL.url;
       title = barcode.URL.title;
       break;
     // ...
     default:
       break;
   }
 }

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

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

  • ক্যামেরার নেটিভ রেজোলিউশনে ইনপুট ক্যাপচার করবেন না। কিছু ডিভাইসে, নেটিভ রেজোলিউশনে ইনপুট ক্যাপচার করলে অত্যন্ত বড় (১০+ মেগাপিক্সেল) ছবি তৈরি হয়, যার ফলে নির্ভুলতার কোনও সুবিধা ছাড়াই খুব খারাপ লেটেন্সি হয়। এর পরিবর্তে, বারকোড স্ক্যান করার জন্য ক্যামেরার থেকে শুধুমাত্র প্রয়োজনীয় সাইজের ছবিই অনুরোধ করুন, যা সাধারণত ২ মেগাপিক্সেলের বেশি হয় না।

    নামযুক্ত ক্যাপচার সেশন প্রিসেট—AVCaptureSessionPresetDefault, AVCaptureSessionPresetLow, AVCaptureSessionPresetMedium, ইত্যাদি—ব্যবহার করার পরামর্শ দেওয়া হয় না, কারণ এগুলি কিছু ডিভাইসে অনুপযুক্ত রেজোলিউশনের সাথে ম্যাপ করতে পারে। এর পরিবর্তে, AVCaptureSessionPreset1280x720-এর মতো নির্দিষ্ট প্রিসেট ব্যবহার করুন।

    স্ক্যান করার স্পিড গুরুত্বপূর্ণ হলে, আপনি ছবি ক্যাপচার করার রেজোলিউশন আরও কমাতে পারেন। তবে, উপরে উল্লিখিত ন্যূনতম বারকোড সাইজ সংক্রান্ত প্রয়োজনীয়তা মনে রাখবেন।

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

    ITF এবং CODE-39-এর জন্য চেকসাম ডিজিট কাজ করে না।

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