تصاویر افزوده شده ARCore

1. بررسی اجمالی

ARCore پلتفرمی برای ساخت اپلیکیشن های واقعیت افزوده در اندروید است. Augmented Images به شما این امکان را می دهد که برنامه های واقعیت افزوده ایجاد کنید که می توانند تصاویر دو بعدی از پیش ثبت شده را در دنیای واقعی تشخیص دهند و محتوای مجازی را در بالای آنها لنگر بیاندازند.

این لبه کد شما را از طریق اصلاح یک برنامه نمونه ARCore موجود برای ترکیب تصاویر افزوده شده که در حال حرکت یا ثابت هستند راهنمایی می کند.

چیزی که خواهی ساخت

در این کد لبه، شما قصد دارید بر روی یک برنامه نمونه ARCore از قبل موجود بسازید. در پایان برنامه کد، برنامه شما قادر خواهد بود:

  • یک هدف تصویری را شناسایی کنید و یک پیچ و خم مجازی را روی هدف قرار دهید
  • هدف متحرک را تا زمانی که در دید دوربین است ردیابی کنید

6bc6605df89de525.gif

آیا این اولین بار است که یک برنامه ARCore می سازید؟

بله خیر

آیا قصد دارید نمونه کد را در این لبه کد بنویسید یا فقط می خواهید این صفحات را بخوانید؟

کد نمونه را بنویسید فقط این صفحات را بخوانید

چیزی که یاد خواهید گرفت

  • نحوه استفاده از تصاویر افزوده شده در ARCore در جاوا
  • چگونه می توان توانایی یک تصویر را برای تشخیص توسط ARCore اندازه گیری کرد
  • چگونه یک محتوای مجازی را روی یک تصویر ضمیمه کنیم و حرکت آن را ردیابی کنیم

پیش نیازها

برای تکمیل این کد لبه به سخت افزار و نرم افزار خاصی نیاز دارید.

الزامات سخت افزاری

الزامات نرم افزاری

  • ARCore APK 1.9.0 یا جدیدتر. این APK معمولاً به طور خودکار از طریق فروشگاه Play بر روی دستگاه نصب می شود
  • یک ماشین توسعه با Android Studio (نسخه 3.1 یا بالاتر)
  • دسترسی به اینترنت، زیرا در طول توسعه باید کتابخانه ها را دانلود کنید

اکنون که همه چیز را آماده کرده اید، بیایید شروع کنیم!

2. محیط توسعه را تنظیم کنید

SDK را دانلود کنید

ما با دانلود آخرین ARCore Android SDK از GitHub شروع می کنیم. آن را در مکان دلخواه خود از حالت فشرده خارج کنید. برای این نرم افزار کد، اولین نسخه SDK 1.18.1 است. پوشه به عنوان arcore-android-sdk-x.xx.x نامیده می شود، مقدار دقیق نسخه SDK مورد استفاده شما خواهد بود.

Android Studio را اجرا کنید و روی Open an Android Studio موجود پروژه کلیک کنید.

5fbf2b21609187cc.png

به این پوشه زیپ نشده بروید:

arcore-android-sdk-x.xx.x/samples/augmented_image_java

روی Open کلیک کنید.

منتظر بمانید تا Android Studio همگام سازی پروژه را تمام کند. اگر Android Studio شما اجزای مورد نیاز را ندارد، ممکن است با پیام Install missing platform and sync project ناموفق باشد. دستورالعمل ها را برای رفع مشکل دنبال کنید.

برنامه نمونه را اجرا کنید

اکنون که یک پروژه برنامه کاربردی ARCore دارید، بیایید آن را آزمایش کنیم.

دستگاه ARCore خود را به دستگاه توسعه متصل کنید و از منوی Run > Run 'app' برای اجرای نسخه اشکال زدایی در دستگاه استفاده کنید. در گفتگویی که از شما می خواهد انتخاب کنید از کدام دستگاه اجرا شود، دستگاه متصل را انتخاب کنید و روی OK کلیک کنید.

1aa2c6faa7ecdbd0.png

92e4c144a632b4ca.png

این پروژه نمونه از targetSdkVersion 28 استفاده می کند. اگر خطای ساخت مانند Failed to find Build Tools revision 28.0.3 دارید، دستورالعمل‌های توضیح داده شده در Android Studio را دنبال کنید تا نسخه مورد نیاز Android Build Tools را دانلود و نصب کنید.

