מדריך למפתחים של תמונות משופרות ל-Android NDK

איך משתמשים בתמונות משופר באפליקציות שלכם

דרישות מוקדמות

לפני שממשיכים, חשוב להבין את המושגים הבסיסיים של AR ואת האופן שבו מגדירים סשן ARCore.

יצירת מסד נתונים של תמונות

יוצרים ArAugmentedImageDatabase כדי לאחסן תמונות עזר. יש שתי דרכים לעשות זאת:

  • יצירת מסד נתונים ריק
ArAugmentedImageDatabase* ar_augmented_image_database = NULL;
ArAugmentedImageDatabase_create(ar_session, &ar_augmented_image_database);
  • קריאה מקובץ של מאגר תמונות. אפשר לעיין באפליקציית הדוגמה ב-C‏ AugmentedImage עבור util::LoadFileFromAssetManager.
std::string database_buffer;
util::LoadFileFromAssetManager(asset_manager_, "sample_database.imgdb",
                               &database_buffer);
uint8_t* raw_buffer = reinterpret_cast<uint8_t*>(&database_buffer.front());

ArAugmentedImageDatabase* ar_augmented_image_database = NULL;
const ArStatus status = ArAugmentedImageDatabase_deserialize(
    ar_session, raw_buffer, database_buffer.size(),
    &ar_augmented_image_database);

אפשר ליצור קבצים של מסדי נתונים באמצעות כלי התמונות או באמצעות קריאה ל-ArAugmentedImageDatabase_serialize().

הוספת תמונות למסד נתונים

השלב הזה הוא אופציונלי אם קובץ התמונות של ההפניות הרצויות כבר נטען מקובץ מסד הנתונים. כדי להוסיף תמונה בזמן הריצה, צריך להפעיל את ArAugmentedImageDatabase_addImage() כפי שמתואר בהמשך. פונקציות במרחב השמות util מפורטות באפליקציית הדוגמה augmented_image_c.

int32_t width, height, stride, index;
uint8_t* image_pixel_buffer = nullptr;
constexpr const char kSampleImageName[] = "default.jpg";
bool load_image_result = util::LoadImageFromAssetManager(
    kSampleImageName, &width, &height, &stride, &image_pixel_buffer);

uint8_t* grayscale_buffer = nullptr;
util::ConvertRgbaToGrayscale(image_pixel_buffer, width, height, stride,
                             &grayscale_buffer);

int32_t grayscale_stride = stride / 4;
const ArStatus status = ArAugmentedImageDatabase_addImage(
    ar_session_, ar_augmented_image_database, kSampleImageName,
    grayscale_buffer, width, height, grayscale_stride, &index);

// If the physical size of the image is known, you can instead use
//     ArStatus ArAugmentedImageDatabase_addImageWithPhysicalSize
// This will improve the initial detection speed. ARCore will still actively
// estimate the physical size of the image as it is viewed from multiple
// viewpoints.

delete[] image_pixel_buffer;
delete[] grayscale_buffer;

הערכים index ו-name משמשים בהמשך לזיהוי תמונת העזר שזוהתה.

הפעלת מעקב אחר תמונות

כדי להגדיר את סשן ARCore למעקב אחר תמונות, צריך לרשום את מסד הנתונים של התמונות:

ArConfig_setAugmentedImageDatabase(ar_session_, ar_config,
                                   ar_augmented_image_database);
const ArStatus status = ArSession_configure(ar_session_, ar_config);

במהלך הסשן, ARCore משתמשת בנקודות תכונה מהתמונה במצלמה כדי להתאים אותן לנקודות במסד הנתונים של התמונות.

חיפוש תמונות עם תוספות במציאות רבודה בסשן AR

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

// Update loop, in onDrawFrame
ArTrackableList* updated_image_list = nullptr;
ArTrackableList_create(ar_session_, &updated_image_list);
ArFrame_getUpdatedTrackables(
    ar_session_, ar_frame_, AR_TRACKABLE_AUGMENTED_IMAGE, updated_image_list);

int32_t image_list_size;
ArTrackableList_getSize(ar_session_, updated_image_list, &image_list_size);

for (int i = 0; i < image_list_size; ++i) {
  ArTrackable* ar_trackable = nullptr;
  ArTrackableList_acquireItem(ar_session_, updated_image_list, i,
                              &ar_trackable);
  ArAugmentedImage* image = ArAsAugmentedImage(ar_trackable);

  ArTrackingState tracking_state;
  ArTrackable_getTrackingState(ar_session_, ar_trackable, &tracking_state);

  int image_index;
  ArAugmentedImage_getIndex(ar_session_, image, &image_index);

  if (tracking_state == AR_TRACKING_STATE_TRACKING) {
    util::ScopedArPose scopedArPose(ar_session_);
    ArAugmentedImage_getCenterPose(ar_session_, image,
                                   scopedArPose.GetArPose());

    ArAnchor* image_anchor = nullptr;
    const ArStatus status = ArTrackable_acquireNewAnchor(
        ar_session_, ar_trackable, scopedArPose.GetArPose(), &image_anchor);

    // For example, you can now render content at the image anchor, choosing
    // content based on the image index (or name).
  }
}

תמיכה בתרחישי שימוש שונים

כש-ARCore מזהה תמונה משולבת, היא יוצרת Trackable לאותה תמונה משולבת ומגדירה את ArTrackingState לערך TRACKING ואת ArAugmentedImageTrackingMethod לערך FULL_TRACKING. כשהתמונה שבמעקב יוצאת מהשדה החזותי של המצלמה, ARCore ממשיכה להגדיר את ArTrackingState כ-TRACKING, אבל משנה את ArAugmentedImageTrackingMethod ל-LAST_KNOWN_POSE תוך המשך מתן המידע על הכיוון והמיקום של התמונה.

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

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

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

תרחיש לדוגמה תמונה קבועה תמונה מונפשת
דוגמה פוסטר שתלוי על קיר מודעה בצד של אוטובוס
אפשר
להתייחס לתנוחה כתקפה אם
ArTrackingState == TRACKING ArTrackingState == TRACKING
וגם
ArAugmentedImageTrackingMethod == FULL_TRACKING