ติดป้ายกำกับรูปภาพด้วย ML Kit ใน iOS

คุณใช้ ML Kit เพื่อติดป้ายกำกับออบเจ็กต์ที่รู้จักในรูปภาพได้ โมเดลเริ่มต้นที่มาพร้อมกับ ML Kit รองรับป้ายกำกับที่แตกต่างกันมากกว่า 400 ป้าย

ลองเลย

ก่อนเริ่มต้น

  1. รวมพ็อด ML Kit ต่อไปนี้ใน Podfile:
    pod 'GoogleMLKit/ImageLabeling', '3.2.0'
    
  2. หลังจากติดตั้งหรืออัปเดตพ็อดของโปรเจ็กต์แล้ว ให้เปิดโปรเจ็กต์ Xcode โดยใช้ .xcworkspace ของโปรเจ็กต์นั้น Xcode เวอร์ชัน 12.4 ขึ้นไปรองรับ ML Kit

ตอนนี้คุณก็พร้อมติดป้ายกำกับรูปภาพแล้ว

1. เตรียมรูปภาพอินพุต

สร้างออบเจ็กต์ VisionImage โดยใช้ UIImage หรือ CMSampleBuffer

หากคุณใช้ UIImage ให้ทำตามขั้นตอนต่อไปนี้

  • สร้างออบเจ็กต์ VisionImage ที่มี UIImage ตรวจสอบว่าได้ระบุ .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;
      }
    }
          
  • สร้างออบเจ็กต์ VisionImage โดยใช้ออบเจ็กต์ CMSampleBuffer และการวางแนวดังนี้

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

2. กำหนดค่าและเรียกใช้เครื่องมือติดป้ายกำกับรูปภาพ

หากต้องการติดป้ายกำกับวัตถุในรูปภาพ ให้ส่งออบเจ็กต์ VisionImage ไปยังเมธอด processImage() ของ ImageLabeler

  1. ก่อนอื่น ให้รับอินสแตนซ์ของ ImageLabeler

Swift

let labeler = ImageLabeler.imageLabeler()

// Or, to set the minimum confidence required:
// let options = ImageLabelerOptions()
// options.confidenceThreshold = 0.7
// let labeler = ImageLabeler.imageLabeler(options: options)

Objective-C

MLKImageLabeler *labeler = [MLKImageLabeler imageLabeler];

// Or, to set the minimum confidence required:
// MLKImageLabelerOptions *options =
//         [[MLKImageLabelerOptions alloc] init];
// options.confidenceThreshold = 0.7;
// MLKImageLabeler *labeler =
//         [MLKImageLabeler imageLabelerWithOptions:options];
  1. จากนั้นส่งรูปภาพไปยังเมธอด processImage() ดังนี้

Swift

labeler.process(image) { labels, error in
    guard error == nil, let labels = labels else { return }

    // Task succeeded.
    // ...
}

Objective-C

[labeler processImage:image
completion:^(NSArray *_Nullable labels,
            NSError *_Nullable error) {
   if (error != nil) { return; }

   // Task succeeded.
   // ...
}];

3. รับข้อมูลเกี่ยวกับออบเจ็กต์ที่ติดป้ายกำกับ

หากการติดป้ายกำกับรูปภาพสำเร็จ ตัวแฮนเดิลการเสร็จสมบูรณ์จะได้รับอาร์เรย์ของออบเจ็กต์ ImageLabel รายการ ออบเจ็กต์ ImageLabel แต่ละรายการแสดงถึงสิ่งที่ติดป้ายกำกับไว้ในรูปภาพ โมเดลฐานรองรับป้ายกำกับที่แตกต่างกันมากกว่า 400 ป้าย คุณสามารถดูคำอธิบายข้อความของแต่ละป้ายกำกับ จัดทำดัชนีจากป้ายกำกับทั้งหมดที่โมเดลดังกล่าวรองรับ และคะแนนความเชื่อมั่นของการจับคู่ เช่น

Swift

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

Objective-C

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

เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์

หากต้องการติดป้ายกำกับรูปภาพในแอปพลิเคชันแบบเรียลไทม์ ให้ทำตามหลักเกณฑ์ต่อไปนี้เพื่อให้ได้อัตราเฟรมที่ดีที่สุด

  • สำหรับการประมวลผลเฟรมวิดีโอ ให้ใช้ API แบบซิงโครนัส results(in:) ของผู้ติดป้ายกำกับรูปภาพ เรียกใช้เมธอดนี้จากฟังก์ชัน captureOutput(_, didOutput:from:) ของ AVCaptureVideoDataOutputSampleBufferDelegate เพื่อรับผลการค้นหาจากเฟรมวิดีโอที่ระบุแบบพร้อมกัน เก็บ alwaysDiscardsLateVideoFrames ของ AVCaptureVideoDataOutput เป็น true เพื่อควบคุมการเรียกไปยังผู้ติดป้ายกำกับรูปภาพ หากเฟรมวิดีโอใหม่พร้อมใช้งานขณะที่ผู้ติดป้ายกำกับรูปภาพทำงานอยู่ เฟรมดังกล่าวจะหายไป
  • หากคุณใช้เอาต์พุตของผู้ติดป้ายกำกับรูปภาพเพื่อวางซ้อนกราฟิกบนรูปภาพอินพุต ให้รับผลลัพธ์จาก ML Kit ก่อน จากนั้นจึงแสดงผลรูปภาพและการวางซ้อนในขั้นตอนเดียว การทำเช่นนี้จะทำให้คุณแสดงผลบนพื้นผิวแสดงผลเพียงครั้งเดียวต่อเฟรมอินพุตที่ประมวลผลแต่ละเฟรม ดู updatePreviewOverlayViewWithLastFrame ในตัวอย่างการเริ่มใช้งานอย่างรวดเร็วของ ML Kit