美文网首页
ARCore 构建增强图像应用程序,识别图片加载模型

ARCore 构建增强图像应用程序,识别图片加载模型

作者: 橙果子 | 来源:发表于2019-08-14 19:28 被阅读0次

Github源码地址

在本教程中,您将学习如何通过将锚点设置为特定场景而不是常规平面来将3D模型放置在现实世界中。通过Google的ARCore,您可以增加可以被arcore识别的2D图像,然后将3D模型放在它们上面。

您提供一些参考图像,并且ARCore跟踪确定这些图像在环境中的物理位置。增强图像已经广泛使用,如书籍,报纸,杂志等。

您将对ARCore和Sceneform中的一些术语有基本的了解,例如Scene,Anchor,Node,TransformableNode等。

什么是增强图像?

ARCore中的增强图像允许您构建可在用户环境中响应2D图像(例如海报或产品包装)的AR应用程序。您提供了一组参考图像,一旦在摄像机视图中检测到这些图像,ARCore跟踪就会告诉您这些图像在AR会话中的物理位置。

基本上,使用增强图像,您可以将简单的2D图像转换为增强图像,该图像可以被您的应用程序识别,然后用于在其上方放置3D模型。

当您可能想要使用增强图像?

以下是使用增强图像之前可能需要考虑的一些限制:

  • 您的使用案例不得涉及同时扫描20多张图像。由于ARCore一次只能跟踪多达20张图像。
  • 现实世界中物理对应物的尺寸必须大于15cm X 15cm且平坦。
  • 您不想跟踪移动的对象。尽管可以在图像停止后开始跟踪,但ARCore无法跟踪运动图像。
  • ARCore使用参考图像中的特征点,可以存储多达1000个图像的特征点信息。

选择一个好的参考图像

以下是一些选择良好参考图像以提高arcore可检测性的技巧:

  • 增强图像支持PNG,JPEG和JPG格式。
  • 检测基于高对比度的点,因此无论是使用彩色还是黑/白参考图像,都检测彩色和黑/白图像。
  • 图像的分辨率必须至少为300 X 300像素。
  • 使用高分辨率图像并不意味着提高性能。
  • 必须避免使用具有重复特征的图像,如图案,波尔卡圆点。
  • 使用arcoreimg工具评估参考图像的好坏程度。建议得分至少为75分。

如何使用 arcoreimg工具:

从这个链接下载arcore sdk for android:
在任何您喜欢的地方解压缩zip文件的zip内容。
导航到解压缩的文件夹,然后转到工具 - > arcoreimg - > windows(linux / macos,无论你使用什么)
在此位置打开命令提示符。
现在输入以下命令:

// 将dog.png替换为图像的完整路径。
arcoreimg.exe eval-img --input_image_path=dog.png

开始使用增强图像应用程序

现在你已经熟悉了ARCore和Sceneform,并选择了一个分数为75+的好参考图像,现在是时候开始编写应用程序!

编写代码

将创建一个自定义片段以添加到界面中。需要一个自定义代码,将改变默认代码的一些属性。

创建一个名为“CustomArFragment”的类,并从ArFragment扩展它。以下是CustomArFragment的代码:

package com.ayusch.augmentedimages;

import android.util.Log;

import com.google.ar.core.Config;
import com.google.ar.core.Session;
import com.google.ar.sceneform.ux.ArFragment;

public class CustomArFragment extends ArFragment {

    @Override
    protected Config getSessionConfiguration(Session session) {
        getPlaneDiscoveryController().setInstructionView(null);
        Config config = new Config(session);
        config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
        session.configure(config);
        getArSceneView().setupSession(session);

        return config;
    }
}

首先,我们将平面发现指令设置为null。通过这样做,我们关闭在初始化片段之后出现的手形图标,该图标指示用户移动他的手机。我们不再需要它,因为我们没有检测随机平面而是特定图像。

