Phát hiện và theo dõi đối tượng bằng ML Kit trên iOS

Bạn có thể sử dụng ML Kit để phát hiện và theo dõi các đối tượng trên các khung hình của video.

Khi bạn chuyển hình ảnh Bộ công cụ ML, Bộ công cụ ML sẽ trả về, đối với mỗi hình ảnh, danh sách tối đa năm đối tượng được phát hiện và vị trí của chúng trong hình ảnh. Khi phát hiện đối tượng trong luồng video, mọi đối tượng đều có ID mà bạn có thể sử dụng để theo dõi đối tượng trên các hình ảnh. Bạn cũng có thể tùy ý kích hoạt phân loại đối tượng thô, gắn nhãn các đối tượng bằng mô tả danh mục rộng.

Trước khi bắt đầu

  1. Nếu bạn chưa thêm Firebase vào ứng dụng của mình, hãy làm như vậy bằng cách làm theo các bước trong hướng dẫn bắt đầu .
  2. Bao gồm các thư viện ML Kit trong Podfile của bạn:
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionObjectDetection', '6.25.0'
    
    Sau khi bạn cài đặt hoặc cập nhật Pod của dự án, hãy nhớ mở dự án Xcode của bạn bằng cách sử dụng .xcworkspace .
  3. Trong ứng dụng của bạn, hãy nhập Firebase:

    Nhanh

    import Firebase

    Mục tiêu-C

    @import Firebase;

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

Để bắt đầu phát hiện và theo dõi các đối tượng, trước tiên hãy tạo một phiên bản VisionObjectDetector , tùy ý chỉ định bất kỳ cài đặt trình phát hiện nào bạn muốn thay đổi so với 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 với đối tượng VisionObjectDetectorOptions . Bạn có thể thay đổi các cài đặt sau:

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

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

    Ở chế độ một hình ảnh, trình phát hiện đối tượng sẽ đợi cho đến khi hộp giới hạn của đối tượng được phát hiện và danh mục (nếu bạn đã bật phân loại) có sẵn trước khi trả về kết quả. Kết quả là độ trễ phát hiện có khả năng cao hơn. Ngoài ra, ở chế độ một hình ảnh, ID theo dõi không được chỉ định. Sử dụng chế độ này nếu độ trễ không quá nghiêm 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 năm đối tượng hay chỉ đối tượng nổi bật nhất (mặc định).

    Phân loại đồ vật false (mặc định) | true

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

    API theo dõi và phát hiện đối tượng được tối ưu hóa cho hai trường hợp sử dụng cốt lõi sau:

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

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

    Nhanh

    // Live detection and tracking
    let options = VisionObjectDetectorOptions()
    options.detectorMode = .stream
    options.shouldEnableMultipleObjects = false
    options.shouldEnableClassification = true  // Optional
    
    // Multiple object detection in static images
    let options = VisionObjectDetectorOptions()
    options.detectorMode = .singleImage
    options.shouldEnableMultipleObjects = true
    options.shouldEnableClassification = true  // Optional
    

    Mục tiêu-C

    // Live detection and tracking
    FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init];
    options.detectorMode = FIRVisionObjectDetectorModeStream;
    options.shouldEnableMultipleObjects = NO;
    options.shouldEnableClassification = YES;  // Optional
    
    // Multiple object detection in static images
    FIRVisionObjectDetectorOptions *options = [[FIRVisionObjectDetectorOptions alloc] init];
    options.detectorMode = FIRVisionObjectDetectorModeSingleImage;
    options.shouldEnableMultipleObjects = YES;
    options.shouldEnableClassification = YES;  // Optional
    
  2. Lấy một phiên bản của FirebaseVisionObjectDetector :

    Nhanh

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

    Mục tiêu-C

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

2. Chạy trình dò ​​tìm đối tượng

