ARCore를 머신러닝 모델의 입력으로 사용

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder">

ARCore가 머신러닝 파이프라인에서 캡처한 카메라 피드를 사용하여 지능형 증강 현실 환경을 만들 수 있습니다. ARCore ML Kit 샘플ML KitGoogle Cloud Vision API를 사용하여 실제 객체를 식별하는 방법을 보여줍니다. 이 샘플은 머신러닝 모델을 사용하여 카메라의 뷰에서 객체를 분류하고 가상 장면의 객체에 라벨을 연결합니다.

ARCore ML Kit 샘플은 다음과 같습니다. 살펴봤습니다 또한 ml_kotlin 샘플로도 사용할 수 있습니다. ARCore SDK의 앱 GitHub 저장소

ARCore의 CPU 이미지 사용

ARCore는 기본적으로 최소 두 세트의 이미지 스트림을 캡처합니다.

  • 특징 인식 및 이미지 처리에 사용되는 CPU 이미지 스트림입니다. 기본적으로 CPU 이미지의 해상도는 VGA (640x480)입니다. 필요한 경우 고해상도 이미지 스트림을 추가로 사용하도록 ARCore를 구성할 수 있습니다.
  • GPU 텍스처 스트림: 일반적으로 해상도 1080p의 고해상도 텍스처를 포함합니다. 일반적으로 사용자 대상 카메라 미리보기로 사용됩니다. 이는 Session.setCameraTextureName()에서 지정한 OpenGL 텍스처에 저장됩니다.
  • SharedCamera.setAppSurfaces()에서 지정한 추가 스트림입니다.

CPU 이미지 크기 고려사항

ARCore는 세계 이해를 위해 이 스트림을 사용하기 때문에 기본 VGA 크기의 CPU 스트림을 사용하는 경우 추가 비용이 발생하지 않습니다. 다른 해상도로 스트림을 요청하면 추가 스트림을 캡처해야 하므로 비용이 많이 들 수 있습니다. 해상도가 높을수록 모델에 비용이 빠르게 증가할 수 있습니다. 이미지의 너비와 높이를 두 배로 늘리면 이미지의 픽셀 수도 4배로 늘어납니다.

모델이 저해상도 이미지에서 여전히 잘 작동할 수 있다면 이미지를 축소하는 것이 유리할 수 있습니다.

추가적인 고해상도 CPU 이미지 스트림 구성

ML 모델의 성능은 입력으로 사용된 이미지의 해상도에 따라 달라질 수 있습니다. 이러한 스트림의 해상도는 Session.setCameraConfig()를 사용하여 현재 CameraConfig를 변경하고 Session.getSupportedCameraConfigs()에서 유효한 구성을 선택하여 조정할 수 있습니다.

자바

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 이미지를 가져옵니다. 이러한 이미지는 더 이상 필요하지 않으면 즉시 폐기해야 합니다.

자바

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 이미지를 처리하기 위해 다양한 머신러닝 라이브러리를 사용할 수 있습니다.

AR 장면에 결과 표시하기

이미지 인식 모델은 중심점 또는 감지된 객체를 나타내는 경계 다각형을 표시하여 감지된 객체를 출력하는 경우가 많습니다.

모델에서 출력된 경계 상자의 중심점 또는 중심을 사용하여 감지된 객체에 앵커를 연결할 수 있습니다. Frame.hitTest()를 사용하여 가상 장면에 있는 객체의 포즈를 추정합니다.

IMAGE_PIXELS 좌표를 VIEW 좌표로 변환합니다.

자바

// 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 좌표를 사용하여 히트 테스트를 실행하고 결과에서 앵커를 만듭니다.

자바

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 추론 모델을 사용해 계산 복잡성을 줄여보세요.

다음 단계