מדריך למפתחים בנושא תמונות מורחבות ב-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 מחפשת תמונות על ידי התאמה בין נקודות הפיצ'רים מתמונת המצלמה לבין אלה שבמסד הנתונים של התמונות.

כדי לקבל את התמונות התואמות, צריך לבצע סקר לגבי AugmentedImages מעודכנים בלולאת עדכון המסגרת.

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 ל-TRACKING ול-TrackingMethod ל-FULL_TRACKING. כשהתמונה שבמעקב יוצאת מתצוגת המצלמה, מערכת ARCore משנה את TrackingMethod ל-LAST_KNOWN_POSE ועדיין ממשיכה לספק את הכיוון והמיקום של התמונה.

האפליקציה צריכה להשתמש בספירות האלה באופן שונה, בהתאם לתרחיש השימוש המיועד.

  • תמונות מתוקנות. ברוב תרחישי השימוש בתמונות שמתוקנות במיקום (כלומר, לא צפויות לזוז) אפשר פשוט להשתמש בפונקציה TrackingState כדי לקבוע אם התמונה זוהתה ואם המיקום שלה ידוע. אפשר להתעלם מ-TrackingMethod.

  • תמונות זזות. אם האפליקציה שלכם צריכה לעקוב אחרי תמונה נעה, כדאי להשתמש ב-TrackingState וב-TrackingMethod כדי לקבוע אם התמונה זוהתה ואם המיקום שלה ידוע.

תרחיש לדוגמה תמונה מתוקנת התמונה זזה
דוגמה פוסטר שתלוי על קיר פרסומת לצד אוטובוס
התנוחה יכולה להיחשב תקפה
כאשר
TrackingState == TRACKING TrackingState == TRACKING
ו-
TrackingMethod == FULL_TRACKING

כדאי לעיין גם בפרטים הבאים