【图像识别】在Unity中使用ARCore增强图像的几种方式

简述

本文档记录两种在Unity中使用ARCore实现图像识别的方式。

开发环境:

Unity 2021.3.29

依赖库:

    "dependencies":
    {
        "com.unity.xr.arfoundation": "4.1.5",
        "com.unity.xr.arcore": "4.1.5"
    }

方式1:

  • 直接使用AR Foundation的2D图像跟踪API

方式2:

  • 使用我基于AR Foundation实现的API

补充说明:这里基于AR Foundation实现的API,支持在AOT(Ahead-of-time)程序集和热更程序集中使用图像识别功能。

注意:
如需将现有项目从(已废弃)ARCore SDK for Unity 迁移到 Unity 的 AR Foundation 和(可选)ARCore Extensions,请参阅迁移指南。
如需从早期版本的 AR Foundation 升级现有项目,请参阅 Unity 的升级和迁移指南

环境配置

1、在您的项目中,前往 Window > Package Manager。

2、选择Packages旁边的Unity Registry。

3、在搜索栏中输入“AR Foundation”,找到后点击Install。

4、在搜索栏中输入“ARCore XR plugin”,找到后点击Install。

5、前往 Edit > Project Settings。在 XR Plug-in Management 中,打开 Android 标签页并启用 ARCore。

6、配置Player Settings,详情如下:

Player Settings > …
Other Settings > Rendering取消选中 Auto Graphics API。 如果 Vulkan 列在 Graphics APIs 下,请将其移除,因为 ARCore 尚不支持 Vulkan。
Other Settings > Package Name使用 Java 软件包名称格式创建一个唯一的应用 ID。 例如,使用 com.example.helloAR
Other Settings > Minimum API Level如果您要构建 AR 必备应用,请指定 Android 7.0 ‘Nougat’ (API Level 24) or higher。 如果您要构建 AR 可选应用,请指定 Android API Level 19 or higher
Other Settings > Scripting Backend选择 IL2CPP(而非 Mono)以允许在下一步中启用 ARM64 支持。在开发过程中:使用 Mono + 32 位 (ARMv7)安装 FAT(32 位 + 64 位)ARCore APK寄送到 Play 商店时:使用 IL2CPP同时启用 32 位 (ARMv7) 和 64 位 (ARM64),以满足 Play 商店的 64 位要求可选(在 2018.3 及更高版本中受支持):在 Build Settings 中,启用 Android App Bundles
Other Settings > Target Architectures为了满足 Google Play 64 位要求,请启用 ARM64(64 位 ARM)。 使 ARMv7(32 位 ARM)保持启用状态,以支持 32 位设备。

方式1:直接使用ARFoundation

官方文档

AR Foundation 增强图像开发指南

介绍了如何通过Unity的开发方式在应用中使用增强图像(图像识别)功能。

示例工程

ARFoundation-sample

在这个示例工程中
Assets/Scenes/ImageTracking/BasicImageTracking.unity演示了如何识别图片,并当识别到图片时,在图片位置加载一个prefab。

Assets/Scenes/ImageTracking/ImageTrackingWithMultiplePrefabs.unity演示了如何识别图片,并当识别不同图片时,在图片位置加载预设的与之对应的prefab。

关键类

ARTrackedImageManager

API接口文档

调用示例:

void OnEnable() => m_TrackedImageManager.trackedImagesChanged += OnChanged;

void OnDisable() => m_TrackedImageManager.trackedImagesChanged -= OnChanged;

void OnChanged(ARTrackedImagesChangedEventArgs eventArgs)
{
    foreach (var newImage in eventArgs.added)
    {
        // Handle added event
    }

    foreach (var updatedImage in eventArgs.updated)
    {
        // Handle updated event
    }

    foreach (var removedImage in eventArgs.removed)
    {
        // Handle removed event
    }
}

在运行时添加增强图像,示例如下:

[SerializeField]
ARTrackedImageManager m_TrackedImageManager;

void AddImage(Texture2D imageToAdd)
{
    if (!(ARSession.state == ARSessionState.SessionInitializing || ARSession.state == ARSessionState.SessionTracking))
        return; // Session state is invalid

    if (m_TrackedImageManager.referenceLibrary is MutableRuntimeReferenceImageLibrary mutableLibrary)
    {
        mutableLibrary.ScheduleAddImageWithValidationJob(
            imageToAdd,
            "my new image",
            0.5f /* 50 cm */);
    }
}

但是需要注意的是,在运行时添加增强图像的前提是,这之前存在一个ImageLibrary(可以是没有添加图像的)。

void AddImage(Texture2D imageToAdd)
{
    if (!(ARSession.state == ARSessionState.SessionInitializing || ARSession.state == ARSessionState.SessionTracking))
        return; // Session state is invalid

    var library = m_TrackedImageManager.CreateRuntimeLibrary();
    if (library is MutableRuntimeReferenceImageLibrary mutableLibrary)
    {
        mutableLibrary.ScheduleAddImageWithValidationJob(
            imageToAdd,
            "my new image",
            0.5f /* 50 cm */);
    }
}

编辑器操作

ImageLibrary定义

1、在Assets的目录下,右键->create->XR->Reference Image Library

2、在library中添加图像,如下图

定义lib

绑定对象

1、在AR session Origin 下添加“ARTrackedImageManager”组件(也可在层级菜单右键创建),

2、在“ARTrackedImageManager”组件中绑定“ReferenceImageLibrary”

对象绑定

编写代码

以下是ARFoundation的示例代码

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.XR.ARFoundation;

namespace UnityEngine.XR.ARFoundation.Samples
{
    /// This component listens for images detected by the <c>XRImageTrackingSubsystem</c>
    /// and overlays some information as well as the source Texture2D on top of the
    /// detected image.
    /// </summary>
    [RequireComponent(typeof(ARTrackedImageManager))]
    public class TrackedImageInfoManager : MonoBehaviour
    {
        [SerializeField]
        [Tooltip("The camera to set on the world space UI canvas for each instantiated image info.")]
        Camera m_WorldSpaceCanvasCamera;

        /// <summary>
        /// The prefab has a world space UI canvas,
        /// which requires a camera to function properly.
        /// </summary>
        public Camera worldSpaceCanvasCamera
        {
            get { return m_WorldSpaceCanvasCamera; }
            set { m_WorldSpaceCanvasCamera = value; }
        }

        [SerializeField]
        [Tooltip("If an image is detected but no source texture can be found, this texture is used instead.")]
        Texture2D m_DefaultTexture;

        /// <summary>
        /// If an image is detected but no source texture can be found,
        /// this texture is used instead.
        /// </summary>
        public Texture2D defaultTexture
        {
            get { return m_DefaultTexture; }
            set { m_DefaultTexture = value; }
        }

        ARTrackedImageManager m_TrackedImageManager;

        void Awake()
        {
            m_TrackedImageManager = GetComponent<ARTrackedImageManager>();
        }

        void OnEnable()
        {
            m_TrackedImageManager.trackedImagesChanged += OnTrackedImagesChanged;
        }

        void OnDisable()
        {
            m_TrackedImageManager.trackedImagesChanged -= OnTrackedImagesChanged;
        }

