סרוק ברקודים עם ערכת ML ב- iOS

אתה יכול להשתמש בערכת ML כדי לזהות ולפענח ברקודים.

לפני שאתה מתחיל

  1. אם לא כבר הוסיף Firebase באפליקציה, לעשות זאת על ידי ביצוע השלבים במדריך להפעלה .
  2. כלול את הספריות קיט ML ב Podfile שלך:
    pod 'Firebase/MLVision'
    pod 'Firebase/MLVisionBarcodeModel'
    
    לאחר להתקין או לעדכן שקיקים של הפרויקט שלך, להיות בטוח כדי לפתוח פרויקט Xcode שלך באמצעות שלה .xcworkspace .
  3. באפליקציה שלך, ייבא את Firebase:

    מָהִיר

    import Firebase

    Objective-C

    @import Firebase;

הקלט הנחיות לתמונות

  • כדי ש- ML Kit יקרא ברקודים במדויק, תמונות הקלט חייבות להכיל ברקודים המיוצגים על ידי נתוני פיקסל מספיקים.

    דרישות נתוני הפיקסלים הספציפיים תלויים הן בסוג הברקוד והן בכמות הנתונים המקודדים בו (מכיוון שרוב הברקודים תומכים במטען באורך משתנה). באופן כללי, היחידה המשמעותית הקטנה ביותר של הברקוד צריכה להיות ברוחב 2 פיקסלים לפחות (ולגבי קודים דו ממדיים, בגובה 2 פיקסלים).

    לדוגמה, ברקודים EAN-13 מורכבים מסורגים ומרווחים ברוחב 1, 2, 3 או 4 יחידות, כך שתמונת ברקוד EAN-13 מכילה אידיאלי ברים ומרווחים שהם לפחות 2, 4, 6 ו 8 פיקסלים ברוחב. מכיוון שברקוד EAN-13 הוא ברוחב 95 יחידות בסך הכל, הברקוד צריך להיות ברוחב של לפחות 190 פיקסלים.

    פורמטים צפופים יותר, כגון PDF417, זקוקים לממדי פיקסלים גדולים יותר כדי ש- ML Kit יקרא אותם בצורה מהימנה. לדוגמה, קוד PDF417 יכול להכיל עד 34 "מילים" ברוחב 17 יחידות בשורה אחת, שרוחבו יהיה ברוחב של לפחות 1156 פיקסלים.

  • מיקוד לקוי של התמונה עלול לפגוע בדיוק הסריקה. אם אינך מקבל תוצאות מקובלות, נסה לבקש מהמשתמש לצלם מחדש את התמונה.

  • ליישומים טיפוסיים, מומלץ לספק תמונה ברזולוציה גבוהה יותר (כגון 1280x720 או 1920x1080), מה שהופך את הברקודים לזיהוי ממרחק גדול יותר מהמצלמה.

    עם זאת, ביישומים בהם חביון הוא קריטי, תוכל לשפר את הביצועים על ידי לכידת תמונות ברזולוציה נמוכה יותר, אך דרישה שהברקוד יהווה את מרבית תמונת הקלט. ראה גם טיפים לשיפור ביצועים בזמן אמת .

1. הגדר את גלאי הברקוד

אם אתה יודע אילו פורמטים של ברקוד אתה מצפה לקרוא, תוכל לשפר את מהירות גלאי הברקוד על ידי הגדרתו לזיהוי פורמטים אלה בלבד.

לדוגמה, כדי לזהות קודים קוד QR האצטקית בלבד, לבנות VisionBarcodeDetectorOptions להתנגד כמו בדוגמה הבאה:

מָהִיר

let format = VisionBarcodeFormat.all
let barcodeOptions = VisionBarcodeDetectorOptions(formats: format)

הפורמטים הבאים נתמכים:

  • קוד 128
  • קוד 39
  • קוד 93
  • CodaBar
  • EAN13
  • EAN8
  • ITF
  • UPCA
  • UPCE
  • קוד QR
  • PDF417
  • אצטקים
  • מטריצת נתונים

Objective-C

FIRVisionBarcodeDetectorOptions *options =
    [[FIRVisionBarcodeDetectorOptions alloc]
     initWithFormats: FIRVisionBarcodeFormatQRCode | FIRVisionBarcodeFormatAztec];

