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

כאן תוכלו ללמוד איך להשתמש בתמונות מרובות באפליקציות.

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

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

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

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

  • יצירת מסד נתונים ריק
ArAugmentedImageDatabase* ar_augmented_image_database = NULL;
ArAugmentedImageDatabase_create(ar_session, &ar_augmented_image_database);
  • לקרוא מקובץ מסד נתונים של תמונות. יש לעיין ב[AugmentedImage C sample app] בשביל 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() כמו שמוצג בהמשך. באפליקציה לדוגמה augmented_image_cאפשר לראות פונקציות במרחב השמות util.

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

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

// 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