اگر همه چیز موفقیت‌آمیز باشد، برنامه نمونه روی دستگاه راه‌اندازی می‌شود و از شما می‌خواهد تا اجازه دهید تصویر افزوده شده عکس و فیلم بگیرد. برای اعطای مجوز روی ALLOW ضربه بزنید.

با نمونه تصویر تست کنید

اکنون که محیط توسعه خود را راه‌اندازی کرده‌اید، می‌توانید برنامه را با دادن تصویری به آن آزمایش کنید.

در Android Studio، در پنجره Project ، به app > assets بروید و روی فایل default.jpg دوبار کلیک کنید تا باز شود.

9b333680e7b9f247.jpeg

دوربین دستگاه خود را به سمت تصویر زمین روی صفحه بگیرید و دستورالعمل ها را دنبال کنید تا تصویری را که در حال اسکن می کنید در خط تیره قرار دهید.

یک قاب تصویر در بالای تصویر قرار می گیرد، مانند این:

999e05ed35964f6e.png

در مرحله بعد، بهبودهای کوچکی در برنامه نمونه ایجاد خواهیم کرد.

3. یک مدل پیچ و خم را روی تصویر دو بعدی نمایش دهید

می توانید با نمایش یک مدل سه بعدی در بالای آن، بازی با تصاویر افزوده شده را شروع کنید.

دانلود مدل سه بعدی

برای این نرم افزار کد ما از " Circle Maze - Green " توسط Evol و دارای مجوز تحت CC-BY 3.0 استفاده می کنیم. من یک کپی از این مدل سه بعدی را در مخزن github این کد لبه ذخیره کردم که می توانید آن را اینجا پیدا کنید.

برای دانلود مدل و قرار دادن آن در اندروید استودیو مراحل زیر را دنبال کنید.

  1. به مخزن GitHub این کد لبه، دایرکتوری third_party بروید.
  2. روی GreenMaze_obj.zip کلیک کنید و روی دکمه دانلود کلیک کنید.

با این کار فایلی به نام GreenMaze_obj.zip دانلود می شود.

  1. در استودیو اندروید، پوشه green-maze را در زیر برنامه > دارایی ها > مدل ها ایجاد کنید
  2. GreenMaze_obj.zip را از حالت فشرده خارج کنید و محتوا را در این مکان کپی کنید: arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/assets/models/green-maze
  3. در Android Studio، به app > assets > models > green-maze بروید.

باید دو فایل در این پوشه وجود داشته باشد: GreenMaze.obj و GreenMaze.mtl .

a1f33a2d2d407e03.png

رندر مدل ماز

این مراحل را دنبال کنید تا مدل سه بعدی GreenMaze.obj در بالای تصویر دو بعدی موجود نمایش داده شود.

در AugmentedImageRenderer.java ، یک متغیر عضو به نام mazeRenderer را برای رندر کردن مدل ماز اضافه کنید. از آنجا که ماز باید به تصویر متصل شود، منطقی است که mazeRenderer در کلاس AugmentedImageRenderer قرار دهیم.

AugmentedImageRenderer.java

  // Add a member variable to hold the maze model.
  private final ObjectRenderer mazeRenderer = new ObjectRenderer();

در تابع createOnGlThread() ، GreenMaze.obj بارگیری کنید. برای سادگی، از بافت فریم مشابه بافت آن استفاده کنید.

AugmentedImageRenderer.java

  // Replace the definition of the createOnGlThread() function with the
  // following code, which loads GreenMaze.obj.
  public void createOnGlThread(Context context) throws IOException {

    mazeRenderer.createOnGlThread(
        context, "models/green-maze/GreenMaze.obj", "models/frame_base.png");
    mazeRenderer.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);

  }

تعریف تابع draw() را با زیر جایگزین کنید. این اندازه ماز را با اندازه تصویر شناسایی شده تنظیم می کند و آن را روی صفحه نمایش می دهد.

