Phát hiện và theo dõi đối tượng bằng Bộ công cụ học máy trên iOS

Bạn có thể dùng Bộ công cụ học máy để phát hiện và theo dõi các đối tượng trong các khung hình video liên tiếp.

Khi bạn truyền hình ảnh đến Bộ công cụ học máy, công cụ này sẽ phát hiện tối đa 5 đối tượng trong hình ảnh đó cùng với vị trí của mỗi đối tượng trong hình ảnh. Khi phát hiện đối tượng trong luồng video, mỗi đối tượng có một mã nhận dạng duy nhất mà bạn có thể dùng để theo dõi đối tượng giữa các khung hình. Bạn cũng có thể tùy ý bật đối tượng tương đối Phân loại để gắn nhãn các đối tượng bằng mô tả danh mục rộng.

Dùng thử

Trước khi bắt đầu

  1. Đưa các nhóm Bộ công cụ học máy sau đây vào Podfile của bạn:
    pod 'GoogleMLKit/ObjectDetection', '3.2.0'
    
  2. Sau khi bạn cài đặt hoặc cập nhật Nhóm của dự án, hãy mở dự án Xcode của bạn bằng cách sử dụng .xcworkspace. Bộ công cụ học máy được hỗ trợ trong Xcode phiên bản 12.4 trở lên.

1. Định cấu hình trình phát hiện đối tượng

Để phát hiện và theo dõi các đối tượng, trước tiên hãy tạo một thực thể của ObjectDetector và tuỳ ý chỉ định mọi chế độ cài đặt trình phát hiện bạn muốn thay đổi so với giá trị mặc định.

  1. Định cấu hình trình phát hiện đối tượng cho trường hợp sử dụng của bạn bằng Đối tượng ObjectDetectorOptions. Bạn có thể thay đổi các tuỳ chọn sau cài đặt:

    Cài đặt trình phát hiện đối tượng
    Chế độ phát hiện .stream (mặc định) | .singleImage

    Ở chế độ phát trực tuyến (mặc định), trình phát hiện đối tượng chạy với mức pin rất thấp nhưng có thể dẫn đến kết quả không đầy đủ (chẳng hạn như kết quả không được chỉ định) hộp giới hạn hoặc danh mục) trên một số lệnh gọi đầu tiên của trình phát hiện. Ngoài ra, ở chế độ phát trực tuyến, trình phát hiện gán tính năng theo dõi Mã nhận dạng của các đối tượng mà bạn có thể dùng để theo dõi đối tượng trên nhiều khung hình. Sử dụng chế độ này khi bạn muốn theo dõi các đối tượng hoặc khi có độ trễ thấp rất quan trọng, chẳng hạn như khi xử lý luồng video trong thực tế bất cứ lúc nào.

    Ở chế độ hình ảnh đơn, trình phát hiện đối tượng sẽ trả về kết quả sau khi xác định vùng giới hạn của đối tượng. Nếu bạn cũng bật phương thức này sẽ trả về kết quả sau hộp giới hạn và nhãn danh mục đều có sẵn. Do vậy, việc phát hiện thì độ trễ có thể cao hơn. Ngoài ra, ở chế độ hình ảnh đơn, tính năng theo dõi Chưa chỉ định mã nhận dạng. Sử dụng chế độ này nếu độ trễ không quan trọng và bạn không muốn xử lý một phần kết quả.

    Phát hiện và theo dõi nhiều đối tượng false (mặc định) | true

    Phát hiện và theo dõi tối đa 5 đối tượng hay chỉ phát hiện tối đa đối tượng đối tượng nổi bật (mặc định).

    Phân loại đối tượng false (mặc định) | true

    Liệu có phân loại các đối tượng được phát hiện thành các danh mục tương đối hay không. Khi được bật, trình phát hiện đối tượng sẽ phân loại đối tượng thành các danh mục sau: hàng thời trang, thực phẩm, đồ gia dụng, địa điểm và cây cối.

    API theo dõi và phát hiện đối tượng được tối ưu hoá cho hai mục đích sử dụng cốt lõi này trường hợp:

    • Phát hiện trực tiếp và theo dõi đối tượng nổi bật nhất trong máy ảnh kính ngắm.
    • Phát hiện nhiều đối tượng trong ảnh tĩnh.

    Cách định cấu hình API cho các trường hợp sử dụng này:

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. Nhận một thực thể của 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. Chuẩn bị hình ảnh đầu vào

Để phát hiện và theo dõi các đối tượng, hãy làm như sau cho từng hình ảnh hoặc khung video. Nếu đã bật chế độ phát trực tuyến, bạn phải tạo các đối tượng VisionImage từ CMSampleBuffer giây.