הפורמטים הבאים נתמכים:

  • קוד 128 ( FIRVisionBarcodeFormatCode128 )
  • קוד 39 ( FIRVisionBarcodeFormatCode39 )
  • קוד 93 ( FIRVisionBarcodeFormatCode93 )
  • Codabar ( FIRVisionBarcodeFormatCodaBar )
  • EAN-13 ( FIRVisionBarcodeFormatEAN13 )
  • EAN-8 ( FIRVisionBarcodeFormatEAN8 )
  • ITF ( FIRVisionBarcodeFormatITF )
  • UPC-A ( FIRVisionBarcodeFormatUPCA )
  • UPC-E ( FIRVisionBarcodeFormatUPCE )
  • קוד QR ( FIRVisionBarcodeFormatQRCode )
  • PDF417 ( FIRVisionBarcodeFormatPDF417 )
  • האצטקים ( FIRVisionBarcodeFormatAztec )
  • מטריקס נתונים ( FIRVisionBarcodeFormatDataMatrix )

2. הפעל את גלאי הברקוד

כדי לסרוק ברקודים בתמונה, להעביר את התמונה כקובץ UIImage או CMSampleBufferRef אל VisionBarcodeDetector של detect(in:) השיטה:

  1. קבל מופע של VisionBarcodeDetector :

    מָהִיר

    lazy var vision = Vision.vision()
    
    let barcodeDetector = vision.barcodeDetector(options: barcodeOptions)
    

    Objective-C

    FIRVision *vision = [FIRVision vision];
    FIRVisionBarcodeDetector *barcodeDetector = [vision barcodeDetector];
    // Or, to change the default settings:
    // FIRVisionBarcodeDetector *barcodeDetector =
    //     [vision barcodeDetectorWithOptions:options];
    
  2. צור VisionImage אובייקט באמצעות UIImage או CMSampleBufferRef .

    כדי להשתמש UIImage :

    1. במידת הצורך, לסובב את התמונה כך שלה imageOrientation הנכס הוא .up .
    2. צור VisionImage אובייקט באמצעות כראוי-המסובב UIImage . לא ציין סיבוב מטה-ערך ברירת המחדל, .topLeft , חייב לשמש.

      מָהִיר

      let image = VisionImage(image: uiImage)

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

    כדי להשתמש CMSampleBufferRef :

    1. צור VisionImageMetadata אובייקט המציין את הכיוון של נתוני תמונה הכלול CMSampleBufferRef חיץ.

      כדי לקבל את כיוון התמונה:

      מָהִיר

      func imageOrientation(
          deviceOrientation: UIDeviceOrientation,
          cameraPosition: AVCaptureDevice.Position
          ) -> VisionDetectorImageOrientation {
          switch deviceOrientation {
          case .portrait:
              return cameraPosition == .front ? .leftTop : .rightTop
          case .landscapeLeft:
              return cameraPosition == .front ? .bottomLeft : .topLeft
          case .portraitUpsideDown:
              return cameraPosition == .front ? .rightBottom : .leftBottom
          case .landscapeRight:
              return cameraPosition == .front ? .topRight : .bottomRight
          case .faceDown, .faceUp, .unknown:
              return .leftTop
          }
      }

      Objective-C

      - (FIRVisionDetectorImageOrientation)
          imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                                 cameraPosition:(AVCaptureDevicePosition)cameraPosition {
        switch (deviceOrientation) {
          case UIDeviceOrientationPortrait:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationLeftTop;
            } else {
              return FIRVisionDetectorImageOrientationRightTop;
            }
          case UIDeviceOrientationLandscapeLeft:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationBottomLeft;
            } else {
              return FIRVisionDetectorImageOrientationTopLeft;
            }
          case UIDeviceOrientationPortraitUpsideDown:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationRightBottom;
            } else {
              return FIRVisionDetectorImageOrientationLeftBottom;
            }
          case UIDeviceOrientationLandscapeRight:
            if (cameraPosition == AVCaptureDevicePositionFront) {
              return FIRVisionDetectorImageOrientationTopRight;
            } else {
              return FIRVisionDetectorImageOrientationBottomRight;
            }
          default:
            return FIRVisionDetectorImageOrientationTopLeft;
        }
      }

      לאחר מכן, צור את אובייקט המטא -נתונים:

      מָהִיר

      let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
      let metadata = VisionImageMetadata()
      metadata.orientation = imageOrientation(
          deviceOrientation: UIDevice.current.orientation,
          cameraPosition: cameraPosition
      )

      Objective-C

      FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
      AVCaptureDevicePosition cameraPosition =
          AVCaptureDevicePositionBack;  // Set to the capture device you used.
      metadata.orientation =
          [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                       cameraPosition:cameraPosition];
    2. צור VisionImage אובייקט באמצעות CMSampleBufferRef האובייקט ואת מטה סיבוב:

      מָהִיר

      let image = VisionImage(buffer: sampleBuffer)
      image.metadata = metadata

      Objective-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  3. ואז, להעביר את התמונה detect(in:) השיטה:

    מָהִיר

    barcodeDetector.detect(in: visionImage) { features, error in
      guard error == nil, let features = features, !features.isEmpty else {
        // ...
        return
      }
    
      // ...
    }
    

    Objective-C

    [barcodeDetector detectInImage:image
                        completion:^(NSArray<FIRVisionBarcode *> *barcodes,
                                     NSError *error) {
      if (error != nil) {
        return;
      } else if (barcodes != nil) {
        // Recognized barcodes
        // ...
      }
    }];
    