AugmentedImageRenderer.java

  // Adjust size of detected image and render it on-screen
  public void draw(
      float[] viewMatrix,
      float[] projectionMatrix,
      AugmentedImage augmentedImage,
      Anchor centerAnchor,
      float[] colorCorrectionRgba) {
    float[] tintColor =
        convertHexToColor(TINT_COLORS_HEX[augmentedImage.getIndex() % TINT_COLORS_HEX.length]);

    final float mazeEdgeSize = 492.65f; // Magic number of maze size
    final float maxImageEdgeSize = Math.max(augmentedImage.getExtentX(), augmentedImage.getExtentZ()); // Get largest detected image edge size

    Pose anchorPose = centerAnchor.getPose();

    float mazeScaleFactor = maxImageEdgeSize / mazeEdgeSize; // scale to set Maze to image size
    float[] modelMatrix = new float[16];

    // OpenGL Matrix operation is in the order: Scale, rotation and Translation
    // So the manual adjustment is after scale
    // The 251.3f and 129.0f is magic number from the maze obj file
    // You mustWe need to do this adjustment because the maze obj file
    // is not centered around origin. Normally when you
    // work with your own model, you don't have this problem.
    Pose mazeModelLocalOffset = Pose.makeTranslation(
                                -251.3f * mazeScaleFactor,
                                0.0f,
                                129.0f * mazeScaleFactor);
    anchorPose.compose(mazeModelLocalOffset).toMatrix(modelMatrix, 0);
    mazeRenderer.updateModelMatrix(modelMatrix, mazeScaleFactor, mazeScaleFactor/10.0f, mazeScaleFactor); // This line relies on a change in ObjectRenderer.updateModelMatrix later in this codelab.
    mazeRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
  }

اکنون، ماز باید در بالای تصویر default.jpg از زمین نمایش داده شود.

توجه: از آنجایی که شما کنترل کاملی روی این نمونه سه بعدی ندارید، کد بالا از چند عدد "جادویی" استفاده می کند. ابعاد مدل ماز 492.65 x 120 x 492.65 است که مرکز آن (251.3, 60, -129.0) است. دامنه مقادیر مختصات X، Y و Z رئوس آن به ترتیب [5.02، 497.67]، [0، 120] و [375.17-، 117.25] است. بنابراین، مقیاس مدل ماز باید image_size / 492.65 باشد. mazeModelLocalOffset به این دلیل معرفی شده است که مدل سه بعدی ماز حول مبدا (0، 0، 0) متمرکز نیست.

دیوار پیچ و خم هنوز کمی بلندتر از آن است که در بالای تصویر قرار بگیرد. یک تابع کمکی updateModelMatrix() ایجاد کنید که می تواند X, Y, Z را به طور ناهموار مقیاس کند تا ارتفاع Maze را 0.1 کند. توجه داشته باشید، باید updateModelMatrix(float[] modelMatrix, float scaleFactor) موجود را نگه دارید و تابع اضافه بار updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) به عنوان یک تابع جدید اضافه کنید.

common/rendering/ObjectRenderer.java

// Scale X, Y, Z coordinates unevenly
public void updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) {
    float[] scaleMatrix = new float[16];
    Matrix.setIdentityM(scaleMatrix, 0);
    scaleMatrix[0] = scaleFactorX;
    scaleMatrix[5] = scaleFactorY;
    scaleMatrix[10] = scaleFactorZ;
    Matrix.multiplyMM(this.modelMatrix, 0, modelMatrix, 0, scaleMatrix, 0);
}

کد را اجرا کنید. اکنون پیچ و خم باید کاملاً بالای تصویر قرار بگیرد.

772cbe2a8baef3ba.png

4. اندی را به ماز اضافه کنید

اکنون که یک پیچ و خم دارید، یک شخصیت برای حرکت در داخل آن اضافه کنید. از فایل andy.obj موجود در ARCore Android SDK استفاده کنید. بافت قاب تصویر را به عنوان بافت آن حفظ کنید، زیرا به نظر متفاوت از پیچ و خم سبز ارائه شده در بالای تصویر است.

در AugmentedImageRenderer.java ، یک ObjectRenderer خصوصی برای رندر Andy اضافه کنید.

AugmentedImageRenderer.java

// Render for Andy
  private final ObjectRenderer andyRenderer = new ObjectRenderer();

سپس، andyRenderer در انتهای createOnGlThread() مقداردهی اولیه کنید.

