Makine Öğrenimi modelleri için giriş olarak ARCore'u kullanma

ARCore'un makine öğrenimi ardışık düzeninde yakaladığı kamera feed'ini kullanarak akıllı bir artırılmış gerçeklik deneyimi oluşturabilirsiniz. ARCore ML Kit örneği, gerçek nesneleri tanımlamak için ML Kit'in ve Google Cloud Vision API'nin nasıl kullanılacağını gösterir. Örnek, kameranın görüş açısındaki nesneleri sınıflandırmak için bir makine öğrenimi modeli kullanır ve sanal sahnedeki nesneye bir etiket ekler.

ARCore ML Kiti örneği Kotlin'de yazılmıştır. Ayrıca ARCore SDK'sı GitHub deposunda ml_kotlin örnek uygulaması olarak da mevcuttur.

ARCore'un CPU görüntüsünü kullan

ARCore, varsayılan olarak en az iki görüntü akışı grubunu yakalar:

  • Özellik tanıma ve görüntü işleme için kullanılan bir CPU görüntü akışı. Varsayılan olarak, CPU görüntüsü VGA (640x480) çözünürlüğüne sahiptir. ARCore, gerekirse daha yüksek çözünürlüklü ek bir resim akışı kullanacak şekilde yapılandırılabilir.
  • Genellikle 1080p çözünürlükte, yüksek çözünürlüklü bir doku içeren bir GPU doku akışı. Bu genellikle kullanıcıya yönelik kamera önizlemesi olarak kullanılır. Bu, Session.setCameraTextureName() tarafından belirtilen OpenGL dokusunda saklanır.
  • SharedCamera.setAppSurfaces() tarafından belirtilen tüm ek akışlar.

CPU görüntüsü boyutuyla ilgili dikkat edilmesi gereken noktalar

ARCore bu akışı dünyayı anlamak için kullandığından, varsayılan VGA boyutundaki CPU akışı kullanılırsa ek ücret alınmaz. Ek bir akışın yakalanması gerekeceğinden farklı çözünürlükte bir akış isteğinde bulunmak pahalı olabilir. Daha yüksek bir çözünürlüğün modeliniz için kısa sürede pahalı olabileceğini unutmayın: Resmin genişliği ve yüksekliği iki katına çıkarıldığında resimdeki piksel miktarı dörde katlanır.

Modeliniz daha düşük çözünürlüklü bir resimde de iyi performans gösterebiliyorsa resmin ölçeğini küçültmek avantajlı olabilir.

Yüksek çözünürlüklü ek CPU resim akışı yapılandırma

ML modelinizin performansı, giriş olarak kullanılan görüntünün çözünürlüğüne bağlı olabilir. Bu akışların çözünürlüğü, Session.setCameraConfig() ile mevcut CameraConfig değeri değiştirilip Session.getSupportedCameraConfigs() içinden geçerli bir yapılandırma seçilerek ayarlanabilir.

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 görüntüsünü alma

CPU görüntüsünü Frame.acquireCameraImage() kullanarak alın. Bu resimler artık ihtiyaç duyulmadığında imha edilmelidir.

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 görüntüsünü işleyin

CPU görüntüsünü işlemek için çeşitli makine öğrenimi kitaplıkları kullanılabilir.

Sonuçları artırılmış gerçeklik (AR) sahnenizde görüntüleyin

Görüntü tanıma modelleri, algılanan nesneleri genellikle bir merkez noktası veya algılanan nesneyi temsil eden bir sınırlayıcı poligon belirterek çıkarır.

Modelden alınan sınırlayıcı kutunun merkez noktasını veya merkezini kullanarak, algılanan nesneye bir bağlayıcı eklemek mümkündür. Sanal sahnedeki bir nesnenin konumunu tahmin etmek için Frame.hitTest() aracını kullanın.

IMAGE_PIXELS koordinatlarını VIEW koordinatlarına dönüştürün:

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.

Bir isabet testi yapmak ve sonuçtan bir çapa oluşturmak için şu VIEW koordinatlarını kullanın:

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

Performansla ilgili konular

İşlem gücü tasarrufu yapmak ve daha az enerji tüketmek için aşağıdaki önerileri uygulayın:

  • ML modelinizi gelen her karede çalıştırmayın. Bunun yerine, nesne algılamayı düşük bir kare hızında çalıştırmayı düşünebilirsiniz.
  • Bilişimsel karmaşıklığı azaltmak için online bir makine öğrenimi çıkarım modeli kullanmayı düşünün.

Sonraki adımlar