ML Kit を使用すると、動画のフレーム間でオブジェクトを検出してトラックできます。
ML Kit に画像を渡すと、ML Kit は各画像について、最大 5 つの検出されたオブジェクトとその画像内での位置のリストを返します。動画ストリーム内のオブジェクトを検出する場合は、すべてのオブジェクトに ID を割り当てます。この ID を使用して、画像全体でオブジェクトをトラックできます。また、大まかなオブジェクト分類を有効にして、オブジェクトに幅広いカテゴリの説明をラベル付けすることもできます。
始める前に
- まだアプリに Firebase を追加していない場合は、スタートガイドの手順に沿って追加してください。
- ML Kit ライブラリを Podfile に含めます:
pod 'Firebase/MLVision', '6.25.0' pod 'Firebase/MLVisionObjectDetection', '6.25.0'
プロジェクトの Pod をインストールまたは更新した後に、.xcworkspace
を使用して Xcode プロジェクトを開くようにしてください。 - アプリに Firebase をインポートします。
Swift
import Firebase
Objective-C
@import Firebase;
1. オブジェクト検出を構成する
オブジェクトの検出とトラックを開始するには、まず VisionObjectDetector
インスタンスを作成し、必要に応じてデフォルトから変更する検出設定を指定します。
VisionObjectDetectorOptions
オブジェクトを使用して、ユースケースにオブジェクト検出を構成します。次の設定を変更できます。オブジェクト検出の設定 検出モード .stream
(デフォルト)|.singleImage
ストリーム モード(デフォルト)では、オブジェクト検出は低レイテンシで実行されますが、最初の数回の検出の呼び出しで不完全な結果(未指定の境界ボックスやカテゴリなど)が発生する可能性があります。また、ストリーム モードでは、検出でオブジェクトにトラッキング ID が割り当てられます。これを使用して、フレームをまたいでオブジェクトをトラックできます。このモードは、オブジェクトをトラックする場合、または動画ストリームをリアルタイムで処理する場合のように低レイテンシが重要な場合に使用します。
シングル イメージモードでは、検出されたオブジェクトの境界ボックスと(分類を有効にしている場合)カテゴリが利用可能になるまでオブジェクト検出を待機してから結果を返します。結果として、検出のレイテンシが潜在的に長くなります。また、シングル イメージ モードでは、トラッキング ID が割り当てられません。レイテンシが重要ではなく、部分的な結果を処理しない場合は、このモードを使用します。
複数のオブジェクトを検出してトラックする false
(デフォルト)|true
最大 5 つのオブジェクトを検出してトラックするか、最も目立つオブジェクトのみをトラックするか(デフォルト)。
オブジェクトを分類する false
(デフォルト)|true
検出されたオブジェクトをおまかなカテゴリに分類するかどうか。有効にすると、オブジェクト検出でファッション グッズ、食品、家庭用品、場所、植物または不明のカテゴリにオブジェクトを分類します。
オブジェクトの検出とトラッキングの API は主に、次の 2 つのユースケース用に最適化されています。
- カメラのファインダー内で最も目立つオブジェクトをライブで検出してトラッキングする
- 静止画像の複数のオブジェクトを検出する
これらのユースケースに API を構成するには以下を実行します。
Swift
// 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
Objective-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
FirebaseVisionObjectDetector
のインスタンスを取得します。Swift
let objectDetector = Vision.vision().objectDetector() // Or, to change the default settings: let objectDetector = Vision.vision().objectDetector(options: options)
Objective-C
FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetector]; // Or, to change the default settings: FIRVisionObjectDetector *objectDetector = [[FIRVision vision] objectDetectorWithOptions:options];
2. オブジェクト検出を実行する
オブジェクトを検出してトラックするには、各画像または動画フレームに対して次の手順を行います。ストリーム モードを有効にした場合は、CMSampleBufferRef
から VisionImage
オブジェクトを作成する必要があります。
UIImage
またはCMSampleBufferRef
を使用してVisionImage
オブジェクトを作成します。UIImage
を使用するには:- 必要に応じて、
imageOrientation
プロパティが.up
になるように画像を回転させます。 - 適切に回転させた
UIImage
を使用してVisionImage
オブジェクトを作成します。回転メタデータにはデフォルト値の.topLeft
を使用する必要があるため、値を指定しないでください。Swift
let image = VisionImage(image: uiImage)
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];
CMSampleBufferRef
を使用するには:-
VisionImageMetadata
オブジェクトを作成し、CMSampleBufferRef
バッファに格納されている画像データの向きを指定します。画像の向きは次のように取得します。
Swift
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 } }
Objective-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; } }
次に、メタデータ オブジェクトを作成します。
Swift
let cameraPosition = AVCaptureDevice.Position.back // Set to the capture device you used. let metadata = VisionImageMetadata() metadata.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition )
Objective-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];
VisionImage
オブジェクトと回転メタデータを使用してCMSampleBufferRef
オブジェクトを作成します。Swift
let image = VisionImage(buffer: sampleBuffer) image.metadata = metadata
Objective-C
FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer]; image.metadata = metadata;
- 必要に応じて、
VisionImage
をオブジェクト検出のいずれかのイメージ処理メソッドに渡します。非同期process(image:)
メソッドまたは同期results()
メソッドを使用できます。オブジェクトを非同期的に検出するには、次の手順を行います。
Swift
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. // ... }
Objective-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. // ... }];
オブジェクトを同期的に検出するには、次の手順を行います。
Swift
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 } // ...
Objective-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. // ...
イメージ プロセッサへの呼び出しが成功した場合は、非同期メソッドと同期メソッドのどちらを呼び出したかに応じて、
VisionObject
のリストを完了ハンドラに渡すか、リストを返します。各
VisionObject
には次のプロパティが含まれています。frame
画像内のオブジェクトの位置を示す CGRect
。trackingID
画像間でオブジェクトを識別する整数。シングル イメージ モードの nil。 classificationCategory
オブジェクトのおおまかなカテゴリ。オブジェクト検出で分類が有効になっていない場合、これは常に .unknown
です。confidence
オブジェクト分類の信頼値。オブジェクト検出で分類が有効になっていない場合、またはオブジェクトが不明と分類されている場合、これは nil
です。Swift
// 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 }
Objective-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; }
ユーザビリティとパフォーマンスの向上
最高のユーザー エクスペリエンスを提供するため、次のガイドラインに従ってアプリを作成してください。
- オブジェクトの検出に成功するかどうかは、オブジェクトの視覚的な複雑さによります。視覚的特徴の少ないオブジェクトは、検出対象の画像の大部分を占めていないと検出に成功しない可能性があります。検出するオブジェクトの種類に適した入力をキャプチャするためのガイダンスを用意する必要があります。
- 分類を使用するときに、サポート対象のカテゴリに該当しないオブジェクトを検出する場合は、未知のオブジェクトに対して特別な処理を実装してください。
また、[ML Kit Material Design ショーケース アプリ][showcase-link]{: .external } とマテリアル デザインの Patterns for machine learning-powered features のコレクションも確認してください。
リアルタイム アプリケーションでストリーミング モードを使用する場合は、最適なフレームレートを得るため、次のガイドラインに従ってください。
ストリーミング モードで複数のオブジェクト検出を使用しないでください。ほとんどのデバイスは十分なフレームレートを生成できません。
不要な場合は、分類を無効にします。
- 検出器の呼び出しのスロットル調整を行います。検出器の実行中に新しい動画フレームが使用可能になった場合は、そのフレームをドロップします。
- 検出器の出力を使用して入力画像の上にグラフィックスをオーバーレイする場合は、まず ML Kit から検出結果を取得し、画像とオーバーレイを 1 つのステップでレンダリングします。これにより、ディスプレイ サーフェスへのレンダリングは入力フレームごとに 1 回で済みます。例については、ショーケース サンプルアプリの previewOverlayView クラスと FIRDetectionOverlayView クラスをご覧ください。