适用于 Android 的增强图像开发者指南

了解如何在您自己的应用中使用增强图片。

前提条件

在继续操作之前,请确保您了解基本 AR 概念以及如何配置 ARCore 会话

创建图片数据库

每个图片数据库最多可存储 1,000 张图片的信息。

您可以通过以下两种方式创建 AugmentedImageDatabase

  • 加载已保存的图片数据库。然后,您可以根据需要添加更多参考图片。
  • 创建一个新的空数据库。然后,逐一添加参考图片。

加载已保存的图片数据库

使用 AugmentedImageDatabase.deserialize() 加载现有图片数据库:

Java

AugmentedImageDatabase imageDatabase;
try (InputStream inputStream = this.getAssets().open("example.imgdb")) {
  imageDatabase = AugmentedImageDatabase.deserialize(session, inputStream);
} catch (IOException e) {
  // The Augmented Image database could not be deserialized; handle this error appropriately.
}

Kotlin

val imageDatabase = this.assets.open("example.imgdb").use {
  AugmentedImageDatabase.deserialize(session, it)
}

您可以在开发期间使用 arcoreimg 命令行工具创建图片数据库,也可以对包含已加载到内存中的数据库调用 AugmentedImageDatabase.serialize() 来创建图片数据库。

创建一个新的空数据库

如需在运行时创建空图片数据库,请使用 AugmentedImageDatabase 构造函数

Java

AugmentedImageDatabase imageDatabase = new AugmentedImageDatabase(session);

Kotlin

val imageDatabase = AugmentedImageDatabase(session)

向现有数据库添加图片

为每张图片调用 AugmentedImageDatabase.addImage(),并指定可选的 widthInMeters,以将图片添加到图片数据库。

Java

Bitmap bitmap;
try (InputStream bitmapString = getAssets().open("dog.jpg")) {
  bitmap = BitmapFactory.decodeStream(bitmapString);
} catch (IOException e) {
  // The bitmap could not be found in assets; handle this error appropriately.
  throw new AssertionError("The bitmap could not be found in assets.", e);
}

// If the physical size of the image is not known, use addImage(String, Bitmap) instead, at the
// expense of an increased image detection time.
float imageWidthInMeters = 0.10f; // 10 cm
int dogIndex = imageDatabase.addImage("dog", bitmap, imageWidthInMeters);

Kotlin

val bitmap = assets.open("dog.jpg").use { BitmapFactory.decodeStream(it) }
// If the physical size of the image is not known, use addImage(String, Bitmap) instead, at the
// expense of an increased image detection time.
val imageWidthInMeters = 0.10f // 10 cm
val dogIndex = imageDatabase.addImage("dog", bitmap, imageWidthInMeters)

返回的索引稍后可用于确定检测到哪个参考图片。

启用图片跟踪

将会话配置设置为使用所需图片数据库配置的会话配置,以便配置 ARCore 会话以开始跟踪图片:

Java

Config config = new Config(session);
config.setAugmentedImageDatabase(imageDatabase);
session.configure(config);

Kotlin

val config = Config(session)
config.augmentedImageDatabase = imageDatabase
session.configure(config)

在会话期间,ARCore 会将相机图像中的特征点与图片数据库中的特征点进行匹配,以查找图片。

如需获取匹配的图片,请在帧更新循环中轮询更新后的 AugmentedImage

Java

Collection<AugmentedImage> updatedAugmentedImages =
    frame.getUpdatedTrackables(AugmentedImage.class);
for (AugmentedImage img : updatedAugmentedImages) {
  if (img.getTrackingState() == TrackingState.TRACKING) {
    // Use getTrackingMethod() to determine whether the image is currently
    // being tracked by the camera.
    switch (img.getTrackingMethod()) {
      case LAST_KNOWN_POSE:
        // The planar target is currently being tracked based on its last
        // known pose.
        break;
      case FULL_TRACKING:
        // The planar target is being tracked using the current camera image.
        break;
      case NOT_TRACKING:
        // The planar target isn't been tracked.
        break;
    }

    // You can also check which image this is based on img.getName().
    if (img.getIndex() == dogIndex) {
      // TODO: Render a 3D version of a dog in front of img.getCenterPose().
    } else if (img.getIndex() == catIndex) {
      // TODO: Render a 3D version of a cat in front of img.getCenterPose().
    }
  }
}

Kotlin

val updatedAugmentedImages = frame.getUpdatedTrackables(AugmentedImage::class.java)

for (img in updatedAugmentedImages) {
  if (img.trackingState == TrackingState.TRACKING) {
    // Use getTrackingMethod() to determine whether the image is currently
    // being tracked by the camera.
    when (img.trackingMethod) {
      AugmentedImage.TrackingMethod.LAST_KNOWN_POSE -> {
        // The planar target is currently being tracked based on its last known pose.
      }
      AugmentedImage.TrackingMethod.FULL_TRACKING -> {
        // The planar target is being tracked using the current camera image.
      }
      AugmentedImage.TrackingMethod.NOT_TRACKING -> {
        // The planar target isn't been tracked.
      }
    }

    // You can also check which image this is based on AugmentedImage.getName().
    when (img.index) {
      dogIndex -> TODO("Render a 3D version of a dog at img.getCenterPose()")
      catIndex -> TODO("Render a 3D version of a cat at img.getCenterPose()")
    }
  }
}

支持不同的用例

当 ARCore 检测到增强图像时,它会为该增强图像创建 Trackable,并将 TrackingState 设置为 TRACKINGTrackingMethod 设置为 FULL_TRACKING。当被跟踪的图片移出相机视野时,ARCore 会将 TrackingMethod 更改为 LAST_KNOWN_POSE,同时继续提供图片的方向和位置。

您的应用应根据预期用例以不同的方式使用这些枚举。

  • 修复了图片。大多数涉及固定图片(即预计不会移动)的用例都可以简单地使用 TrackingState 来确定是否已检测到图片以及是否已知其位置。TrackingMethod 可以忽略。

  • 移动图片。如果您的应用需要跟踪移动图片,请同时使用 TrackingStateTrackingMethod 来确定是否已检测到图片以及是否已知其位置。

使用场景 固定图片 移动图片
示例 墙上挂着的海报 公交车车身上的广告
当以下条件成立时,可以
将姿势视为有效:
TrackingState == TRACKING TrackingState == TRACKING

TrackingMethod == FULL_TRACKING

另请参阅