接下来,我们将会话的更新模式设置为LATEST_CAMERA_IMAGE。这可确保在相机帧更新时调用更新侦听器。它配置更新方法的行为。

设置增强图像数据库
在assets文件夹中添加您选择的参考图像(您要在物理世界中检测)。如果您的资源文件夹不存在,请创建一个。 现在我们将添加增强图像到我们的数据库,然后在现实世界中检测到。

我们将在创建片段(场景)后立即设置此数据库。然后我们检查此调用的成功与否,并相应地设置日志。将以下代码添加到自定义片段:

if ((((MainActivity) getActivity()).setupAugmentedImagesDb(config, session))) {
    Log.d("SetupAugImgDb", "Success");
} else {
    Log.e("SetupAugImgDb","Faliure setting up db");
}

这是CustomArFragment的代码:

package com.ayusch.augmentedimages;

import android.util.Log;

import com.google.ar.core.Config;
import com.google.ar.core.Session;
import com.google.ar.sceneform.ux.ArFragment;

public class CustomArFragment extends ArFragment {

    @Override
    protected Config getSessionConfiguration(Session session) {
        getPlaneDiscoveryController().setInstructionView(null);
        Config config = new Config(session);
        config.setUpdateMode(Config.UpdateMode.LATEST_CAMERA_IMAGE);
        session.configure(config);
        getArSceneView().setupSession(session);

        if ((((MainActivity) getActivity()).setupAugmentedImagesDb(config, session))) {
            Log.d("SetupAugImgDb", "Success");
        } else {
            Log.e("SetupAugImgDb","Faliure setting up db");
        }
        return config;
    

}

我们很快将 在MainActivity中创建setupAugmentedImagesDb方法。现在创建了CustomArFragment,让我们将它添加到activity_main.xml,这里是您的activity_main.xml的代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <fragment
        android:id="@+id/sceneform_fragment"
        android:name="com.google.ar.sceneform.samples.augmentedimage.CustomArFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


</RelativeLayout>

请注意,我们将此片段的名称设置为CustomArFragment。这是确保添加的片段是我们的自定义片段所必需的。这将确保处理权限处理和会话初始化。

将图像添加到增强图像数据库

在这里,我们将设置我们的图像数据库,在现实世界中找到参考图像,然后相应地添加3D模型。

让我们从设置数据库开始。在MainActivity.java类中创建一个公共函数setupAugmentedImagesDb

public boolean setupAugmentedImagesDb(Config config, Session session) {
    AugmentedImageDatabase augmentedImageDatabase;
    Bitmap bitmap = loadAugmentedImage();
    if (bitmap == null) {
        return false;
    }

    augmentedImageDatabase = new AugmentedImageDatabase(session);
    augmentedImageDatabase.addImage("tiger", bitmap);
    config.setAugmentedImageDatabase(augmentedImageDatabase);
    return true;
}

private Bitmap loadAugmentedImage() {
      try (InputStream is = getAssets().open("default.jpg")) {
             return BitmapFactory.decodeStream(is);
       } catch (IOException e) {
              Log.e("ImageLoad", "IO Exception", e);
       }

       return null;
}

我们还有loadAugmentedImage方法,它从assets文件夹加载图像并返回一个位图。

setupAugmentedImagesDb中,我们首先为此会话初始化数据库,然后将图像添加到此数据库。我们将我们的形象命名为“老虎”。然后我们为此会话配置设置数据库并返回true,表示图像已成功添加。

default.jpg识别图, frame_lower_left.sfb模型文件

检测现实世界中的参考图像

现在我们将开始在现实世界中检测我们的参考图像。为了做到这一点,我们将为场景添加一个监听器,每次创建一个帧时都会调用该监听器,并且将分析该帧以查找我们的参考图像。

在MainActivity.java 的onCreate方法中添加此行

arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);

现在将onUpdateFrame方法添加到MainActivity:

@RequiresApi(api = Build.VERSION_CODES.N)
private void onUpdateFrame(FrameTime frameTime) {
    Frame frame = arFragment.getArSceneView().getArFrame();

    Collection<AugmentedImage> augmentedImages = frame.getUpdatedTrackables(AugmentedImage.class);
    for (AugmentedImage augmentedImage : augmentedImages) {
        if (augmentedImage.getTrackingState() == TrackingState.TRACKING) {
            if (augmentedImage.getName().equals("tiger") && shouldAddModel) {
                placeObject(arFragment, augmentedImage.createAnchor(augmentedImage.getCenterPose()), Uri.parse("models/frame_upper_left.sfb"));
                shouldAddModel = false;
            }
        }
    }
}

在第一行中,我们从场景中获取帧。甲帧可以被想象为在视频的中间的快照。如果您熟悉视频的工作原理,您可能会知道它们是一系列静止图像,一个接一个地快速翻转,给人以电影的印象。我们正在提取其中一张照片。

一旦我们有了框架,我们就会分析我们的参考图像。我们使用frame.getUpdatedTrackables提取了ARCore跟踪的所有项目的列表。这是所有检测到的图像的集合。然后我们循环收集并检查框架中是否存在我们的图像“tiger”。
如果我们找到匹配项,那么我们继续并在检测到的图像上放置3D模型。

注意:我已添加,shouldAddModel 以确保我们只添加一次模型。

将3D模型放在参考图像上

现在我们已经在现实世界中检测到了我们的图像,我们可以开始在其上添加3D模型。我们将从之前的项目中复制placeObject和addNodeToScene方法并在此处添加它们。

虽然我之前已经逐行解释了这些方法的作用,但这里有一个概述:

  • PlaceObject:此方法用于从提供的Uri构建可渲染。构建可渲染后,将其传递到addNodeToScene方法,其中可渲染附加到节点,并将该节点放置到场景上。
  • AddNodeToScene:此方法从接收到的锚点创建AnchorNode,创建附加了可渲染项的另一个节点,然后将此节点添加到AnchorNode并将AnchorNode添加到场景中。

这是我们最终的MainActivity.java类:

package com.ayusch.augmentedimages;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.google.ar.core.Anchor;
import com.google.ar.core.AugmentedImage;
import com.google.ar.core.AugmentedImageDatabase;
import com.google.ar.core.Config;
import com.google.ar.core.Frame;
import com.google.ar.core.Session;
import com.google.ar.core.TrackingState;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.FrameTime;
import com.google.ar.sceneform.rendering.ModelRenderable;
import com.google.ar.sceneform.rendering.Renderable;
import com.google.ar.sceneform.ux.ArFragment;
import com.google.ar.sceneform.ux.TransformableNode;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;

public class MainActivity extends AppCompatActivity {
    ArFragment arFragment;
    boolean shouldAddModel = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        arFragment = (CustomArFragment) getSupportFragmentManager().findFragmentById(R.id.sceneform_fragment);
        arFragment.getPlaneDiscoveryController().hide();
        arFragment.getArSceneView().getScene().addOnUpdateListener(this::onUpdateFrame);
    }


    @RequiresApi(api = Build.VERSION_CODES.N)
    private void placeObject(ArFragment arFragment, Anchor anchor, Uri uri) {
        ModelRenderable.builder()
                .setSource(arFragment.getContext(), uri)
                .build()
                .thenAccept(modelRenderable -> addNodeToScene(arFragment, anchor, modelRenderable))
                .exceptionally(throwable -> {
                            Toast.makeText(arFragment.getContext(), "Error:" + throwable.getMessage(), Toast.LENGTH_LONG).show();
                            return null;
                        }

                );
    }