Để phát hiện và theo dõi các đối tượng, hãy thực hiện như sau cho từng hình ảnh hoặc khung hình của video. Nếu bạn đã bật chế độ truyền phát, bạn phải tạo các đối tượng VisionImage từ CMSampleBufferRef s.

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

    Để sử dụng UIImage :

    1. Nếu cần, hãy xoay hình ảnh sao cho thuộc tính imageOrientation của nó là .up .
    2. Tạo một đối tượng VisionImage bằng cách sử dụng UIImage được xoay chính xác. Không chỉ định bất kỳ siêu dữ liệu xoay nào—giá trị mặc định, .topLeft , phải được sử dụng.

      Nhanh

      let image = VisionImage(image: uiImage)

      Mục tiêu-C

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

    Để sử dụng CMSampleBufferRef :

    1. Tạo một đối tượng VisionImageMetadata chỉ định hướng của dữ liệu hình ảnh có trong bộ đệm CMSampleBufferRef .

      Để có được hướng hình ảnh:

      Nhanh

      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
          }
      }

      Mục tiêu-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;
        }
      }

      Sau đó, tạo đối tượng siêu dữ liệu:

      Nhanh

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

      Mục tiêu-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. Tạo một đối tượng VisionImage bằng cách sử dụng đối tượng CMSampleBufferRef và siêu dữ liệu xoay:

      Nhanh

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

      Mục tiêu-C

      FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
      image.metadata = metadata;
  2. Truyền VisionImage cho một trong các phương pháp 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 phương thức results() đồng bộ.

    Để phát hiện các đối tượng không đồng bộ:

    Nhanh

    objectDetector.process(image) { detectedObjects, error in
      guard error == nil else {
        // Error.
        return
      }
      guard let detectedObjects = detectedObjects, !detectedObjects.isEmpty else {
        // No objects detected.
        return
      }
    
      // Success. Get object info here.
      // ...
    }
    

    Mục tiêu-C

    [objectDetector processImage:image
                      completion:^(NSArray<FIRVisionObject *> * _Nullable objects,
                                   NSError * _Nullable error) {
                        if (error == nil) {
                          return;
                        }
                        if (objects == nil | objects.count == 0) {
                          // No objects detected.
                          return;
                        }
    
                        // Success. Get object info here.
                        // ...
                      }];
    

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

    Nhanh

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

    Mục tiêu-C

    NSError *error;
    NSArray<FIRVisionObject *> *objects = [objectDetector resultsInImage:image
                                                                   error:&error];
    if (error == nil) {
      return;
    }
    if (objects == nil | objects.count == 0) {
      // No objects detected.
      return;
    }
    
    // Success. Get object info here.
    // ...
    
  3. Nếu lệnh gọi tới bộ xử lý hình ảnh thành công, nó sẽ chuyển danh sách VisionObject đến trình xử lý hoàn thành hoặc trả về danh sách, tùy thuộc vào việc bạn gọi phương thức không đồng bộ hay đồng bộ.

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

    frame CGRect cho biết vị trí của đối tượng trong ảnh.
    trackingID Một số nguyên xác định đối tượng trên các hình ảnh. Không có ở chế độ hình ảnh đơn.
    classificationCategory Phạm trù thô của đối tượng. Nếu trình phát hiện đối tượng không bật tính năng phân loại thì đây luôn là .unknown .
    confidence Giá trị tin cậy của phân loại đối tượng. Nếu trình phát hiện đối tượng không bật tính năng phân loại hoặc đối tượng được phân loại là không xác định thì đây là nil .

    Nhanh

    // detectedObjects contains one item if multiple object detection wasn't enabled.
    for obj in detectedObjects {
      let bounds = obj.frame
      let id = obj.trackingID
    
      // If classification was enabled:
      let category = obj.classificationCategory
      let confidence = obj.confidence
    }
    

    Mục tiêu-C

    // The list of detected objects contains one item if multiple
    // object detection wasn't enabled.
    for (FIRVisionObject *obj in objects) {
      CGRect bounds = obj.frame;
      if (obj.trackingID) {
        NSInteger id = obj.trackingID.integerValue;
      }
    
      // If classification was enabled:
      FIRVisionObjectCategory category = obj.classificationCategory;
      float confidence = obj.confidence.floatValue;
    }
    

Cải thiện khả năng sử 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 đối tượng thành công phụ thuộc vào độ phức tạp trực quan của đối tượng. Các đối tượng có ít đặc điểm hình ảnh có thể cần chiếm phần lớn hơn của hình ảnh để được phát hiện. Bạn nên cung cấp cho người dùng hướng dẫn về cách thu thập thông tin đầ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 phân loại, nếu bạn muốn phát hiện các đối tượng không thuộc các danh mục được hỗ trợ, hãy thực hiện xử lý đặc biệt đối với các đối tượng không xác định.

Ngoài ra, hãy xem [ứng dụng giới thiệu Material Design của ML Kit][showcase-link]{: .external } và Mẫu thiết kế Material Design cho bộ sưu tập các tính năng hỗ trợ máy học .

Khi sử dụng chế độ phát trực tuyến trong ứng dụng 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:

  • Không sử dụng tính năng phát hiện nhiều đối tượng trong chế độ phát trực tuyến vì hầu hết các thiết bị sẽ không thể tạo ra tốc độ khung hình phù hợp.

  • Vô hiệu hóa phân loại nếu bạn không cần nó.

  • Van tiết lưu gọi tới máy dò. Nếu có khung hình video mới trong khi trình phát hiện đang chạy, hãy thả khung hình đó xuống.
  • Nếu bạn đang sử dụng đầu ra của bộ dò để phủ đồ họa lên hình ảnh đầu vào, trước tiên hãy lấy kết quả từ Bộ công cụ ML, sau đó kết xuất hình ảnh và lớp phủ trong một bước duy nhất. Bằng cách đó, bạn chỉ hiển thị trên bề mặt hiển thị một lần cho mỗi khung hình đầu vào. Xem các lớp PreviewOverlayViewFIRDetectionOverlayView trong ứng dụng mẫu giới thiệu để biết ví dụ.