ARFoundation之路-人脸检测增强之三

版权声明:Davidwang原创文章,严禁用于任何商业途径,授权后方可转载。

  ARFoundation在进行人脸检测时需要借助底层Provider提供的算法及功能特性,不同的底层能提供的功能特征也不相同,如在ARCore人脸检测中,提供人脸区域的概念与功能,而在ARKit人脸检测中,则提供Blend Shape功能。

(一)人脸区域

  ARCore在进行人脸检测时其实是同时运行了两个实时深度神经网络模型:一个负责检测整张图像并计算人脸位置的探测模型,另一个是借助通用3D网格模型通过回归方式检测并预测大概的面部结构。ARCore在检测的人脸时,除了提供一张468个点的人脸网络之外,其还对网格特定区域进行了标定,如下图所示,ARCore提供的人脸网格包括了顶点信息、中心点姿态信息、人脸区域信息。其中中心点位于人体头部的中央位置,中心点也是人脸网格顶点的坐标原点,即为人脸风格的局部空间原点。

在这里插入图片描述
  ARCore目前定义了三个人脸局部区域,即上图所示三个黄色小圈区域,可以在应用开发中直接使用,并在代码中定义了一个枚举数 ARCoreFaceRegion,如下表所示:

属性描述
ForeheadLeft定位人脸模型的左前额
ForeheadRight定位人脸模型的右前额
NoseTip定位人脸模型的鼻尖

  因为人脸特征,在有这三个局部区域定位后, 我们可以方便的将虚拟物体挂载到人脸上,ARCoreFaceRegion枚举以后应该还会继续扩充,起码会包括眼睛、耳朵、嘴部、脸颊,更方便我们精确定位检测到的人脸模型的具体位置。

  下面以鼻尖区域(NoseTip)为例,我们将人脸盔甲面罩戴在人脸上。
  思路:
  1、制作一个盔甲面罩,将眼镜部分镂空。
  2、注册AR Face Manager组件的facesChanged事件,在added、updated中将面罩挂在NoseTip位置上。

  为了将面罩挂在NoseTip位置上,我们需要在人脸区域中找到NoseTip,新建一个C#脚本,命名为SingleFaceRegionManager,编写如下代码:

[RequireComponent(typeof(ARFaceManager))]
[RequireComponent(typeof(ARSessionOrigin))]
public class SingleFaceRegionManager : MonoBehaviour
{
    [SerializeField]
    private GameObject mRegionPrefab;
    private ARFaceManager mARFaceManager;
    private GameObject mInstantiatedPrefab;
    private ARSessionOrigin mSessionOrigin;
    private NativeArray<ARCoreFaceRegionData> mFaceRegions;

    private void Awake()
    {
        mARFaceManager = GetComponent<ARFaceManager>();
        mSessionOrigin = GetComponent<ARSessionOrigin>();
        mInstantiatedPrefab = Instantiate(mRegionPrefab, mSessionOrigin.trackablesParent);
    }

    private void OnEnable()
    {
        mARFaceManager.facesChanged += OnFacesChanged;
    }
    void OnDisable()
    {
        mARFaceManager.facesChanged -= OnFacesChanged;
    }
    void OnFacesChanged(ARFacesChangedEventArgs eventArgs)
    {


        foreach (var trackedFace in eventArgs.added)
        {
            OnFaceChanged(trackedFace);
        }
        
        foreach (var trackedFace in eventArgs.updated)
        {
            OnFaceChanged(trackedFace);
        }
        /*
        foreach (var trackedFace in eventArgs.removed)
        {
            OnFaceRemoved(trackedFace);
        }
        */
    }

    private void OnFaceChanged(ARFace refFace)
    {
        var subsystem = (ARCoreFaceSubsystem)mARFaceManager.subsystem;
        subsystem.GetRegionPoses(refFace.trackableId, Allocator.Persistent, ref mFaceRegions);
        for (int i = 0; i < mFaceRegions.Length; ++i)
        {
            var regionType = mFaceRegions[i].region;
            if (regionType == ARCoreFaceRegion.NoseTip)
            {
                mInstantiatedPrefab.transform.localPosition = mFaceRegions[i].pose.position;
                mInstantiatedPrefab.transform.localRotation = mFaceRegions[i].pose.rotation;
            }
        }
    }

