ตรวจจับและติดตามวัตถุด้วย ML Kit บน iOS

คุณสามารถใช้ ML Kit เพื่อตรวจหาและติดตามวัตถุในเฟรมวิดีโอต่อเนื่องได้

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

ลองเลย

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

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

1. กำหนดค่าตัวตรวจจับออบเจ็กต์

ในการตรวจหาและติดตามออบเจ็กต์ ให้สร้างอินสแตนซ์ของ ObjectDetector และเลือกระบุการตั้งค่าตัวตรวจจับที่คุณต้องการ เปลี่ยนจากค่าเริ่มต้น

  1. กำหนดค่าตัวตรวจจับออบเจ็กต์สำหรับ Use Case ของคุณด้วย ออบเจ็กต์ ObjectDetectorOptions รายการ คุณสามารถเปลี่ยนสิ่งต่อไปนี้ได้ การตั้งค่าต่อไปนี้

    การตั้งค่าตัวตรวจจับวัตถุ
    โหมดการตรวจจับ .stream (ค่าเริ่มต้น) | วันที่ .singleImage

    ในโหมดสตรีม (ค่าเริ่มต้น) ตัวตรวจจับวัตถุจะทำงานโดยมีปริมาณต่ำมาก เวลาในการตอบสนอง แต่อาจทำให้ผลลัพธ์ไม่สมบูรณ์ (เช่น ไม่ได้ระบุ กรอบหรือหมวดหมู่) ในการเรียกใช้ 2-3 ครั้งแรก ตัวตรวจจับ นอกจากนี้ ตัวตรวจจับจะกำหนดการติดตามในโหมดสตรีม รหัสไปยังออบเจ็กต์ซึ่งใช้เพื่อติดตามวัตถุในเฟรมได้ ใช้โหมดนี้เมื่อคุณต้องการติดตามออบเจ็กต์ หรือเมื่อมีเวลาในการตอบสนองต่ำ มีความสำคัญ เช่น เมื่อประมวลผลสตรีมวิดีโอแบบเรียลไทม์

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

    ตรวจหาและติดตามวัตถุหลายรายการ false (ค่าเริ่มต้น) | วันที่ true

    สามารถตรวจจับและติดตามวัตถุได้สูงสุด 5 รายการ หรือเฉพาะวัตถุที่พบมากที่สุด ออบเจ็กต์ที่โดดเด่น (ค่าเริ่มต้น)

    จำแนกประเภทวัตถุ false (ค่าเริ่มต้น) | วันที่ true

    ระบุว่าจะจัดประเภทออบเจ็กต์ที่ตรวจพบเป็นหมวดหมู่คร่าวๆ หรือไม่ เมื่อเปิดใช้ ตัวตรวจจับวัตถุจะจัดประเภทออบเจ็กต์ลงใน หมวดหมู่ต่อไปนี้: สินค้าแฟชั่น อาหาร ของใช้ในบ้าน สถานที่ และต้นไม้ได้

    API การติดตามและตรวจจับออบเจ็กต์ได้รับการเพิ่มประสิทธิภาพสำหรับการใช้งานหลัก 2 รายการนี้ กรณี:

    • การตรวจจับแบบเรียลไทม์และการติดตามวัตถุที่โดดเด่นที่สุดในกล้อง ช่องมองภาพ
    • การตรวจจับวัตถุหลายรายการในภาพนิ่ง

    วิธีกำหนดค่า API สำหรับกรณีการใช้งานเหล่านี้

Swift

// Live detection and tracking
let options = ObjectDetectorOptions()
options.shouldEnableClassification = true

// Multiple object detection in static images
let options = ObjectDetectorOptions()
options.detectorMode = .singleImage
options.shouldEnableMultipleObjects = true
options.shouldEnableClassification = true

Objective-C

// Live detection and tracking
MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init];
options.shouldEnableClassification = YES;

// Multiple object detection in static images
MLKObjectDetectorOptions *options = [[MLKOptions alloc] init];
options.detectorMode = MLKObjectDetectorModeSingleImage;
options.shouldEnableMultipleObjects = YES;
options.shouldEnableClassification = YES;
  1. รับอินสแตนซ์ของ ObjectDetector:

Swift

let objectDetector = ObjectDetector.objectDetector()

// Or, to change the default settings:
let objectDetector = ObjectDetector.objectDetector(options: options)

Objective-C

MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector];

// Or, to change the default settings:
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];

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

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

