当前位置: 首页 > news >正文

【iOS ARKit】2D肢体动作捕捉

       人体肢体动作捕捉在动漫影视制作、游戏CG 动画、实时模型驱动中有着广泛的应用,利用 ARKit,无须额外的硬件设备即可实现 2D和3D人体一系列关节和骨骼的动态捕捉,由于移动AR 的便携性及低成本,必将促进相关产业的发展。

ARBody TrackingConfiguration

      ARKit 配置类 ARBodyTrackingConfiguration 专用于 2D、3D人体肢体检测捕捉,同时,该配置类也可以设置实现 2D 图像检测和平面检测,构建对现实环境的跟踪。为更真实地渲染虚拟元素,ARBodyTrackingConfiguration 还支持 HDR(High Dynamic Range Imaging,高动态范围成像)环境反射功能。其主要属性如下表所示。

属性名

描述

automaticSkeletonScaleEstimationEnabled

布尔值,指定 ARKit是否进行人体骨骼尺寸评估,设置为true 时,ARKit会根据人体距离摄像头的远近调整所驱动的模型大小,使其更匹配

isAutoFocusEnabled

设置是否自动对焦

planeDetection

在进行人体肢体检测跟踪时是否进行平面检测,可以设置为水平(horizontal)或者垂直(vertical),或者两者都设置。设置该值后就会启动平面检测功能

automaticImageScaleEstimationEnabled

自动评估检测到的2D图像的尺寸,这在设置2D 图像跟踪时有效

detectionImages

参考图像库

maximum NumberOfTrackedImages

最大可同时跟踪的2D 图像数量

wantsHDREnvironment Textures

是否使用HDR 环境纹理反射,使用后渲染的虚拟元素更真实

environment Texturing

环境纹理来源,可设置为自动(automatic)、手动(manual)、无(none)三者之一,当设置为手动时,需要提供环境纹理图

      通常,在实现人体肢体检测和人形遮挡功能时,还需要设置 frameSemantics 语义属性,使用ARBoodyTrackingConfiguration 配置类进行人体肢体检测和动作捕捉时,frameSemantics 语义属性值只能设置 bodyDetection(默认值)。frameSemantics 语义属性中 bodyDetection 用于肢体检测跟踪,后两个用于人形遮挡,personSegmentation现实屏幕空间的人形分离,而 personSegmentation WithDepth则是带有深度信息的人形分离。

2D人体姿态估计

      在ARKit 中,2D人体姿态估计是指对摄像头采集的视频图像中人像在屏幕空间中的姿态进行估计,通常使用人体骨骼关节点来描述人体姿态。近年来,随着深度学习技术的发展,人体骨骼关节点检测效率与效果不断提升,已经开始广泛应用于计算机视觉的相关领域。2D人体姿态检测估计在视频安防、动作分类、行为检测、人机交互、体育科学中有着广阔的应用前景。

人体骨骼关节点检测

     人体骨骼关节点检测(Pose Estimation)主要检测人体的一些关键节点,如关节、头部、手掌等,通过关节点描述人体骨骼及姿态信息。人体骨骼关节点检测在计算机视觉人体姿态检测相关领域的研究中起到了基础性的作用,是智能视频监控、病人监护系统、人机交互、虚拟现实、智能家居、智能安防、运动员辅助训练等应用的基础性算法。

      在实际应用中,由于人体具有相当的柔性,会出现各种姿态和形状,人体任何一个部位的微小变化都会产生一种新的姿态,同时其关节点的可见性受穿着、姿态、视角等影响非常大,而且还受到光照、遮挡等环境影响。除此之外,2D人体关节点和3D人体关节点在视觉上会有明显的差异,身体不同部位都会有视觉上的缩短效应(Fore Shortening),使得人体骨骼关节点检测成为计算机视觉领域中一个极具挑战性的课题。