        void UpdateInfo(ARTrackedImage trackedImage)
        {
            // Set canvas camera
            var canvas = trackedImage.GetComponentInChildren<Canvas>();
            canvas.worldCamera = worldSpaceCanvasCamera;

            // Update information about the tracked image
            var text = canvas.GetComponentInChildren<Text>();
            text.text = string.Format(
                "{0}\ntrackingState: {1}\nGUID: {2}\nReference size: {3} cm\nDetected size: {4} cm",
                trackedImage.referenceImage.name,
                trackedImage.trackingState,
                trackedImage.referenceImage.guid,
                trackedImage.referenceImage.size * 100f,
                trackedImage.size * 100f);

            var planeParentGo = trackedImage.transform.GetChild(0).gameObject;
            var planeGo = planeParentGo.transform.GetChild(0).gameObject;

            // Disable the visual plane if it is not being tracked
            if (trackedImage.trackingState != TrackingState.None)
            {
                planeGo.SetActive(true);

                // The image extents is only valid when the image is being tracked
                trackedImage.transform.localScale = new Vector3(trackedImage.size.x, 1f, trackedImage.size.y);

                // Set the texture
                var material = planeGo.GetComponentInChildren<MeshRenderer>().material;
                material.mainTexture = (trackedImage.referenceImage.texture == null) ? defaultTexture : trackedImage.referenceImage.texture;
            }
            else
            {
                planeGo.SetActive(false);
            }
        }

        void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
        {
            foreach (var trackedImage in eventArgs.added)
            {
                // Give the initial image a reasonable default scale
                trackedImage.transform.localScale = new Vector3(0.01f, 1f, 0.01f);

                UpdateInfo(trackedImage);
            }

            foreach (var trackedImage in eventArgs.updated)
                UpdateInfo(trackedImage);
        }
    }
}

编译运行

BasicImageTracking场景:识别图片,在真实世界的图片位置加载图片和文字描述。

识别到图片后,运行效果如下:

运行截图

ImageTrackingWithMultiplePrefab场景:识别不同图片,加载不同的Prefab

识别到图片后,运行效果如下:

运行截图

方式2:间接使用ARFoundation(热更新版本)

使用说明

这里我对ARFoundation做了一层封装,简化了ARCore XR Plugin的使用流程,沿用之前集成其它MR SDK的通用接口。

注意事项

若不使用热更新,则可直接参考“方式1:直接使用ARFoundation的方式”实现即可。

主体程序

1、导入集成后的SDK
2、在场景中添加预制件 “ARCore Session”
3、在场景中添加预制件“HotfixDataLoader”
4、在“HotfixDataLoader”的DataDownLoader组件中添加服务器数据地址

至此,简单的主体程序已完成,编译打包即可。

编辑热更场景

目标

在热更场景中实现ARCore的图像识别

添加组件

在“ARCore Session”对象上添加组件“ARCoreImageDetect”,如下图所示。

添加组件

在“ARCoreImageDetect”中的“Images”下所添加的就是用于识别的图像和识别到图像后加载的Prefab

在“ARCoreImageDetect”中的“DetectCallback”即是事件回调(见下节描述)。

事件回调

有时我们需要监听什么时候识别到图片,什么时候图片失去跟踪状态等信息。

可通过重写"DetectCallback"类

    public class DetectCallback : MonoBehaviour
    {
        public virtual void OnAdded(ARImageInfo image) { }
        public virtual void OnUpdate(ARImageInfo image) { }
        public virtual void OnRemoved(ARImageInfo image) { }

    }

示例如下:

    public override void OnUpdate(ARImageInfo image)
    {
        EqLog.i("DetectMethod", "image.name:" + image.name
            + ";image.position:" + image.transform.position);
    }

    public override void OnAdded(ARImageInfo image)
    {
        EqLog.i("DetectMethod", "image.name:" + image.name
            + ";image.position:" + image.transform.position);
        AndroidUtils.Toast("image.name:" + image.name
            + ";image.position:" + image.transform.position);
    }

    public void LoadCompleted()
    {
        AndroidUtils.Toast("图片数据库加载完成");
    }
场景导出
  • 执行菜单栏“Holo-XR”->“BuildBundle-Android”,指定入口场景后,点击”导出“

img

  • 场景打包的结果为zip包和version文件

img

热更运行

启动之前打包安装的主体程序。会自动校正数据版本,并下载最新场景数据。

运行效果如下:

添加组件

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQ-雪梨蛋花汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值