@RequiresApi(api = Build.VERSION_CODES.N)
    private void onUpdateFrame(FrameTime frameTime) {
        Frame frame = arFragment.getArSceneView().getArFrame();

        Collection<AugmentedImage> augmentedImages = frame.getUpdatedTrackables(AugmentedImage.class);
        for (AugmentedImage augmentedImage : augmentedImages) {
            if (augmentedImage.getTrackingState() == TrackingState.TRACKING) {
                if (augmentedImage.getName().equals("tiger") && shouldAddModel) {
                    placeObject(arFragment, augmentedImage.createAnchor(augmentedImage.getCenterPose()), Uri.parse("Mesh_BengalTiger.sfb"));
                    shouldAddModel = false;
                }
            }
        }
    }

    public boolean setupAugmentedImagesDb(Config config, Session session) {
        AugmentedImageDatabase augmentedImageDatabase;
        Bitmap bitmap = loadAugmentedImage();
        if (bitmap == null) {
            return false;
        }

        augmentedImageDatabase = new AugmentedImageDatabase(session);
        augmentedImageDatabase.addImage("tiger", bitmap);
        config.setAugmentedImageDatabase(augmentedImageDatabase);
        return true;
    }

private Bitmap loadAugmentedImage() {
        try (InputStream is = getAssets().open("blanket.jpeg")) {
            return BitmapFactory.decodeStream(is);
        } catch (IOException e) {
            Log.e("ImageLoad", "IO Exception", e);
        }

        return null;
    }

    private void addNodeToScene(ArFragment arFragment, Anchor anchor, Renderable renderable) {
        AnchorNode anchorNode = new AnchorNode(anchor);
        TransformableNode node = new TransformableNode(arFragment.getTransformationSystem());
        node.setRenderable(renderable);
        node.setParent(anchorNode);
        arFragment.getArSceneView().getScene().addChild(anchorNode);
        node.select();
    }


}

现在运行你的应用程序 您应该看到如下所示的屏幕。在我们的手机上移动一点参考物体。ARCore将检测特征点,一旦在现实世界中检测到参考图像,它就会将3D模型添加到其中。
有了这个,我们使用Arcore by Google和Sceneform SDK创建了我们的第一个增强图像应用程序!


效果图

相关文章

  • ARCore 构建增强图像应用程序,识别图片加载模型

    Github源码地址 在本教程中,您将学习如何通过将锚点设置为特定场景而不是常规平面来将3D模型放置在现实世界中。...

  • ND4J读取图片

    一、构建加载器 构建图片加载器,顺便完成了对图片的缩放功能,可以直接用于fit网络模型。 height: 图片的高...

  • ARCore 相关

    1、概述 ARCore 是 Google 的增强现实体验构建平台。 ARCore 利用不同的 API 让手机能够感...

  • ARCore的原理和应用

    ARCore 是 Google 的增强现实体验构建平台。 ARCore 利用不同的 API 让您的手机能够感知其环...

  • ARCore 1.0正式发布啦

    ARCore是一个用于在Android上构建增强现实应用的平台。ARCore使用三个主要技术将虚拟内容与通过手机摄...

  • 图片加载库-Picasso使用

    引入 Picasso 库 混淆 使用 加载网络图片当然首先要设置权限 Picasso 允许在应用程序中轻松加载图像...

  • CV-数据读取与数据扩增

    首先考虑使用[定长字符识别]思路来构建模型。 1. 图像读取 Pillow OpenCV 1.1 Pillow ...

  • 图像增强

    图像增强包括空间域增强与频域图像增强。考虑以下图片: 首先考虑灰度图的处理,转化为灰度图片 空间域图像增强 基本灰...

  • 7- 深度学习之神经网络核心原理与算法-模型的保存与加载

    模型的保存与加载 网络训练完毕你需要保存,以便在产品上使用。(手写识别模型要识别新的图片) 保存网络的结构,权重,...

  • ICML 2019 oral 论文 | 伯克利 AI 研究院提出

    数据增强是提升图像识别模型性能的重要手段。伯克利 AI 研究院的一篇关于数据增强的论文便被ICML 2019 收录...

网友评论

      本文标题:ARCore 构建增强图像应用程序,识别图片加载模型

      本文链接:https://www.haomeiwen.com/subject/emynjctx.html