使用2D 人体姿态估计

     在 ARKit 中,我们不必关心底层的人体骨骼关节点检测算法,也不必自己去调用这些算法,在运行使用ARBodyTrackingConfiguration 配置的ARSession 之后,基于摄像头图像的2D人体姿态估计任务就会启动。

      2D人体姿态检测基于屏幕空间,获取的人体姿态信息没有深度值。在 ARKit 检测到屏幕空间中的人形后,可以通过 ARFrame. detectedBody 获取一个 ARBody2D 对象,也就是说 ARKit 目前对屏幕空间中的2D人体,只支持单个人形检测。ARBody2D对象描述了检测到的人形结构信息,其结构如下图所示。

     通过图可以看到,在使用 session(_ session: ARSession,didUpdate frame: ARFrame)方法获取ARFrame 中表示 2D人体的 ARBody2D 对象后,就可以使用其 skeleton. jointLandmarks 获取所有关节点位置信息,也可以通过其 skeleton. definition.jointNames 获取所有关节点名称。jointLandmarks 是一个包含所有关节点位置信息的数组,我们可以通过索引值检索某个关节点的位置,也可以通过 skeleton.landmark(for: ARSkeleton. JointName(rawValue: jointName))方法取指定关节点名称的位置信息。

     2D人体姿态估计是在屏幕空间中对摄像头采集的图像进行逐帧分析,解算出的关节点位置也是在屏幕空间中的归一化坐标,以屏幕左上角(0,0)右下角为(1,1),如下图所示。

    为了描述人体骨骼关节点,ARKit 新建了一个 ARSkeleton 类,该类包含一个人体关节点(Joint)集合及关节之间关系的定义,该类预定义了8个关节点,分别是 head、 leftFoot、 left Hand、 leftShoulder.hannnt riahtHand.rightShoulder、root.这是在应用开发中使用最多的关节点,2D和3D人体肢体都包含这些关节点,因此我们可以通过这些预定义的节点名字快速找到骨骼节点位置。ARSkeleton 类是ARSkeleton2D 和 ARSkeleton3D类的父类。

      ARSkeleton2D 类继承自 ARSkeleton,其 jointLandmarks 包含了所有2D关节点的位置信息,也可以通过该类的landmark(forJointNamed:)方法获取某个名字关节点的位置,此方法需要传递关节点的原始名称(rawValue)而不是 ARSkeleton 预定义的关节点名(预定义关节点名可以通过其.rawValue 获取原始名称)。jointLandmarks 是 simd_float2 类型数组,因此我们也可以直接通过下标获取特定的关节点位置信息,下标方法取值比使用 landmark(forJointNamed:)快得多,特别是对每帧都要执行的循环操作,可以节省很多时间。获取特定节点名称的索引值可以通过 definition.index(for:)方法实现。除此之外,还可以通过 ARSkeleton2D的isJointTracked(_:)方法查询每一个关节点在当前帧的检测跟踪情况,还可以获取每一个节点的父节点。

骨骼关节点名称

索引

父节点名称

索引

invalid

-1

head_ joint

0

neck_1 joint

1

neck_ 1_joint

1

root

16

right_ shoulder_1 _joint

2

neck_1_joint

1

right_ forearm_joint

3

right_shoulder_1_joint

2

right_hand _joint

4

right_ forearm_joint

3

left_shoulder_1_joint

5

neck_1 _joint

1

left_forearm_joint

6

5

left_hand joint

7

left forearm_joint

6

right_upLeg_joint

8

root

16

right_leg joint

9

right_upLeg_joint

8

right_foot_ joint

10

right_leg joint

9

left_ upLeg_joint

11

root

16

left_leg joint

12

left_upLeg_joint

11

left_foot joint

13

left_leg joint

12

right_eye joint

14

head _joint

0

left_eye_joint

15

head_joint

0

root

16

Invalid

-1

right_ear_joint

17

right_eye joint

14

left-ear- joint

18

left_eye_joint

15

     ARKit 2D 人体骨骼关节点定义及它们之间的关联关系如上表所示,通过表可以看到,在ARKit 中,检测到的2D人体共包含19个关节点(root 节点代表了整个 ARBody2D 对象,不计算在内时包含18个关节点),这些关节点相互之间有很强的相关性,存在紧密的父子连接关系,通过节点之间的相互关系,就可以画出各骨骼节点之间的连结图。

     下面演示利用 ARKit 检测到的2D人体骨骼关节点信息,将每一个关节点用一个圆圈标示出来,具体代码如下