AugmentedImageRenderer.java

public void createOnGlThread(Context context) throws IOException {

    // Initialize andyRenderer
    andyRenderer.createOnGlThread(
        context, "models/andy.obj", "models/andy.png");
    andyRenderer.setMaterialProperties(0.0f, 3.5f, 1.0f, 6.0f);
  }

در نهایت، اندی را در بالای ماز در انتهای تابع draw() رندر کنید.

AugmentedImageRenderer.java

public void draw(
      float[] viewMatrix,
      float[] projectionMatrix,
      AugmentedImage augmentedImage,
      Anchor centerAnchor,
      float[] colorCorrectionRgba) {


    // Render Andy, standing on top of the maze
    Pose andyModelLocalOffset = Pose.makeTranslation(
        0.0f,
        0.1f,
        0.0f);
    anchorPose.compose(andyModelLocalOffset).toMatrix(modelMatrix, 0);
    andyRenderer.updateModelMatrix(modelMatrix, 0.05f); // 0.05f is a Magic number to scale
    andyRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);

  }

کد خود را اجرا کنید شما باید اندی را ببینید که در بالای پیچ و خم ایستاده است.

cb1e74569d7ace69.png

کیفیت تصویر هدف را تعیین کنید

ARCore برای تشخیص تصاویر به ویژگی های بصری متکی است. به دلیل تفاوت در کیفیت، همه تصاویر را نمی توان به راحتی تشخیص داد.

arcoreimg یک ابزار خط فرمان است که به شما این امکان را می دهد تا تعیین کنید که یک تصویر چقدر برای ARCore قابل تشخیص است. عددی بین 0 تا 100 را خروجی می دهد که تشخیص 100 ساده ترین است.

. در اینجا یک مثال است:

arcore-android-sdk-x.xx.x/tools/arcoreimg/macos$
$ ./arcoreimg  eval-img --input_image_path=/Users/username/maze.jpg
100

maze.jpg دارای مقدار 100 است، بنابراین ARCore آن را به راحتی تشخیص می دهد.

5. اختیاری: اندی را در پیچ و خم حرکت دهید

در نهایت، می‌توانید کدی اضافه کنید تا اندی در پیچ و خم حرکت کند. به عنوان مثال، از موتور منبع باز Physics، jBullet برای انجام شبیه سازی فیزیک استفاده کنید. اگر این قسمت را رد کنید کاملاً خوب است.

PhysicsController.java را دانلود کنید و آن را به پروژه خود در دایرکتوری اضافه کنید

arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/java/com/google/ar/core/examples/java/augmentedimage/

در Android Studio، GreenMaze.obj را به فهرست دارایی های پروژه اضافه کنید تا در زمان اجرا بارگذاری شود. GreenMaze.obj را از app > assets > models > green-maze در app > assets کپی کنید.

وابستگی های زیر را به فایل build.gradle برنامه اضافه کنید.

app/build.gradle

    // jbullet library
    implementation 'cz.advel.jbullet:jbullet:20101010-1'

یک متغیر andyPose برای ذخیره موقعیت ژست فعلی اندی تعریف کنید.

AugmentedImageRenderer.java

  // Create a new pose for the Andy
  private Pose andyPose = Pose.IDENTITY;

AugmentedImageRenderer.java تغییر دهید تا Andy با استفاده از متغیر andyPose جدید رندر شود.

AugmentedImageRenderer.java

public void draw(
      float[] viewMatrix,
      float[] projectionMatrix,
      AugmentedImage augmentedImage,
      Anchor centerAnchor,
      float[] colorCorrectionRgba) {

    // Use these code to replace previous code for rendering the Andy object
    // 
    // Adjust the Andy's rendering position
    // The Andy's pose is at the maze's vertex's coordinate
    Pose andyPoseInImageSpace = Pose.makeTranslation(
        andyPose.tx() * mazeScaleFactor,
        andyPose.ty() * mazeScaleFactor,
        andyPose.tz() * mazeScaleFactor);

    anchorPose.compose(andyPoseInImageSpace).toMatrix(modelMatrix, 0);
    andyRenderer.updateModelMatrix(modelMatrix, 0.05f);
    andyRenderer.draw(viewMatrix, projectionMatrix, colorCorrectionRgba, tintColor);
  }

