Hình ảnh tăng cường ARCore

1. Tổng quan

ARCore là nền tảng tạo các ứng dụng thực tế tăng cường trên Android. Hình ảnh tăng cường cho phép bạn tạo những ứng dụng thực tế tăng cường (AR) có khả năng nhận dạng hình ảnh 2D đã đăng ký trước trong thế giới thực và cố định nội dung ảo trên đó.

Lớp học lập trình này hướng dẫn bạn chỉnh sửa ứng dụng mẫu ARCore hiện có để tích hợp Hình ảnh tăng cường đang di chuyển hoặc cố định tại chỗ.

Sản phẩm bạn sẽ tạo ra

Trong lớp học lập trình này, bạn sẽ xây dựng dựa trên một ứng dụng mẫu ARCore có sẵn. Khi kết thúc lớp học lập trình, ứng dụng của bạn sẽ có thể:

  • Phát hiện mục tiêu hình ảnh và đính kèm một mê cung ảo vào mục tiêu
  • Theo dõi mục tiêu di chuyển miễn là mục tiêu đó nằm trong góc nhìn của camera

6bc6605df89de525.gif

Đây có phải là lần đầu tiên bạn tạo ứng dụng ARCore?

Không

Bạn dự định viết mã mẫu trong lớp học lập trình này hay chỉ muốn đọc các trang này?

Viết mã mẫu Chỉ cần đọc những trang này

Kiến thức bạn sẽ học được

  • Cách sử dụng Hình ảnh tăng cường trong ARCore trong Java
  • Cách đánh giá khả năng ARCore nhận dạng hình ảnh
  • Cách đính kèm nội dung ảo vào hình ảnh và theo dõi chuyển động của hình ảnh đó

Điều kiện tiên quyết

Bạn cần có phần cứng và phần mềm cụ thể để hoàn tất lớp học lập trình này.

Yêu cầu về phần cứng

Yêu cầu về phần mềm

  • ARCore APK 1.9.0 trở lên. Tệp APK này thường được tự động cài đặt trên thiết bị thông qua Cửa hàng Play
  • Máy phát triển có Android Studio (phiên bản 3.1 trở lên)
  • Quyền truy cập Internet, vì bạn sẽ cần phải tải thư viện xuống trong quá trình phát triển

Giờ thì mọi thứ đã sẵn sàng. Hãy bắt đầu nào!

2. Thiết lập môi trường phát triển

Tải SDK xuống

Chúng ta sẽ bắt đầu bằng cách tải SDK ARCore Android mới nhất xuống từ GitHub. Giải nén tệp này đến vị trí bạn muốn. Đối với lớp học lập trình này, phiên bản SDK cũ nhất là 1.18.1. Thư mục này sẽ được gọi là arcore-android-sdk-x.xx.x, giá trị chính xác sẽ là phiên bản SDK mà bạn sử dụng.

Chạy Android Studio rồi nhấp vào Open an existing Android Studio project (Mở một dự án hiện có trong Android Studio).

5fbf2b21609187cc.pngS

Chuyển đến thư mục đã giải nén này:

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

Nhấp vào Mở.

Chờ Android Studio hoàn tất quá trình đồng bộ hoá dự án. Nếu Android Studio không có các thành phần bắt buộc, thì có thể Android Studio sẽ không hiện thông báo Install missing platform and sync project. Làm theo hướng dẫn để khắc phục sự cố.

Chạy ứng dụng mẫu

Bây giờ, bạn đã có một dự án ứng dụng ARCore đang hoạt động, hãy chạy thử dự án đó.

Kết nối thiết bị ARCore với máy phát triển và sử dụng trình đơn Run > (Chạy >) Chạy "app" (ứng dụng) để chạy phiên bản gỡ lỗi trên thiết bị. Trong hộp thoại nhắc bạn chọn thiết bị sẽ chạy, hãy chọn thiết bị được kết nối rồi nhấp vào OK.

1aa2c6faa7ecdbd0.pngs

92e4c144a632b4ca.png.

Dự án mẫu này sử dụng targetSdkVersion 28. Nếu bạn gặp lỗi bản dựng như Failed to find Build Tools revision 28.0.3, hãy làm theo hướng dẫn được mô tả trong Android Studio để tải xuống và cài đặt phiên bản được yêu cầu của Công cụ xây dựng Android.

Nếu mọi thứ đều thành công, ứng dụng mẫu sẽ khởi chạy trên thiết bị và nhắc bạn cấp quyền cho phép Hình ảnh tăng cường chụp ảnh và quay video. Nhấn vào CHO PHÉP để cấp quyền.

Kiểm thử bằng hình ảnh mẫu

Giờ đây, khi đã thiết lập môi trường phát triển, bạn có thể kiểm thử ứng dụng bằng cách cung cấp hình ảnh để xem.

Quay lại Android Studio, trong cửa sổ Project (Dự án), chuyển đến app > nội dung rồi nhấp đúp vào tệp default.jpg để mở tệp đó.

