ML Kit を使用してオブジェクトを検出して追跡する(iOS)

ML Kit を使用すると、連続する動画フレーム内のオブジェクトを検出して追跡できます。

ML Kit に画像を渡すと、画像内で最大 5 つのオブジェクトが検出されます。 画像内の各オブジェクトの位置を確認できます対象物の検知時に 各オブジェクトには、そのオブジェクトを追跡するために使用できる 同じです必要に応じて、おおまかなオブジェクトの 分類を使用します。

試してみる

始める前に

  1. Podfile に次の ML Kit Pod を追加します。
    pod 'GoogleMLKit/ObjectDetection', '3.2.0'
    
  2. プロジェクトの Pod をインストールまたは更新したら、Xcode プロジェクトを開きます。 .xcworkspace。ML Kit は Xcode バージョン 12.4 以降でサポートされています。

1. オブジェクト検出を構成する

オブジェクトを検出して追跡するには、まず ObjectDetector。必要に応じて、検出機能の設定を指定します。 変更できます。

  1. 以下を使用して、ユースケースに合わせてオブジェクト検出を構成してください。 ObjectDetectorOptions オブジェクト。次の項目を変更できます。 設定:

    オブジェクト検出の設定
    検出モード .stream(デフォルト)|.singleImage

    ストリーム モード(デフォルト)では、オブジェクト検出は、 発生する可能性はありますが、不完全な結果(未指定など)は 最初の数回の呼び出しで、境界ボックスやカテゴリなど)を なります。また、ストリーム モードでは、検出機能によってトラッキング ID をオブジェクトにマッピングすることで、フレームをまたいでオブジェクトを追跡できます。 このモードは、オブジェクトを追跡する場合や、 リアルタイムで動画ストリームを処理する場合などに、 あります。

    シングル イメージ モードでは、オブジェクト検出によって オブジェクトの境界ボックスが確定した後のレスポンスです。「新規顧客の獲得」目標も 境界ボックスの後に結果を返します。 両方を使用できます。その結果 レイテンシが高くなる可能性がありますまた シングル画像モードでは ID は割り当てられません。このモードは、レイテンシが重要ではなく、 部分的な結果を処理したくない場合です

    複数のオブジェクトを検出して追跡する false(デフォルト)|true

    最大 5 つのオブジェクトを検出して追跡するか、最も大きい 目立たせることができます(デフォルト)。

    オブジェクトを分類する false(デフォルト)|true

    検出されたオブジェクトを大まかなカテゴリに分類するかどうか。 有効にすると、オブジェクト検出はオブジェクトを 次のカテゴリ: ファッション アイテム、食品、日用品、 予測します。

    Object Detection and Tracking 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 を使用する場合は、次の手順を行います。

  • UIImage を使用して VisionImage オブジェクトを作成します。正しい .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 画像全体でオブジェクトを識別する整数、または 選択します。
labels 検出機能によって返されたオブジェクトを説明するラベルの配列。 検出機能オプションに値を指定すると、このプロパティは空になります。 shouldEnableClassificationfalse に設定されています。

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

ユーザビリティとパフォーマンスの向上

最適なユーザー エクスペリエンスを実現するには、アプリで次のガイドラインを遵守してください。

  • オブジェクトの検出が成功するかどうかは、オブジェクトの視覚的な複雑さによって決まります。イン 検出するには、対象物の視覚的な特徴の数が少ない場合、 大きな部分を占めるようにしますユーザーに 検出したい種類のオブジェクトに適した入力をキャプチャします。
  • 分類を使用するときに、落下しないオブジェクトを検出したい場合 サポートされているカテゴリに明確に分類し、不明点に対する特別な処理を実装 説明します。

マテリアルデザインの ML を利用した特徴のパターン コレクション。

リアルタイム アプリケーションでストリーミング モードを使用する場合は、次のガイドラインに従ってください。 実現します。

  • ストリーミング モードでは複数オブジェクト検出を使用しないでください。ほとんどのデバイスは 適切なフレームレートを生成できます
  • 不要な場合は、分類を無効にします。
  • 動画フレームの処理には、検出機能の results(in:) 同期 API を使用します。発信 このメソッドは、 AVCaptureVideoDataOutputSampleBufferDelegate の <ph type="x-smartling-placeholder"></ph> 指定された動画から結果を同期的に取得する captureOutput(_, didOutput:from:) 関数 クリックします。<ph type="x-smartling-placeholder"></ph>のままにする AVCaptureVideoDataOutput さんの alwaysDiscardsLateVideoFramestrue として、検出機能の呼び出しをスロットリングします。新しい 検出機能の実行中に利用可能になった動画フレームは破棄されます。
  • 検出機能の出力を使用して、ディスプレイにグラフィックをオーバーレイする場合、 まず ML Kit から結果を取得してから、画像をレンダリングする 1 ステップでオーバーレイできますこれにより、ディスプレイ サーフェスにレンダリングされます。 各入力フレームに対して 1 回だけです。updatePreviewOverlayViewWithLastFrame をご覧ください。 をご覧ください。