王淑婷 路雪参与

TF官方博客:基于TensorFlow.js框架的浏览器实时姿态估计

TensorFlow 近日发布 TensorFlow.js 版本 PoseNet,该版本 PoseNet 只要电脑或手机配备了适当的网络摄像头,就可以直接在网页浏览器中进行体验。该模型源代码已开放,Javascript 开发者只需几行代码就可以修补和使用该技术。

通过与谷歌创意实验室合作,TensorFlow 近日发布了 TensorFlow.js 版的 PoseNet。这是一款机器学习模型,可以在浏览器中实时估计人体姿态。

模型 Demo:https://storage.googleapis.com/tfjs-models/demos/posenet/camera.html

PoseNet 可以利用单姿态或多姿态算法检测图像和视频中的人物,而所有这些都可以在浏览器中实现。

那么姿态估计到底是什么呢?该计算机视觉技术检测图像和视频中人物,以确定诸如某人的肘部在图像中的位置。要明确的是,这种技术不会识别图像中的人——没有与姿态检测相关联的个人可识别信息,而只是简单地估计关键身体部位的位置。

它为什么如此振奋人心?姿态估计有很多用途,从对身体作出反应的交互式装置到增强现实、动画、健身等。TensorFlow 希望该模型的可访问性能够鼓励更多的开发者和制造者在自己独特的项目中进行姿态检测实验和应用。虽然很多其他的姿态检测系统已经开源,但这些系统都需要专门的硬件和/或摄像头,以及相当多的系统设置。而基于 TensorFlow.js 框架运行的 PoseNet,只要电脑或手机配备了适当的网络摄像头,你就可以直接在网页浏览器中体验这一技术。TensorFlow 已经开放了该模型的源代码,因此 Javascript 开发者只需几行代码就可以修补和使用该技术。此外,这项技术实际上有助于保护用户隐私。自从基于 TensorFlow.js 的 PoseNet 在浏览器中运行以来,没有用户的姿态数据泄露。

PoseNet 了解一下

PoseNet 可用于估计单个姿态或多个姿态,这意味着有两种算法,一种仅能检测图像/视频中的一个人,而另一种可以检测图像/视频中的多个人。为什么要有两个版本?单人姿态检测器更快、更简单,但要求图像中只能出现一个目标。我们先讨论单姿态,因为它更容易理解。

简单而言,姿态估计分两个阶段进行:

  1. 将 RGB 图像作为输入馈送到卷积神经网络中。

  2. 利用单姿态或多姿态解码算法解码来解码模型输出中的姿态、姿态置信度得分、关键点位置和关键点置信度得分。

但这些关键词是什么意思呢?我们来看几个最重要的词:

  • 姿态——在最高层次上,PoseNet 将返回一个姿态目标,其中包含检测到的每个人物的关键点列表和实例级置信度得分。