9b33680e7b9f247.jpeg

Hướng máy ảnh của thiết bị vào hình ảnh của Earth trên màn hình và làm theo hướng dẫn sao cho hình ảnh mà bạn đang quét khớp với hình chữ thập.

Một khung hình ảnh sẽ phủ lên trên hình ảnh, như sau:

999e05ed35964f6e.pngS

Tiếp theo, chúng ta sẽ thực hiện những cải tiến nhỏ đối với ứng dụng mẫu.

3. Hiển thị mô hình mê cung trên Hình ảnh 2D

Bạn có thể bắt đầu phát bằng Hình ảnh tăng cường bằng cách cho thấy một mô hình 3D lên trên hình ảnh đó.

Tải mô hình 3D xuống

Đối với lớp học lập trình này, chúng ta sẽ sử dụng "Mê cung hình tròn – Xanh lục" bởi Evol và được cấp phép theo CC-BY 3.0. Tôi đã lưu trữ một bản sao của mô hình 3D này trong kho lưu trữ github của lớp học lập trình này. Bạn có thể tìm thấy bản sao đó tại đây.

Hãy làm theo các bước sau để tải mô hình xuống và thêm vào Android Studio.

  1. Chuyển đến kho lưu trữ GitHub của lớp học lập trình này, thư mục bên thứ ba.
  2. Nhấp vào GreenMaze_obj.zip rồi nhấp vào nút Download (Tải xuống).

Thao tác này sẽ tải một tệp có tên là GreenMaze_obj.zip xuống.

  1. Trong Android Studio, hãy tạo thư mục green-maze trong app > thành phần > người mẫu
  2. Giải nén GreenMaze_obj.zip rồi sao chép nội dung vào vị trí sau: arcore-android-sdk-x.xx.x/samples/augmented_image_java/app/src/main/assets/models/green-maze
  3. Trong Android Studio, hãy chuyển đến app > (ứng dụng) > thành phần > mô hình > mê cung xanh.

Phải có hai tệp trong thư mục này: GreenMaze.objGreenMaze.mtl.

a1f33a2d2d407e03.png

Kết xuất mô hình mê cung

Làm theo các bước sau để hiển thị mô hình 3D GreenMaze.obj ở đầu hình ảnh 2D hiện có.

Trong AugmentedImageRenderer.java, hãy thêm một biến thành phần có tên là mazeRenderer để kết xuất mô hình mê cung. Vì mê cung phải đính kèm vào hình ảnh, nên bạn nên đặt mazeRenderer bên trong lớp AugmentedImageRenderer.

AugmentedImageRenderer.java

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

Trong hàm createOnGlThread(), hãy tải GreenMaze.obj. Để đơn giản, hãy sử dụng hoạ tiết khung giống như hoạ tiết của khung.

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);

  }

Thay thế định nghĩa của hàm draw() bằng nội dung sau. Thao tác này sẽ điều chỉnh kích thước của mê cung theo kích thước của hình ảnh phát hiện được và hiển thị hình ảnh trên màn hình.

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);
  }

Bây giờ, mê cung sẽ hiển thị ở trên ảnh default.jpg của Trái đất.

Lưu ý: Vì bạn không có toàn quyền kiểm soát đối với mô hình 3D mẫu này, mã ở trên sử dụng một vài "phép màu" số. Kích thước của mô hình mê cung là 492,65 x 120 x 492,65, với tâm là (251,3, 60, -129,0). Dải ô các đỉnh của nó Các giá trị toạ độ X, Y và Z lần lượt là [5,02, 497,67], [0, 120] và [-375,17, 117,25]. Do đó, tỷ lệ của mô hình mê cung cần phải là image_size / 492.65. mazeModelLocalOffset được giới thiệu vì mô hình 3D của mê cung không tập trung vào nguồn gốc (0, 0, 0).

Bức tường của mê cung vẫn quá cao nên không vừa với ảnh trên cùng. Tạo một hàm trợ giúp updateModelMatrix() có thể điều chỉnh tỷ lệ X, Y, Z không đồng đều để tăng chiều cao của Mê cung thêm 0,1. Lưu ý: bạn sẽ giữ updateModelMatrix(float[] modelMatrix, float scaleFactor) hiện có và thêm phương thức nạp chồng hàm updateModelMatrix(float[] modelMatrix, float scaleFactorX, float scaleFactorY, float scaleFactorZ) làm hàm mới.

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);
}

Chạy mã. Lúc này, mê cung sẽ vừa khít phía trên hình ảnh.

772cbe2a8baef3ba.png.

4. Thêm An vào mê cung

Giờ bạn đã có một mê cung, hãy thêm một nhân vật để di chuyển xung quanh bên trong mê cung đó. Dùng tệp andy.obj có trong SDK Android ARCore. Giữ hoạ tiết của khung hình ảnh làm hoạ tiết, vì nó trông khác với mê cung màu xanh lục được kết xuất ở trên cùng hình ảnh.