برای دریافت به‌روزرسانی‌های اندی پوز، یک تابع ابزار جدید، updateAndyPose() اضافه کنید.

AugmentedImageRenderer.java

  // Receive Andy pose updates
  public void updateAndyPose(Pose pose) {
    andyPose = pose;
  }

در AugmentedImageActivity.java ، یک شی PhysicsController ایجاد کنید که از موتور فیزیک JBullet برای مدیریت تمام توابع مرتبط با فیزیک استفاده می کند.

AugmentedImageActivity.java

import com.google.ar.core.Pose;

  // Declare the PhysicsController object
  private PhysicsController physicsController;

در موتور فیزیک، ما در واقع از یک توپ صلب برای نشان دادن اندی استفاده می کنیم و با استفاده از ژست توپ، ژست اندی را به روز می کنیم. هر زمان که برنامه تصویری را تشخیص داد، با PhysicsController تماس بگیرید تا فیزیک را به روز کنید. برای حرکت دادن توپ در دنیای واقعی، از جاذبه دنیای واقعی استفاده کنید تا توپ را در پیچ و خم حرکت دهید.

AugmentedImageActivity.java

// Update the case clause for TRACKING to call PhysicsController
// whenever the app recognizes an image
  private void drawAugmentedImages(

    ...

        case TRACKING:
          // Switch to UI Thread to update View
          this.runOnUiThread(
              new Runnable() {
                @Override
                public void run() {
                  fitToScanView.setVisibility(View.GONE);
                }
              });

          // Create a new anchor for newly found images
          if (!augmentedImageMap.containsKey(augmentedImage.getIndex())) {
            Anchor centerPoseAnchor = augmentedImage.createAnchor(augmentedImage.getCenterPose());
            augmentedImageMap.put(
                augmentedImage.getIndex(), Pair.create(augmentedImage, centerPoseAnchor));

            physicsController = new PhysicsController(this);
          } else {
            Pose ballPose = physicsController.getBallPose();
            augmentedImageRenderer.updateAndyPose(ballPose);


            // Use real world gravity, (0, -10, 0), as gravity
            // Convert to Physics world coordinate(maze mesh has to be static)
            // Use the converted coordinate as a force to move the ball
            Pose worldGravityPose = Pose.makeTranslation(0, -10f, 0);
            Pose mazeGravityPose = augmentedImage.getCenterPose().inverse().compose(worldGravityPose);
            float mazeGravity[] = mazeGravityPose.getTranslation();
            physicsController.applyGravityToBall(mazeGravity);

            physicsController.updatePhysics();
          }
          break;

برنامه را اجرا کنید. اکنون وقتی تصویر را کج می کنید، اندی باید به طور واقع بینانه حرکت کند.

مثال زیر از تلفن دیگری برای نمایش تصویر استفاده می‌کند، با خیال راحت از هر چیزی که برای شما راحت است، مانند تبلت، یا جلد کتاب چاپ شده یا فقط یک کاغذ چاپ شده که روی یک شی صاف وصل شده است، استفاده کنید.

2f0df284705d3704.gif

همین! از تلاش برای عبور اندی از پیچ و خم لذت ببرید. نکته: وقتی تصویر مورد نظر را به سمت پایین نگه دارید، پیدا کردن خروجی آسان تر است.

6. تبریک می گویم

تبریک می گوییم، شما به پایان این کد لبه رسیده اید، و بدین ترتیب:

  • یک نمونه جاوا ARCore AugmentedImage ساخته و اجرا شد.
  • نمونه را به روز کرد تا یک مدل پیچ و خم را روی تصویر در مقیاس مناسب نمایش دهد.
  • از ژست تصویر برای انجام کاری سرگرم کننده استفاده کرد.

اگر مایلید به کد کامل مراجعه کنید، می توانید آن را از اینجا دانلود کنید.

آیا از انجام این کد لبه لذت بردید؟

بله خیر

آیا در انجام این کد لبه چیز مفیدی یاد گرفتید؟

بله خیر

آیا ساختن برنامه را در این کد لبه کامل کردید؟

بله خیر

آیا قصد دارید تا 6 ماه آینده یک برنامه ARCore بسازید؟

بله شاید خیر