3. קבל מידע מברקודים

אם פעולת זיהוי ברקוד מצליח, גלאי מחזירה מערך של VisionBarcode חפצים. כל VisionBarcode אובייקט מייצג ברקוד שזוהה בתמונה. עבור כל ברקוד, אתה יכול לקבל את קואורדינטות הגבול שלו בתמונת הקלט, כמו גם את הנתונים הגולמיים המקודדים על ידי הברקוד. כמו כן, אם גלאי הברקוד הצליח לקבוע את סוג הנתונים המקודדים על ידי הברקוד, תוכל לקבל אובייקט המכיל נתונים מנותחים.

לדוגמה:

מָהִיר

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 (FIRVisionBarcode *barcode in barcodes) {
   NSArray *corners = barcode.cornerPoints;

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

   FIRVisionBarcodeValueType valueType = barcode.valueType;
   switch (valueType) {
     case FIRVisionBarcodeValueTypeWiFi:
       // ssid = barcode.wifi.ssid;
       // password = barcode.wifi.password;
       // encryptionType = barcode.wifi.type;
       break;
     case FIRVisionBarcodeValueTypeURL:
       // url = barcode.URL.url;
       // title = barcode.URL.title;
       break;
     // ...
     default:
       break;
   }
 }

טיפים לשיפור הביצועים בזמן אמת

אם ברצונך לסרוק ברקודים ביישום בזמן אמת, פעל לפי ההנחיות הבאות כדי להשיג את מסגרות המסגרות הטובות ביותר:

  • אל תצלם קלט ברזולוציה המקורית של המצלמה. במכשירים מסוימים, לכידת קלט ברזולוציה המקורית מייצרת תמונות גדולות במיוחד (10+ מגה פיקסל), מה שמביא לעיכוב גרוע מאוד ללא יתרון לדיוק. במקום זאת, בקש רק את הגודל מהמצלמה הנדרש לזיהוי ברקוד: בדרך כלל לא יותר מ -2 מגה פיקסל.

    המושב ללכוד בשם presets- AVCaptureSessionPresetDefault , AVCaptureSessionPresetLow , AVCaptureSessionPresetMedium , וכן הלאה) -האם לא מומלץ, עם זאת, כפי שהם יכולים למפות החלטות מתאימות על מכשירים מסוימים. במקום זאת, השתמש קבוע מראש ספציפית כגון AVCaptureSessionPreset1280x720 .

    אם מהירות הסריקה חשובה, תוכל להוריד עוד יותר את רזולוציית צילום התמונה. עם זאת, זכור את דרישות גודל הברקוד המינימלי המתוארות לעיל.

  • מצערת מצערת לגלאי. אם מסגרת וידאו חדשה הופכת לזמינה בזמן שהגלאי פועל, השמט את המסגרת.
  • אם אתה משתמש בפלט הגלאי כדי לכסות גרפיקה על תמונת הקלט, תחילה קבל את התוצאה מ- ML Kit, ולאחר מכן עיבד את התמונה ואת שכבת העל בשלב אחד. בכך אתה מעבד למשטח התצוגה רק פעם אחת עבור כל מסגרת קלט. עיין previewOverlayView ו FIRDetectionOverlayView כיתות ביישום מדגם ראווה עבור דוגמה.