Trong AugmentedImageRenderer.java, hãy thêm một ObjectRenderer riêng tư để kết xuất An.

AugmentedImageRenderer.java

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

Tiếp theo, hãy khởi chạy andyRenderer ở cuối 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);
  }

Cuối cùng, hãy kết xuất Andrew đứng trên mê cung ở cuối hàm 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);

  }

Chạy mã. Bạn sẽ thấy An đang đứng trên mê cung.

cb1e74569d7ace69.png

Xác định chất lượng ảnh mục tiêu

ARCore dựa vào các tính năng trực quan để nhận dạng hình ảnh. Do sự khác biệt về chất lượng, nên không phải hình ảnh nào cũng có thể dễ dàng nhận ra.

arcoreimg là một công cụ dòng lệnh cho phép bạn xác định mức độ nhận dạng của hình ảnh đối với ARCore. Kết quả này cho ra một số từ 0 đến 100, trong đó 100 là số dễ nhận ra nhất.

của Google. Sau đây là một ví dụ:

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

maze.jpg có giá trị là 100 nên ARCore có thể dễ dàng nhận ra.

5. Không bắt buộc: Khiến An di chuyển trong mê cung

Cuối cùng, bạn có thể thêm mã để di chuyển trong mê cung. Ví dụ: sử dụng công cụ Physics nguồn mở jBullet để xử lý hoạt động mô phỏng thực tế. Bạn hoàn toàn có thể bỏ qua phần này.

Tải PhysicsController.java xuống rồi thêm vào dự án của bạn trong thư mục

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

Trong Android Studio, hãy Thêm GreenMaze.obj vào thư mục project assets để có thể tải tệp này trong thời gian chạy. Sao chép GreenMaze.obj từ ứng dụng > thành phần > mô hình > Green-maze thành app > tài sản.

Thêm các phần phụ thuộc sau đây vào tệp build.gradle của ứng dụng.

app/build.gradle

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

Xác định biến andyPose để lưu trữ vị trí tư thế hiện tại của An.

AugmentedImageRenderer.java

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

Sửa đổi AugmentedImageRenderer.java để kết xuất An bằng cách sử dụng biến andyPose mới.

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);
  }

Thêm một hàm số hiệu dụng mới là updateAndyPose() để nhận thông tin cập nhật về tư thế của An.

AugmentedImageRenderer.java

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

Trong AugmentedImageActivity.java, hãy tạo một đối tượng PhysicsController sử dụng công cụ vật lý JBullet để quản lý tất cả hàm liên quan đến vật lý.

AugmentedImageActivity.java

import com.google.ar.core.Pose;

  // Declare the PhysicsController object
  private PhysicsController physicsController;

Trong công cụ Vật lý, chúng ta sử dụng một quả bóng cứng để thể hiện An và cập nhật tư thế của An bằng tư thế quả bóng. Gọi PhysicsController để cập nhật vật lý bất cứ khi nào ứng dụng nhận ra một hình ảnh. Để di chuyển quả bóng như thể trong thế giới thực, hãy áp dụng trọng lực trong thế giới thực để di chuyển quả bóng trong mê cung.

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;

Chạy ứng dụng. Bây giờ, An sẽ di chuyển xung quanh khi bạn nghiêng hình ảnh một cách thực tế.

Ví dụ dưới đây dùng một chiếc điện thoại khác để hiển thị hình ảnh, bạn có thể dùng bất kỳ thứ gì thuận tiện cho mình, chẳng hạn như máy tính bảng, bìa của một cuốn sách cứng hoặc chỉ một tờ giấy in gắn trên một vật phẳng.

2f0df284705d3704.gif

Vậy là xong! Chúc bạn vui vẻ khi cố gắng đưa An qua mê cung. Gợi ý: Bạn sẽ dễ tìm thấy lối ra này hơn khi lật ngược hình ảnh mục tiêu.

6. Xin chúc mừng

Xin chúc mừng! Bạn đã kết thúc lớp học lập trình này và:

  • Xây dựng và chạy mẫu AAcceleratedImage Java của ARCore.
  • Đã cập nhật mẫu để hiển thị mô hình mê cung trên hình ảnh theo tỷ lệ thích hợp.
  • Sử dụng tư thế của hình ảnh để làm điều gì đó vui nhộn.

Nếu muốn tham khảo mã hoàn chỉnh, bạn có thể tải xuống tại đây.

Bạn có thấy thú vị khi tham gia lớp học lập trình này không?

Không

Bạn có học được điều gì hữu ích khi thực hiện lớp học lập trình này không?

Không

Bạn đã hoàn tất việc tạo ứng dụng trong lớp học lập trình này chưa?

Không

Bạn có dự định tạo ứng dụng ARCore trong 6 tháng tới không?

Có thể Không