ARCore が機械学習パイプラインで撮影したカメラフィードを使用して、インテリジェントな拡張現実エクスペリエンスを作成できます。 ARCore ML Kit サンプルでは、ML Kit と Google Cloud Vision API を使用して現実世界のオブジェクトを識別する方法を確認できます。 このサンプルでは、機械学習モデルを使用してカメラの視野内のオブジェクトを分類し、仮想シーン内のオブジェクトにラベルを付けます。
ARCore ML Kit サンプルは次のとおりです。 説明します。これは ml_kotlin サンプルとしても入手できます。 ARCore SDK の GitHub リポジトリ。
ARCore の CPU イメージを使用する
ARCore はデフォルトで、少なくとも 2 つの画像ストリーム セットをキャプチャします。
- 特徴認識と画像処理に使用される CPU 画像ストリーム。デフォルトでは、CPU イメージの解像度は VGA(640x480)です。ARCore は、必要に応じて追加の高解像度の画像ストリームを使用するように構成できます。
- GPU テクスチャ ストリーム。通常は解像度 1080p の高解像度テクスチャが含まれます。これは通常、ユーザー向けのカメラ プレビューとして使用されます。
これは、
Session.setCameraTextureName()
で指定された OpenGL テクスチャに格納されます。 SharedCamera.setAppSurfaces()
で指定された追加のストリーム。
CPU イメージサイズに関する考慮事項
デフォルトの VGA サイズの CPU ストリームが使用されても、ARCore はこのストリームを世界を理解するために使用するため、追加料金は発生しません。異なる解像度のストリームをリクエストすると、追加のストリームをキャプチャする必要が生じるため、コストが高くなる可能性があります。解像度が高いと、すぐにモデルのコストが高くなる可能性があるので注意してください。画像の幅と高さを 2 倍にすると、画像のピクセル数が 4 倍になります。
低解像度の画像でもモデルのパフォーマンスが高い場合は、画像をスケールダウンしたほうが良い場合があります。
追加の高解像度 CPU 画像ストリームを構成する
ML モデルのパフォーマンスは、入力として使用される画像の解像度に左右されることがあります。これらのストリームの解像度を調整するには、Session.setCameraConfig()
を使用して現在の CameraConfig
を変更し、Session.getSupportedCameraConfigs()
から有効な設定を選択します。
Java
CameraConfigFilter cameraConfigFilter = new CameraConfigFilter(session) // World-facing cameras only. .setFacingDirection(CameraConfig.FacingDirection.BACK); List<CameraConfig> supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter); // Select an acceptable configuration from supportedCameraConfigs. CameraConfig cameraConfig = selectCameraConfig(supportedCameraConfigs); session.setCameraConfig(cameraConfig);
Kotlin
val cameraConfigFilter = CameraConfigFilter(session) // World-facing cameras only. .setFacingDirection(CameraConfig.FacingDirection.BACK) val supportedCameraConfigs = session.getSupportedCameraConfigs(cameraConfigFilter) // Select an acceptable configuration from supportedCameraConfigs. val cameraConfig = selectCameraConfig(supportedCameraConfigs) session.setCameraConfig(cameraConfig)
CPU イメージを取得する
Frame.acquireCameraImage()
を使用して CPU イメージを取得します。
これらの画像は、不要になったらすぐに破棄してください。
Java
Image cameraImage = null; try { cameraImage = frame.acquireCameraImage(); // Process `cameraImage` using your ML inference model. } catch (NotYetAvailableException e) { // NotYetAvailableException is an exception that can be expected when the camera is not ready // yet. The image may become available on a next frame. } catch (RuntimeException e) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. handleAcquireCameraImageFailure(e); } finally { if (cameraImage != null) { cameraImage.close(); } }
Kotlin
// NotYetAvailableException is an exception that can be expected when the camera is not ready yet. // Map it to `null` instead, but continue to propagate other errors. fun Frame.tryAcquireCameraImage() = try { acquireCameraImage() } catch (e: NotYetAvailableException) { null } catch (e: RuntimeException) { // A different exception occurred, e.g. DeadlineExceededException, ResourceExhaustedException. // Handle this error appropriately. handleAcquireCameraImageFailure(e) } // The `use` block ensures the camera image is disposed of after use. frame.tryAcquireCameraImage()?.use { image -> // Process `image` using your ML inference model. }
CPU イメージを処理する
CPU イメージを処理するために、さまざまな ML ライブラリを使用できます。
- ML Kit: ML Kit は、デバイス上のオブジェクト検出とトラッキング API を提供します。
API に大まかな分類機能が組み込まれており、カスタム分類モデルを使用して、より狭い範囲のオブジェクトに対応することもできます。
InputImage.fromMediaImage
を使用して CPU イメージをInputImage
に変換します。 - Firebase の ML: Firebase は、クラウドでもデバイスでも機能する ML API を提供します。 Android で Firebase Auth と Functions を使用して Cloud Vision で画像に安全にラベルを付けるための Firebase ドキュメントをご覧ください。
AR シーンに結果を表示する
画像認識モデルは多くの場合、検出されたオブジェクトを表す中心点や境界ポリゴンを示すことで、検出されたオブジェクトを出力しています。
モデルから出力された境界ボックスの中心点または中心を使用して、検出されたオブジェクトにアンカーを取り付けることができます。Frame.hitTest()
を使用して、仮想シーン内のオブジェクトのポーズを推定します。
IMAGE_PIXELS
座標を VIEW
座標に変換します。
Java
// Suppose `mlResult` contains an (x, y) of a given point on the CPU image. float[] cpuCoordinates = new float[] {mlResult.getX(), mlResult.getY()}; float[] viewCoordinates = new float[2]; frame.transformCoordinates2d( Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates); // `viewCoordinates` now contains coordinates suitable for hit testing.
Kotlin
// Suppose `mlResult` contains an (x, y) of a given point on the CPU image. val cpuCoordinates = floatArrayOf(mlResult.x, mlResult.y) val viewCoordinates = FloatArray(2) frame.transformCoordinates2d( Coordinates2d.IMAGE_PIXELS, cpuCoordinates, Coordinates2d.VIEW, viewCoordinates ) // `viewCoordinates` now contains coordinates suitable for hit testing.
次の VIEW
座標を使用してヒットテストを実施し、その結果からアンカーを作成します。
Java
List<HitResult> hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]); HitResult depthPointResult = null; for (HitResult hit : hits) { if (hit.getTrackable() instanceof DepthPoint) { depthPointResult = hit; break; } } if (depthPointResult != null) { Anchor anchor = depthPointResult.getTrackable().createAnchor(depthPointResult.getHitPose()); // This anchor will be attached to the scene with stable tracking. // It can be used as a position for a virtual object, with a rotation prependicular to the // estimated surface normal. }
Kotlin
val hits = frame.hitTest(viewCoordinates[0], viewCoordinates[1]) val depthPointResult = hits.filter { it.trackable is DepthPoint }.firstOrNull() if (depthPointResult != null) { val anchor = depthPointResult.trackable.createAnchor(depthPointResult.hitPose) // This anchor will be attached to the scene with stable tracking. // It can be used as a position for a virtual object, with a rotation prependicular to the // estimated surface normal. }
パフォーマンスに関する注意事項
処理能力を節約し、エネルギー消費を抑えるには、次の推奨事項に従ってください。
- 受信フレームごとに ML モデルを実行するのではなく、代わりに、低フレームレートでオブジェクト検出を実行することを検討してください。
- 計算の複雑さを軽減するために、オンライン ML 推論モデルについて考えてみましょう。
次のステップ
- ML エンジニアリングのベスト プラクティスについて学習する。
- 責任ある AI への取り組みについて学習する。
- 「TensorFlow を使用した ML の基本」コースを学習する。