ARCore 构建增强图像应用程序,识别图片加载模型 您所在的位置:网站首页 3dmax添加图片到平面 ARCore 构建增强图像应用程序,识别图片加载模型

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

2023-01-31 00:06| 来源: 网络整理| 查看: 265

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的代码:

请注意,我们将此片段的名称设置为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 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 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创建了我们的第一个增强图像应用程序!

效果图


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有