    void OnDestroy()
    {
        if (mFaceRegions.IsCreated)
            mFaceRegions.Dispose();
    }
}

  在上述代码中,为了更有效的利用模型而不是在每次检测到人脸added、updated时重新实例化盔甲面罩,我们只在Awake()方法中实例化了一个Prefab,并在added、updated中实时的更新该实例化对象的姿态。将该脚本挂载在Hierarchy窗口中的AR Session Origin对象上,将盔甲面罩赋给mRegionPrefab属性,同时将AR Face Manager组件中的Face Prefab置空,编译运行,效果如下:

在这里插入图片描述
  正如前所述,ARCore的区域只是方便让我们以更精确的方式在特定位置挂载虚拟物体。因为在检测人体头部时,都会提供头部中心点姿态信息,加之人脸结构的固定性,因此即使没有区域的概念,我们也可以通过操控模型以偏移一定的距离而将模型挂载在人脸的指定位置,如我们可以通过调整模型位置只使用AR Face Manager将眼镜模型挂载在人眼上,如下图所示。

在这里插入图片描述

在这里插入图片描述
  相比于特征区域,这种通过模型偏移的方式有一个问题,因为我们是通过相对中心点的偏移将虚拟物体挂载到特定位置的,这个偏移量个体差异会很大,即挂在小孩脸上的眼镜正合适时挂在成人脸上的眼镜就会偏下(小孩眼睛离中心点距离比成人小),因此在能使用区域位置特性时尽量使用区域可以提高精度。

(二)多人脸检测

  ARCore与ARKit都支持多人脸检测,在多人脸检测中,除了注册facesChanged事件,我们也可以直接在Update()方法中进行处理,代码如下:

using System.Collections.Generic;
using Unity.Collections;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using UnityEngine.XR.ARCore;

[RequireComponent(typeof(ARFaceManager))]
[RequireComponent(typeof(ARSessionOrigin))]
public class ARCoreFaceRegionManager : MonoBehaviour
{
    [SerializeField]
    GameObject mRegionPrefab;
    ARFaceManager mFaceManager;
    ARSessionOrigin mSessionOrigin;
    NativeArray<ARCoreFaceRegionData> mFaceRegions;
    Dictionary<TrackableId, Dictionary<ARCoreFaceRegion, GameObject>> mInstantiatedPrefabs;

    void Start()
    {
        mFaceManager = GetComponent<ARFaceManager>();
        mSessionOrigin = GetComponent<ARSessionOrigin>();
        mInstantiatedPrefabs = new Dictionary<TrackableId, Dictionary<ARCoreFaceRegion, GameObject>>();
    }

    void Update()
    {
        var subsystem = (ARCoreFaceSubsystem)mFaceManager.subsystem;
        if (subsystem == null)
            return;        
        foreach (var face in mFaceManager.trackables)
        {
            Dictionary<ARCoreFaceRegion, GameObject> regionGos;
            if (!mInstantiatedPrefabs.TryGetValue(face.trackableId, out regionGos))
            {
                regionGos = new Dictionary<ARCoreFaceRegion, GameObject>();
                mInstantiatedPrefabs.Add(face.trackableId, regionGos);
            }
            
            subsystem.GetRegionPoses(face.trackableId, Allocator.Persistent, ref mFaceRegions);
            for (int i = 0; i < mFaceRegions.Length; ++i)
            {                
                var regionType = mFaceRegions[i].region;
                if (regionType == ARCoreFaceRegion.NoseTip)
                {
                    GameObject go;
                    if (!regionGos.TryGetValue(regionType, out go))
                    {
                        go = Instantiate(mRegionPrefab, mSessionOrigin.trackablesParent);
                        regionGos.Add(regionType, go);
                        //Debug.Log("Object Count :" + mInstantiatedPrefabs.Count);
                    }

                    go.transform.localPosition = mFaceRegions[i].pose.position;
                    go.transform.localRotation = mFaceRegions[i].pose.rotation;
                }
            }
        }        
    }

