您可以使用 ARCore 在機器學習管線中擷取的攝影機畫面,打造智慧型擴增實境體驗。 ARCore ML Kit 範例示範如何使用 ML Kit 和 Google Cloud Vision API 辨識真實世界的物件。 這個範例會使用機器學習模型,將相機檢視畫面中的物件分類,並為虛擬場景中的物件加上標籤。
ARCore ML Kit 範例為 以 Kotlin 編寫而成這個程式庫也可做為 ml_kotlin 範例提供 ARCore SDK 中使用應用程式 GitHub 存放區
使用 ARCore 的 CPU 映像檔
根據預設,ARCore 至少會擷取兩組圖片串流:
- 用於特徵辨識和圖片處理的 CPU 映像檔串流。根據預設,CPU 映像檔的解析度為 VGA (640x480)。如有需要,您可以將 ARCore 設為使用額外解析度更高的圖片串流。
- GPU 紋理串流,內含高解析度紋理,通常解析度為 1080p。這項功能通常會做為面向使用者的相機預覽畫面使用。
此項目會儲存在
Session.setCameraTextureName()
指定的 OpenGL 紋理中。 SharedCamera.setAppSurfaces()
指定的任何其他串流。
CPU 映像檔大小注意事項
如果使用預設 VGA 大小的 CPU 串流,則不會產生額外費用,因為 ARCore 會使用這個串流內容讓使用者能夠理解。要求使用其他解析度的直播可能會耗費費用,因為系統必須擷取額外的串流。提醒您,較高的解析度可能會增加模型成本,例如:將圖片寬度和高度加倍,圖片像素量會加倍。
如果模型在解析度較低的圖片上仍可正常運作,建議您縮小圖片。
設定其他高解析度 CPU 映像檔串流
機器學習模型的效能可能會因為輸入的圖片解析度而異。如要調整這些串流的解析度,可以使用 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 Kit:ML Kit 提供裝置端物件偵測和追蹤 API。
API 內建粗略的分類器,而且也可以使用自訂分類模型來涵蓋較窄的物件網域。
使用
InputImage.fromMediaImage
將 CPU 映像檔轉換為InputImage
。 - Firebase 機器學習:Firebase 提供 Machine Learning API,可在雲端或裝置上運作。 請參閱 Firebase 說明文件,瞭解在 Android 上使用 Firebase 驗證和函式,透過 Cloud Vision 安全地為圖片加上標籤。
在 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. }
效能注意事項
請按照下列建議節省處理能力並減少能源消耗:
- 請避免在每個傳入影格上執行機器學習模型。建議改為以低影格速率執行物件偵測。
- 請考慮使用線上機器學習推論模型,降低運算複雜度。