Tạo đối tượng VisionImage bằng UIImage hoặc CMSampleBuffer.

Nếu bạn sử dụng UIImage, hãy làm theo các bước sau:

  • Tạo đối tượng VisionImage bằng UIImage. Hãy nhớ chỉ định đúng .orientation.

    Swift

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

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

Nếu bạn sử dụng CMSampleBuffer, hãy làm theo các bước sau:

  • Chỉ định hướng của dữ liệu hình ảnh có trong CMSampleBuffer.

    Cách lấy hướng ảnh:

    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;
      }
    }
          
  • Tạo đối tượng VisionImage bằng cách sử dụng Đối tượng và hướng 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. Xử lý hình ảnh

Truyền VisionImage đến một trong các trình xử lý hình ảnh của trình phát hiện đối tượng . Bạn có thể sử dụng phương thức process(image:) không đồng bộ hoặc results() đồng bộ.

Cách phát hiện đối tượng không đồng bộ:

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

Cách phát hiện đối tượng một cách đồng bộ:

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. Lấy thông tin về đối tượng được phát hiện

Nếu lệnh gọi đến bộ xử lý hình ảnh thành công, lệnh gọi đó sẽ chuyển danh sách Object cho trình xử lý hoàn thành hoặc trả về danh sách, tuỳ thuộc vào cho dù bạn đã gọi phương thức không đồng bộ hay đồng bộ.

Mỗi Object chứa các thuộc tính sau:

frame CGRect cho biết vị trí của đối tượng trong hình ảnh.
trackingID Một số nguyên xác định đối tượng trên các hình ảnh hoặc `nil` trong chế độ hình ảnh đơn.
labels Một mảng nhãn mô tả đối tượng mà trình phát hiện trả về. Thuộc tính sẽ trống nếu tuỳ chọn trình phát hiện shouldEnableClassification được đặt thành 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];
    ...
  }
}

Cải thiện khả năng hữu dụng và hiệu suất

Để có trải nghiệm người dùng tốt nhất, hãy làm theo các nguyên tắc sau trong ứng dụng của bạn:

  • Việc phát hiện được đối tượng có thành công hay không còn phụ thuộc vào độ phức tạp trực quan của đối tượng. Ngang bằng những đối tượng có một số ít đặc điểm trực quan có thể cần được phát hiện chiếm phần lớn hình ảnh. Bạn nên cung cấp cho người dùng hướng dẫn về thu thập dữ liệu đầu vào phù hợp với loại đối tượng bạn muốn phát hiện.
  • Khi sử dụng tính năng phân loại, nếu bạn muốn phát hiện các đối tượng không nằm trong rõ ràng vào các danh mục được hỗ trợ, triển khai cách xử lý đặc biệt đối với các trường hợp không xác định .

Ngoài ra, hãy tham khảo Material Design Bộ sưu tập Mẫu cho các tính năng dựa trên công nghệ học máy.

Khi bạn sử dụng chế độ truyền trực tuyến trong một ứng dụng theo thời gian thực, hãy làm theo các nguyên tắc sau để đạt được tốc độ khung hình tốt nhất:

  • Đừng dùng tính năng phát hiện nhiều vật thể ở chế độ phát trực tuyến, vì hầu hết các thiết bị sẽ không dùng được có thể tạo đủ tốc độ khung hình.
  • Hãy tắt tính năng phân loại nếu bạn không cần.
  • Để xử lý khung hình video, hãy sử dụng API đồng bộ results(in:) của trình phát hiện. Gọi điện phương thức này từ Điều khoản dịch vụ và Chính sách quyền riêng tư của AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) để nhận kết quả một cách đồng bộ từ video đã cho khung. Giữ của AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames dưới dạng true để điều tiết lệnh gọi đến trình phát hiện. Nếu một khách hàng mới khung hình video sẽ bị loại bỏ trong khi trình phát hiện đang chạy.
  • Nếu bạn sử dụng đầu ra của trình phát hiện để phủ đồ hoạ lên hình ảnh đầu vào, trước tiên hãy lấy kết quả từ Bộ công cụ học máy, sau đó kết xuất hình ảnh và phủ lên trên trong một bước duy nhất. Khi làm vậy, bạn sẽ kết xuất lên giao diện màn hình một lần cho mỗi khung đầu vào đã xử lý. Hãy xem lớp updatePreviewOverlayViewWithLastFrame trong mẫu bắt đầu nhanh của Bộ công cụ học máy.