//
//  BodyTrackingView.swift
//  ARKitDeamo
//
//  Created by zhaoquan du on 2024/2/1.
//import SwiftUI
import ARKit
import RealityKitstruct BodyTrackingView: View {var body: some View {BodyTrackingViewContainer().edgesIgnoringSafeArea(.all).navigationTitle("人体骨架2D检测")}
}struct BodyTrackingViewContainer:UIViewRepresentable {func makeUIView(context: Context) ->ARView {let arView = ARView(frame: .zero)return arView}func updateUIView(_ uiView: UIViewType, context: Context) {guard ARBodyTrackingConfiguration.isSupported else {return}context.coordinator.arView = uiViewlet config = ARBodyTrackingConfiguration()config.frameSemantics = .bodyDetectionconfig.automaticSkeletonScaleEstimationEnabled = trueuiView.session.delegate = context.coordinatoruiView.session.run(config)}func makeCoordinator() -> Coordinator {Coordinator()}class Coordinator: NSObject,ARSessionDelegate {var arView : ARView? = nillet circleWidth: CGFloat = 10let circleHeight: CGFloat = 10var isPrinted = falsefunc session(_ session: ARSession, didUpdate frame: ARFrame) {guard let arView = arView else {return}//清除骨骼圆圈arView.layer.sublayers?.compactMap({$0 as? CAShapeLayer}).forEach({$0.removeFromSuperlayer()})guard let detectedBody =  frame.detectedBody else {return}guard let orientation = arView.window?.windowScene?.interfaceOrientation else {return}let transform = frame.displayTransform(for: orientation, viewportSize: arView.frame.size)detectedBody.skeleton.jointLandmarks.forEach { landmark inlet normalizeCenter = CGPoint(x: CGFloat(landmark.x), y: CGFloat(landmark.y)).applying(transform)let center = normalizeCenter.applying(.identity.scaledBy(x: arView.frame.width, y: arView.frame.height))let rect = CGRect(x: center.x - circleWidth/2, y: center.y - circleWidth/2, width: circleWidth, height: circleHeight)let circleLayer = CAShapeLayer()circleLayer.path = UIBezierPath(ovalIn: rect).cgPatharView.layer.addSublayer(circleLayer)}if !isPrinted {let jointNames = detectedBody.skeleton.definition.jointNamesfor name in jointNames {let landmark = detectedBody.skeleton.landmark(for: ARSkeleton.JointName(rawValue: name))let index = detectedBody.skeleton.definition.index(for: ARSkeleton.JointName(rawValue: name))print("\(name),\(String(describing: landmark)),the index is \(index) parent index is  \(detectedBody.skeleton.definition.parentIndices[index])")}print("last: \(ARSkeleton2D.JointName.rightShoulder.rawValue)")isPrinted = true}}}}

      代码中实现的主要功能是在每一个检测到的2D人体关节点位置画一个圆圈,效果如图所示。

     ​​​​​代码很多语句都是执行画图操作,但也演示了 ARKit 2D 人体检测使用的几个重要功能:

  (1)演示了如何获取屏幕空间中的 ARBody2D对象,为确保代码在没有检测到2D人体时也能正确执行,我们使用了 guard 语句。

  (2)演示了如何获取2D 人体所有骨骼关节点名字集合,以及各关节点索引及其父节点索引。

  (3)演示了如何利用关节点名字获取该关节点在屏幕空间中的位置信息。

    如前所述,使用索引值获取特定的关节点位置信息比使用关节点名字快得多,代码清演示了利用关节点名字获取对应索引值,在实际开发中,可以直接使用前表中各关节点的索引值以提高性能。

具体代码地址:GitHub - duzhaoquan/ARkitDemo

相关文章:

【iOS ARKit】2D肢体动作捕捉

人体肢体动作捕捉在动漫影视制作、游戏CG 动画、实时模型驱动中有着广泛的应用,利用 ARKit,无须额外的硬件设备即可实现 2D和3D人体一系列关节和骨骼的动态捕捉,由于移动AR 的便携性及低成本,必将促进相关产业的发展。 ARBody Tr…...

MAC word删除空白页

问题:MAC word删除空白页 解决: option删除键...

字面跳动前端面试题:React Hook为什么不能放在if/循环/嵌套函数里面?

答:首先,React Hooks 是为了简化组件逻辑和提高代码可读性而设计的。将 Hook 放在 if/循环/嵌套函数中会破坏它们的封装性和可预测性,使得代码更难维护和理解。同时,这样做也增加了代码的复杂度,可能会导致性能下降和潜…...

【SpringBoot】SpringBoot的web开发

📝个人主页:五敷有你 🔥系列专栏:SpringBoot ⛺️稳重求进,晒太阳 Wbe开发 使用Springboot 1)、创建SpringBoot应用,选中我们需要的模块; 2)、SpringBoot已经默…...

houdini 入门指南-参考自用,内有翻译错误

HOUDINI 18.5列1 GETTING STARTED 入门指南 What’s new in Houdini 18.5 胡迪尼18.5有什么新内容 New features and changes in Houdini 18.5.胡迪尼18.5的新功能和变化。Basics基础The basics of working with Houdini’s user interface.使用胡迪尼用户界面的基本知识。Shel…...

【笔记】SPN和PLMN 运营商网络名称显示

一、业务术语 缩写 全称 释义 CDNR Carrier Display Name Ressource 运营商显示名称资源 PLMN Public Land Mobile Network 公共陆地移动网络。 表示最终显示的网络运营商名字 SPN Service Provider Name SIM卡EF文件6F46。表示服务提供商名字,主要是SIM卡服务 OPL Operator …...

Selenium处理Alert弹窗

页面弹窗有 3 种类型: alert(警告信息) confirm(确认信息) prompt(提示输入) 对于页面出现的 alert 弹窗,Selenium 提供如下方法: 序号 方法/属性 描述 1 ac…...

FCIS 2023:洞悉网络安全新前沿,引领未来安全创新狂潮

在数字化浪潮席卷全球的今天,网络安全问题愈发凸显其重要性。 FCIS 2023网络安全创新大会作为业界瞩目的盛会,不仅汇聚了国际顶尖的网络安全专家,更展示了最前沿的安全技术与研究成果。那么,参与这场大会,我们究竟能学…...

4个最佳的免费全磁盘加密程序,总有一款适合你

全磁盘加密软件加密整个驱动器,而不仅仅是几个文件或文件夹。加密计算机的驱动器可以使你的私人数据免受窥探,即使你的计算机被盗。 你也不仅仅局限于一个硬盘驱动器。闪存驱动器和外部硬盘驱动器等外部设备也可以通过磁盘加密软件进行加密。 注意:Windows和macOS都集成了…...

SQL语句创建数据库

在SQL中,可以使用CREATE DATABASE语句来创建数据库。下面是一个示例: CREATE DATABASE database_name;其中,database_name是要创建的数据库的名称。你可以将其替换为你想要的数据库名称。 请注意,在不同的SQL数据库管理系统中&a…...

【lesson38】让minishell支持重定向

文章目录 minishell支持重定向minishell完整代码 minishell支持重定向 支持重定向的核心逻辑: 1.分析字符串是否含有重定向的符号,并且提取文件名。 #define INPUT_REDIR 0 //输入重定向 #define OUTPUT_REDIR 1 //输出重定向 #define APPEND_REDIR…...

【安装指南】maven下载、安装与配置详细教程

🌼一、概述 maven功能与python的pip类似。 Apache Maven是一个用于软件项目管理和构建的强大工具。它是基于项目对象模型的,用于描述项目的构建配置和依赖关系。以下是一些关键的 Maven 特性和概念: POM(Project Object Model&…...

matplotlib-中文乱码问题解决方案

前言 本文主要解决matplotlib在画图时,出现的中文乱码问题,具体问题示意如下: 下面将针对这个问题直接给出具体的解决步骤。 具体步骤 1、首先去网上下载并安装SimHei字体,其它字体也行,如下 并将它安装在此目录下…...

Redis(十一)单线程VS多线程

文章目录 概述为何选择单线程主要性能瓶颈多线程特性和IO多路复用概述Unix网络编程中的五种IO模型Blocking IO-阻塞IONoneBlocking IO-非阻塞IOIO multiplexing-IO多路复用signal driven IO-信号驱动IOasynchronous IO-异步IO 场景:引出epoll总结 开启Redis多线程其…...

【微服务】Spring Boot集成ELK实用案例

推荐一款我一直在用国内很火的AI网站,包含GPT3.5/4.0、文心一言、通义千问、智谱AI等多个AI模型,支持PC、APP、VScode插件同步使用,点击链接跳转->ChatGPT4.0中文版 一、前言 在现代软件开发中,微服务架构已成为一种流行趋势。…...

已解决: ImportError: cannot import name ‘relu‘ from ‘keras.layers‘ 问题

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …...

python-产品篇-火车票分析助手

文章目录 开发环境要求运行方法PyCarmVsCode 代码效果 开发环境要求 本系统的软件开发及运行环境具体如下。 (1)操作系统:操作系统:Windows 7、Windows 8、Windows 10。 (2)Python版本:Python …...

设计一个可以智能训练神经网络的流程

设计一个可以智能训练神经网络的流程,需要考虑以下几个关键步骤: 初始化参数:设定初始的batch size和learning rate,以及其他的神经网络参数。训练循环:开始训练过程,每次迭代更新网络的权重。监控loss:在每个训练周期(epoch)后,监控loss的变化情况。动态调整:根据l…...

自然语言处理(02/10):自然语言处理任务和应用程序

一、描述 在广阔的人工智能领域,自然语言处理 (NLP) 是一个迷人而充满活力的领域。NLP 弥合了计算机和人类语言之间的鸿沟,使机器能够理解、解释和生成类似人类的文本。这项变革性技术具有深远的影响,影响着我们日常生…...

Jmeter学习系列之三:测试计划详细介绍

目录 前言 步骤1:启动JMeter窗口 步骤2:添加/删除测试计划元素 步骤3:加载并保存测试计划元素。 步骤4:配置树元素 步骤5:保存JMeter测试计划 步骤6:运行JMeter测试计划...

redis未授权(CVE-2022-0543)

概述 Redis 默认绑定在 0.0.0.0:6379,在未配置防火墙或访问控制的情况下会将服务暴露在公网上。若未设置访问密码(默认通常为空),攻击者可直接未授权访问 Redis。利用 Redis 提供的 CONFIG 命令,攻击者可修改配置并将…...

c/c++的opencv图像金字塔缩放

图像金字塔缩放:OpenCV C/C 实践 📐 图像金字塔是计算机视觉中一种重要且基础的多尺度表示方法。它通过对原始图像进行连续的下采样(缩小)或上采样(放大)操作,生成一系列不同分辨率的图像。这些…...

相机--RGB相机

教程 RGB--深度相机--激光雷达 RGB相机 原理: 仅捕获红(R)、绿(G)、蓝(B)三通道的彩色图像,输出2D像素矩阵,无深度信息。 核心作用: 2D视觉任务&#xff1…...

Oracle的NVL函数

Oracle的NVL函数是一个常用的空值处理函数,主要用于在查询结果中将NULL值替换为指定的默认值。以下是关于NVL函数的详细说明: ‌基本语法‌ NVL(expr1, expr2) 如果expr1为NULL,则返回expr2如果expr1不为NULL,则返回expr1本身 ‌…...

MySQL大表结构变更利器:pt-online-schema-change原理与实战指南

MySQL大表结构变更利器:pt-online-schema-change原理与实战指南 MySQL数据库运维中,最令人头疼的问题之一莫过于对大表进行结构变更(DDL操作)。传统的ALTER TABLE操作会锁表,导致业务长时间不可用,这在724小时运行的互联网业务中是不可接受的。本文将深入剖析Percona To…...

【笔记】Windows 系统安装 Scoop 包管理工具

#工作记录 一、问题背景 在进行开源项目 Suna 部署过程中,执行设置向导时遭遇报错:❌ Supabase CLI is not installed. 根据资料检索,需通过 Windows 包管理工具Scoop安装 Supabase CLI。 初始尝试以管理员身份运行 PowerShell 安装 Scoop…...

PyQt6基础_QtCharts绘制横向柱状图

前置: pip install PyQt6-Charts 结果: 代码: import sysfrom PyQt6.QtCharts import (QBarCategoryAxis, QBarSet, QChart,QChartView, QValueAxis,QHorizontalBarSeries) from PyQt6.QtCore import Qt,QSize from PyQt6.QtGui import QP…...

(四) 本地YARN集群的部署

一、部署说明 Hadoop YARN分布式资源调度,会启动: ResourceManager进程作为管理节点NodeManager进程作为工作节点ProxyServer、JobHistoryServer这两个辅助节点 二、配置文件 在 $HADOOP_HOME/etc/hadoop 文件夹内,修改: 1.m…...

【数据结构】--二叉树--堆(上)

一、树的概念和结构 概念: 树是一种非线性的数据结构,他是由n(n>0)个有限结点组成一个具有层次关系的集合。其叫做树,是因为他倒过来看就和一棵树差不多,其实际上是根在上,树枝在下的。 树的特点: 1…...

Allegro X PCB设计小诀窍--05.如何在Allegro X中实现隐藏电源飞线效果

背景介绍:在PCB设计过程中,布线初期印制板上的飞线错综复杂,信号线和电源线混合交错,但是实际上对于多层板来说,电源的网络一般是通过电源层铺铜连接的,很少需要走线,这样混乱的情况会严重影响设…...