สร้างออบเจ็กต์ 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];

3. ประมวลผลรูปภาพ

ส่ง VisionImage ไปยังการประมวลผลรูปภาพของตัวตรวจจับวัตถุ คุณสามารถใช้เมธอด process(image:) แบบไม่พร้อมกันหรือ เมธอด results() แบบซิงโครนัส

วิธีตรวจหาวัตถุแบบไม่พร้อมกัน

Swift

objectDetector.process(image) { objects, error in
  guard error == nil else {
    // Error.
    return
  }
  guard !objects.isEmpty else {
    // No objects detected.
    return
  }

  // Success. Get object info here.
  // ...
}

Objective-C

[objectDetector processImage:image
                  completion:^(NSArray * _Nullable objects,
                               NSError * _Nullable error) {
                    if (error == nil) {
                      return;
                    }
                    if (objects.count == 0) {
                      // No objects detected.
                      return;
                    }

                    // Success. Get object info here.
                  }];

วิธีตรวจหาวัตถุพร้อมกัน

Swift

var objects: [Object]
do {
  objects = try objectDetector.results(in: image)
} catch let error {
  print("Failed to detect object with error: \(error.localizedDescription).")
  return
}
guard !objects.isEmpty else {
  print("Object detector returned no results.")
  return
}

// Success. Get object info here.

Objective-C

NSError *error;
NSArray *objects = [objectDetector resultsInImage:image error:&error];
if (error == nil) {
  return;
}
if (objects.count == 0) {
  // No objects detected.
  return;
}

// Success. Get object info here.

4. รับข้อมูลเกี่ยวกับวัตถุที่ตรวจพบ

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

Object แต่ละรายการจะมีพร็อพเพอร์ตี้ต่อไปนี้

frame CGRect ที่ระบุตำแหน่งของออบเจ็กต์ในส่วน รูปภาพ
trackingID จำนวนเต็มที่ระบุออบเจ็กต์ในรูปภาพ หรือ "nil" ใน โหมดภาพเดียว
labels อาร์เรย์ของป้ายกำกับที่อธิบายออบเจ็กต์ที่ตัวตรวจจับแสดงผล พร็อพเพอร์ตี้ว่างเปล่าหากตัวเลือกตัวตรวจจับ ตั้งค่า shouldEnableClassification เป็น false

Swift

// objects contains one item if multiple object detection wasn't enabled.
for object in objects {
  let frame = object.frame
  let trackingID = object.trackingID

  // If classification was enabled:
  let description = object.labels.enumerated().map { (index, label) in
    "Label \(index): \(label.text), \(label.confidence)"
    }.joined(separator:"\n")

}

Objective-C

// The list of detected objects contains one item if multiple
// object detection wasn't enabled.
for (MLKObject *object in objects) {
  CGRect frame = object.frame;
  NSNumber *trackingID = object.trackingID;
  for (MLKObjectLabel *label in object.labels) {
    NSString *labelString = [NSString stringWithFormat: @"%@, %f, %lu",
      label.text, label.confidence, (unsigned long)label.index];
    ...
  }
}

การปรับปรุงความสามารถในการใช้งานและประสิทธิภาพ

โปรดปฏิบัติตามหลักเกณฑ์ต่อไปนี้ในแอปเพื่อให้ผู้ใช้ได้รับประสบการณ์ที่ดีที่สุด

  • การตรวจจับออบเจ็กต์ที่ประสบความสำเร็จขึ้นอยู่กับความซับซ้อนของภาพของออบเจ็กต์ ใน วัตถุที่มีคุณลักษณะทางภาพจำนวนน้อยอาจต้องให้ตรวจจับได้ เพื่อใช้ส่วนที่ใหญ่กว่าของรูปภาพ คุณควรให้คำแนะนำแก่ผู้ใช้เกี่ยวกับ ซึ่งเหมาะสำหรับวัตถุที่ต้องการตรวจจับ
  • เมื่อใช้การจำแนกประเภท หากต้องการตรวจหาวัตถุที่ไม่ตก อยู่ในหมวดหมู่ที่สนับสนุนอย่างชัดเจน ใช้การจัดการพิเศษสำหรับสิ่งที่ไม่ทราบ ออบเจ็กต์

อย่าลืมดูดีไซน์ Material คอลเล็กชันรูปแบบของฟีเจอร์ที่ขับเคลื่อนด้วยแมชชีนเลิร์นนิง

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

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