PoseNet 返回检测到的每个人和每个姿态关键点的置信度值。图像来源:《Microsoft Coco: Common Objects in Context Dataset》(https://cocodataset.org )

  • 姿态置信度得分——决定姿态估计的总体置信度,范围在 0.0~1.0 之间,可用来隐藏被认为不够明显的姿态。

  • 关键点——人体姿态被估计的一部分,如鼻子、右耳、左膝、右脚等。它包含位置和关键点置信度得分。PoseNet 当前可以检测 17 个关键点,如下图所示:

PoseNet 检测到的 17 个姿态关键点。

  • 关键点置信度得分——决定估计的关键点位置准确的置信度,范围在 0.0~1.0 之间,可用来隐藏被认为不够明显的关键点。

  • 关键点位置——检测到的关键点在原始输入图像中的 2D xy 坐标。

第一步:导入 TensorFlow.js 框架和 PoseNet 库

TensorFlow 团队进行了大量工作来降低模型的复杂度,封装功能使之易于使用。接下来将介绍设置 PoseNet 项目的基础知识。

PoseNet 库可以使用 npm 安装:

  1. npm install @tensorflow-models/posenet

使用 es6 模块导入:

  1. import * as posenet from '@tensorflow-models/posenet';

  2. const net = await posenet.load();

或通过页面中的 bundle 文件导入:

  1. <html>

  2.  <body>

  3.    <!-- Load TensorFlow.js -->

  4.    <script src="https://unpkg.com/@tensorflow/tfjs"></script>

  5.    <!-- Load Posenet -->

  6.    <script src="https://unpkg.com/@tensorflow-models/posenet">

  7.    </script>

  8.    <script type="text/javascript">

  9.      posenet.load().then(function(net) {

  10.        // posenet model loaded

  11.      });

  12.    </script>

  13.  </body>

  14. </html>

第二步(上):单人姿态估计

应用于图像的单人姿态估计算法示例。图像来源:《Microsoft Coco: Common Objects in Context Dataset》(https://cocodataset.org)

如前所述,单姿态估计算法是两者中较简单也较快速的。理想的使用场景是当输入的图像或视频中只有一个人时使用这种算法。其缺点在于,如果图像中有多个人,则来自两个人的关键点可能被估计为同一个姿态的一部分——这意味着,A 的左臂和 B 的右膝可能被该算法归为同一姿态。因此,如果输入的图像可能包含多人,则应当使用多姿态估计算法。

让我们看一下单姿态估计算法的输入:

  • 输入图像元素——一种 html 元素,包含要为诸如视频或图像标签预测姿态的图像。重点是,输入的图像或视频元素应为正方形。

  • 图像比例因子——介于 0.2~1 的数字,默认值为 0.50。用于在向网络输送图像之前,对图像进行缩放。将此数字设置得较低,以缩小图像,提高输送至网络的速度,不过这是以准确率为代价的。

  • 水平翻转——默认值为 false,在姿态需要水平翻转/镜像的情况下。而对于默认情况为水平翻转的视频(即网络摄像头),且你希望姿态以正确方向返回,应将水平翻转设置为 true。

  • 输出步幅——必须为 32、16 或 8。默认值为 16。从内部来看,该参数影响神经网络中层的高度和宽度。在较高层次上,它会影响姿态估计的准确率和速度。输出步幅的值越低,准确率越高,但速度越慢;输出步幅值越高,速度越快,但准确率越低。查看输出步幅对输出质量影响的最佳方法是使用单姿态估计算法 demo:https://storage.googleapis.com/tfjs-models/demos/posenet/camera.html。

现在,我们看一下单姿态估计算法的输出:

  • 每个姿态包含姿态置信度得分和 17 个关键点。

  • 每个关键点包含其位置和置信度得分。同样,所有关键点位置在输入图像空间中都有 xy 坐标,并且可以直接映射到图像上。

以下简短的代码块展示了如何使用单姿态估计算法:

  1. const imageScaleFactor = 0.50;

  2. const flipHorizontal = false;

  3. const outputStride = 16;

  4. const imageElement = document.getElementById('cat');

  5. // load the posenet model

  6. const net = await posenet.load();

  7. const pose = await net.estimateSinglePose(imageElement, scaleFactor, flipHorizontal, outputStride);

输出姿态示例如下所示:

  1. {

  2.  "score": 0.32371445304906,

  3.  "keypoints": [

  4.    { // nose

  5.      "position": {

  6.        "x": 301.42237830162,

  7.        "y": 177.69162777066

  8.      },

  9.      "score": 0.99799561500549

  10.    },

  11.    { // left eye

  12.      "position": {

  13.        "x": 326.05302262306,

  14.        "y": 122.9596464932

  15.      },

  16.      "score": 0.99766051769257

  17.    },

  18.    { // right eye

  19.      "position": {

  20.        "x": 258.72196650505,

  21.        "y": 127.51624706388

  22.      },

  23.      "score": 0.99926537275314

  24.    },

  25.    ...

  26.  ]

  27. }

第二步(下):多人姿态估计

应用于图像的多人姿态估计算法示例。图像来源:「Microsoft Coco: Common Objects in Context Dataset」(https://cocodataset.org)

多人姿态估计算法可以估计一个图像中的多个人/姿态。它比单姿态算法更复杂更慢,但其优点是,如果一张图像中出现多个人物,则检测到的关键点不太可能关联至不匹配的姿态。因此,即使是用来检测一个人的姿态,该算法可能也更理想。

此外,该算法还有一个不错的特性——其性能不受输入图像中人数的影响。无论有 15 个还是 5 个人要检测,它的计算时间都一样。

我们来看一下输入:

  • 输入图像元素——与单姿态估计相同。

  • 图像比例因子——与单姿态估计相同。

  • 水平翻转——与单姿态估计相同。

  • 输出步幅——与单姿态估计相同。

  • 最大姿态检测——整数,默认值为 5。表示可检测的最大姿态数量。

  • 姿态置信度得分阈值——0.0~1.0,默认值为 0.5。在较高层次上,它控制返回姿态的最小置信度得分。

  • 非极大值抑制(NMS)半径——以像素为单位。在较高水平上,它控制返回姿态之间的最小距离。默认值为 20,适用于大多数情况。只有在调整姿态置信度得分不够好的情况下,应该增加/减少其数值,以过滤不太精确的姿态。

查看这些参数影响的最佳方法是使用多姿态估计 demo(https://storage.googleapis.com/tfjs-models/demos/posenet/camera.html)。

让我们查看一下输出:

  • 解决多姿态估计问题。

  • 每个姿态包含与单人姿态估计算法相同的信息。

以下简短的代码块展示了如何使用多姿态估计算法:

  1. const imageScaleFactor = 0.50;

  2. const flipHorizontal = false;

  3. const outputStride = 16;

  4. // get up to 5 poses

  5. const maxPoseDetections = 5;

  6. // minimum confidence of the root part of a pose

  7. const scoreThreshold = 0.5;

  8. // minimum distance in pixels between the root parts of poses

  9. const nmsRadius = 20;

  10. const imageElement = document.getElementById('cat');

  11. // load posenet

  12. const net = await posenet.load();

  13. const poses = await net.estimateMultiplePoses(

  14.  imageElement, imageScaleFactor, flipHorizontal, outputStride,    

  15.   maxPoseDetections, scoreThreshold, nmsRadius);

多姿态输出示例如下:

  1. // array of poses/persons

  2. [

  3.  { // pose #1

  4.    "score": 0.42985695206067,

  5.    "keypoints": [

  6.      { // nose

  7.        "position": {

  8.          "x": 126.09371757507,

  9.          "y": 97.861720561981

  10.         },

  11.        "score": 0.99710708856583

  12.      },

  13.      ...

  14.    ]

  15.  },

  16.  { // pose #2

  17.    "score": 0.13461434583673,

  18.    "keypositions": [

  19.      { // nose

  20.        "position": {

  21.          "x": 116.58444058895,

  22.          "y": 99.772533416748

  23.        },

  24.      "score": 0.9978438615799

  25.      },

  26.      ...

  27.    ]

  28.  },

  29.  ...

  30. ]

读完以上内容,你对 PoseNet demo 已经有了足够的了解,阅读止于此处也是一个不错的选择。但如果想进一步了解模型和实现的技术细节,可继续阅读以下内容。

对于好奇的大脑来说,这是一次技术深潜

本节将深入讨论单姿态估计算法的更多技术细节。在较高层次上,其流程如下所示:

使用 PoseNet 的单人姿态检测器流程

需要注意的一个重要细节是,研究人员同时训练了 PoseNet 的 ResNet 模型和 MobileNet 模型。虽然 ResNet 模型具有较高的准确率,但其庞大体积和多层结构使得页面加载时间和推断时间对于任何实时应用来说都不太理想。TensorFlow 采用了 MobileNet 模型,因为它是为移动设备运行而设计的。

再回到单姿态估计算法

处理模型输入:对输出步幅的解释

首先,我们将通过讨论输出步幅来了解 PoseNet 模型输出(主要是热图和偏移向量)。

方便的一点是,PoseNet 模型要求图像尺寸不变,这意味着它可以预测与原始图像相同比例的姿态位置,而不管图像是否被缩小。这也意味着 PoseNet 可以通过在运行时设置输出步幅,以性能为代价获取更高的准确率

输出步幅决定了输出比输入图像缩小的程度,它会影响层的大小和模型输出。输出步幅越高,网络中层的分辨率和输出及其准确率就越小。在此实现中,输出步幅的值可以是 8、16 或 32。换句话说,32 的输出步幅将造成最快的性能、最低的准确率,而 8 将导致最高的准确率、最慢的性能。我们建议从 16 开始。

输出步幅决定了输出比输入图像缩小的程度。输出步幅越高,速度越快,但准确率越低。

实现过程中,当输出步幅被设置为 8 或 16 时,各层中的输入步幅将减少,以创建更大的输出分辨率。然后使用用空洞卷积(atrous convolution)使后续层中的卷积滤波器具有更宽的视野(当输出步幅为 32 时,不使用空洞卷积)。虽然 TensorFlow 支持空洞卷积,但 TensorFlow.js 并不支持,因此我们添加了一个 PR 来弥补这一点。

模型输出:热图和偏移向量(Offset Vector)

当 PoseNet 处理图像时,实际上返回的是热图和偏移向量,我们可对其进行解码,以在图像中找到对应姿态关键点的高置信度区域。下图展示了在较高层次,每个姿态关键点与热图张量和偏移向量张量的关联。

PoseNet 返回的 17 个姿态关键点中每一个都与用于确定关键点确切位置的热图张量和偏移向量张量相关联。

这两个输出都是三维张量,其高度和宽度称为分辨率。根据以下公式,分辨率由输入图像大小和输出步幅确定:

  1. Resolution = ((InputImageSize - 1) / OutputStride) + 1

  2. // Example: an input image with a width of 225 pixels and an output

  3. // stride of 16 results in an output resolution of 15

  4. // 15 = ((225 - 1) / 16) + 1

热图

每个热图是尺寸为分辨率 x 分辨率 x 17 的 3D 张量,17 是 PoseNet 检测到的关键点的数量。例如,对于 225 的图像大小和 16 的输出步幅,热图大小将是 15 x15x 17。(17 个中)第三维的每个切片图对应特定关键点的热图。热图中每个位置具有置信度得分,即该关键点类型的一部分存在于该位置中的概率。我们可以将其看作是把原始图像分割成 15x 15 网格,其中热图得分提供了每个关键点在每个网格正方形中存在可能性的分类。

偏移向量

每个偏移向量是尺寸为分辨率 x 分辨率 x 34 的 3D 张量,34 是关键点数量*2 得出的数字。如果图像大小为 225,输出步幅为 16,则该值为 15x15x34。由于热图是关键点所在位置的近似,因此偏移向量在位置上对应热图点,并且用于预测关键点的确切位置,如通过从相应热图点沿着向量行进。偏移向量的前 17 个切片图包含向量的 x,后 17 个切片包含 y。偏移向量大小与原始图像的比例相同。

根据模型的输出估计姿态

在图像输入到模型后,我们执行一些计算以从输出估计姿态。例如,单姿态估计算法返回姿态置信度得分,该得分本身包含多个关键点(由 part ID 索引),每个关键点具有置信度得分和 xy 位置。

要获取姿态的关键点:

 1. 在热图上进行 sigmoid 激活函数操作,获得得分。

  1. scores = heatmap.sigmoid()

 2. 对关键点置信度得分执行 argmax2d,获得热图中的 x 和 y 索引以及每个部分的最高得分,这基本上是该部分最可能存在的位置。这将产生大小为 17x2 的张量,每行是热图中的 y 和 x 索引以及每个部分的最高得分。

  1. heatmapPositions = scores.argmax(y, x)

 3. 从某部分热图中的 x 和 y 索引的偏移中获取 x 和 y,得到每个部分的偏移向量。这产生大小为 17x2 的张量,其中每行都是对应关键点的偏移向量。例如,对于索引 k 处的部分,当热图位置为 y 和 d 时,偏移向量为:

  1. offsetVector = [offsets.get(y, x, k), offsets.get(y, x, 17 + k)]

 4. 为获得关键点,每个部分的热图 x 和 y 乘以输出步幅,然后再加与原始图像比例相同的相应偏移向量。

  1. keypointPositions = heatmapPositions * outputStride + offsetVectors

 5. 最后,每个关键点置信度得分是其热图位置的置信度得分。姿态置信度得分是关键点得分的平均值。

多人姿态估计

多姿态估计算法的细节不在本文的讨论范围之内。该算法的主要不同之处在于,它使用贪婪过程通过沿着基于部分的图跟随位移向量来将关键点分组。具体而言,它采用了研究论文《PersonLab: Person Pose Estimation and Instance Segmentation with a Bottom-Up, Part-Based, Geometric Embedding Model》中的快速贪婪解码算法(fast greedy decoding algorithm)。有关多姿态算法的更多信息,请阅读完整论文或查看代码。代码地址:https://github.com/tensorflow/tfjs-models/tree/master/posenet/src。


原文链接:https://medium.com/tensorflow/real-time-human-pose-estimation-in-the-browser-with-tensorflow-js-7dd0bc881cd5

工程动作识别计算机视觉JavaScriptTensorFlow
相关数据
增强现实技术

增强现实,是指透过摄影机影像的位置及角度精算并加上图像分析技术,让屏幕上的虚拟世界能够与现实世界场景进行结合与互动的技术。这种技术于1990年提出。随着随身电子产品运算能力的提升,增强现实的用途也越来越广。

激活函数技术

在 计算网络中, 一个节点的激活函数定义了该节点在给定的输入或输入的集合下的输出。标准的计算机芯片电路可以看作是根据输入得到"开"(1)或"关"(0)输出的数字网络激活函数。这与神经网络中的线性感知机的行为类似。 一种函数(例如 ReLU 或 S 型函数),用于对上一层的所有输入求加权和,然后生成一个输出值(通常为非线性值),并将其传递给下一层。

机器学习技术

机器学习是人工智能的一个分支,是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、计算复杂性理论等多门学科。机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。因为学习算法中涉及了大量的统计学理论,机器学习与推断统计学联系尤为密切,也被称为统计学习理论。算法设计方面,机器学习理论关注可以实现的,行之有效的学习算法。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

卷积技术

TensorFlow技术

TensorFlow是一个开源软件库,用于各种感知和语言理解任务的机器学习。目前被50个团队用于研究和生产许多Google商业产品,如语音识别、Gmail、Google 相册和搜索,其中许多产品曾使用过其前任软件DistBelief。

张量技术

张量是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数,这些线性关系的基本例子有内积、外积、线性映射以及笛卡儿积。其坐标在 维空间内,有 个分量的一种量,其中每个分量都是坐标的函数,而在坐标变换时,这些分量也依照某些规则作线性变换。称为该张量的秩或阶(与矩阵的秩和阶均无关系)。 在数学里,张量是一种几何实体,或者说广义上的“数量”。张量概念包括标量、矢量和线性算子。张量可以用坐标系统来表达,记作标量的数组,但它是定义为“不依赖于参照系的选择的”。张量在物理和工程学中很重要。例如在扩散张量成像中,表达器官对于水的在各个方向的微分透性的张量可以用来产生大脑的扫描图。工程上最重要的例子可能就是应力张量和应变张量了,它们都是二阶张量,对于一般线性材料他们之间的关系由一个四阶弹性张量来决定。

计算机视觉技术

计算机视觉(CV)是指机器感知环境的能力。这一技术类别中的经典任务有图像形成、图像处理、图像提取和图像的三维推理。目标识别和面部识别也是很重要的研究领域。

神经网络技术

(人工)神经网络是一种起源于 20 世纪 50 年代的监督式机器学习模型,那时候研究者构想了「感知器(perceptron)」的想法。这一领域的研究者通常被称为「联结主义者(Connectionist)」,因为这种模型模拟了人脑的功能。神经网络模型通常是通过反向传播算法应用梯度下降训练的。目前神经网络有两大主要类型,它们都是前馈神经网络:卷积神经网络(CNN)和循环神经网络(RNN),其中 RNN 又包含长短期记忆(LSTM)、门控循环单元(GRU)等等。深度学习是一种主要应用于神经网络帮助其取得更好结果的技术。尽管神经网络主要用于监督学习,但也有一些为无监督学习设计的变体,比如自动编码器和生成对抗网络(GAN)。

卷积神经网络技术

卷积神经网路(Convolutional Neural Network, CNN)是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现。卷积神经网路由一个或多个卷积层和顶端的全连通层(对应经典的神经网路)组成,同时也包括关联权重和池化层(pooling layer)。这一结构使得卷积神经网路能够利用输入数据的二维结构。与其他深度学习结构相比,卷积神经网路在图像和语音识别方面能够给出更好的结果。这一模型也可以使用反向传播算法进行训练。相比较其他深度、前馈神经网路,卷积神经网路需要考量的参数更少,使之成为一种颇具吸引力的深度学习结构。 卷积网络是一种专门用于处理具有已知的、网格状拓扑的数据的神经网络。例如时间序列数据,它可以被认为是以一定时间间隔采样的一维网格,又如图像数据,其可以被认为是二维像素网格。

准确率技术

分类模型的正确预测所占的比例。在多类别分类中,准确率的定义为:正确的预测数/样本总数。 在二元分类中,准确率的定义为:(真正例数+真负例数)/样本总数

映射技术

映射指的是具有某种特殊结构的函数,或泛指类函数思想的范畴论中的态射。 逻辑和图论中也有一些不太常规的用法。其数学定义为:两个非空集合A与B间存在着对应关系f,而且对于A中的每一个元素x,B中总有有唯一的一个元素y与它对应,就这种对应为从A到B的映射,记作f:A→B。其中,y称为元素x在映射f下的象,记作:y=f(x)。x称为y关于映射f的原象*。*集合A中所有元素的象的集合称为映射f的值域,记作f(A)。同样的,在机器学习中,映射就是输入与输出之间的对应关系。

MobileNets技术

MobileNet是专用于移动和嵌入式视觉应用的卷积神经网络,是基于一个流线型的架构,它使用深度可分离的卷积来构建轻量级的深层神经网络。通过引入两个简单的全局超参数,MobileNet在延迟度和准确度之间有效地进行平衡。MobileNets在广泛的应用场景中有效,包括物体检测、细粒度分类、人脸属性和大规模地理定位。

暂无评论
暂无评论~