    void OnDestroy()
    {
        if (mFaceRegions.IsCreated)
            mFaceRegions.Dispose();
    }
}

  代码中我们也是在NoseTip位置挂载模型,在ForeheadLeft 或 ForeheadRight位置挂载虚拟物体,处理方式完全一致。上述代码中,我们在所有检测到的人脸NoseTip位置挂载相同的虚拟物体模型,如果需要挂载不同的虚拟物体,我们可以设置一个Prefabs数组用于保存所有的待实例化预制体,然后用一个随机数发生器随机实例化虚拟物体。当前,我们无法做到在特定的人脸上挂载特定的虚拟物体,因为ARCore、ARKit只提供人脸检测而不是人脸识别,如果需要此功能,还需要借助其他技术共同完成。

课程介绍 本套课程从技术理念到项目实践,教大家系统掌握ARKit技术开发,随心打造iOS端AR增强现实应用。由一开始的开发环境搭建,到Unity ARKit Plugin、ARFoundation ARKit等不同时期技术的讲解。从平面模型放置、识别图片、手势交互、3D物体识别、面部AR贴纸、光照估计、环境探针、多人AR技术,甚至包含ARKit3.0的动作捕捉技术等。除了以上课程内容,更加入了随着技术更新与时俱进更新的ARKit连载技术教学内容。课程收益 轻松理解ARKit的技术原理,从零到一创建自己的第一个AR项目。学习UnityARKit Plugin经典技术,了解ARKit中的常见概念和原理。学会在 ARFoundation 中使用ARKit,进行企业级AR项目开发。学会如何在AR项目里播放模型动画,通过触屏手势交互实现模型的旋转和缩放。 了解ARKit的图片识别,掌握AR卡片、AR书籍的实现方法。 学会使用面部增强技术,实现热门短视频应用的AR贴纸效果,实现面部表情追踪。学会使用ARKit物体检测技术,实现3D物体识别,可以广泛应用于工业、建筑、古董、玩具手办、艺展览等不同场景。学习ARKit中的经典交互案例,优化AR项目的用户体验。熟练使用环境纹理、光照估计技术,让AR内容随当前现实场景自动变化调节,看起来更加真实。基于WorldMap、CollaborativeSession AR技术,实现AR场景的持久化及多人AR体验效果。
ARFoundation是一个用于在移动设备上创建现实增强应用程序的开发框架。人脸跟踪编程是ARFoundation系列教程中的一部分。 人脸跟踪是通过相机捕捉实时视频流并使用AR技术来检测和跟踪人脸的过程。这个过程涉及到计算机视觉和人工智能的技术,可以在移动设备上实时地识别人脸,进而应用各种效果和交互。 在ARFoundation系列教程中学习人脸跟踪编程,你将学习如何使用ARFoundation和Unity引擎来构建具有人脸追踪功能的应用程序。教程会向你介绍如何在Unity中创建一个AR项目,并使用ARFoundation的API来实现人脸追踪功能。 首先,你需要在Unity中导入ARFoundation库并设置相机权限。然后,你可以创建一个3D模型来代表人脸,并将其与人脸跟踪的数据进行关联。在跟踪开始后,你可以通过获取人脸的特征点信息和姿势来实时地更新模型的位置和角度。 此外,你还可以根据人脸的表情特征,例如眨眼、微笑等,来触发应用程序中的效果或交互。例如,你可以通过检测到用户眨眼的动作来实现快门的触发,拍摄照片或录制视频。 通过学习ARFoundation系列教程中的人脸跟踪编程,你将能够掌握如何使用AR技术在移动设备上实现实时人脸跟踪功能。这将为你开发创新的增强现实应用程序提供基础,并且能够为用户提供更加沉浸式和交互性的体验。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_DavidWang_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值