Handtrack.js 开源:3行JS代码搞定手部动作跟踪

近日,GitHub上开源了一个名为Handtrack.js的项目,有了它,你只需要3行代码就能用来检测图片中手的动作。

\n

\n

演示地址:https://victordibia.github.io/handtrack.js/#/

\n
\n

运行时:22 FPS,Macbook Pro 2018(2.5 Ghz),Chrome浏览器。13FPS,Macbook Pro 2014(2.2GHz)。

\n
\n

不久之前,一个使用TensorFlow对象检测API跟踪图片中手部动作的实验结果把我震惊到了。我把训练模型和源代码开放了出来。

\n

从那时起,它就被用来开发一些非常有趣的东西,比如:

\n

一个可以帮助孩子进行拼写练习的工具。

\n

一个可以识别手势的插件。

\n

一个乒乓球游戏。

\n

有很多人想要尝试我提供的训练模型,但无法设置好Tensorflow(安装问题、TF版本问题、导出图表,等等)。幸运的是,Tensorflow.js解决了其中的一些安装和发行问题,因为它经过优化,可以在浏览器的标准化环境中运行。为此,我创建了Handtrack.js库。

\n

它可以让开发人员使用经过训练的手部检测模型快速创建手势交互原型。

\n

这个库的目标是隐藏与加载模型文件相关的步骤,为用户提供有用的函数,并允许用户在没有任何ML经验的情况下检测图像中的手,你不需要自己训练模型。

\n

你也无需导出任何图或已保存的模型。你可以直接在Web应用程序中包含handtrack.js(详情如下),然后调用这个库提供的方法。

\n

如何在Web应用程序中使用它?

\n

你可以直接在script标签中包含这个库的URL地址,或者使用构建工具从npm中导入它。

\n

使用script标签

\n

Handtrack.js的最小化js文件目前托管在jsdelivr上,jsdelivr是一个免费的开源CDN,让你可以在Web应用程序中包含任何的npm包。

\n
\u0026lt;script src=\u0026quot;https://cdn.jsdelivr.net/npm/handtrackjs/dist/handtrack.min.js\u0026quot;\u0026gt; \u0026lt;/script\u0026gt;\n
\n

在将上面的script标签添加到html页面后,就可以使用handTrack变量引用handtrack.js,如下所示。

\n
const img = document.getElementById('img');  \nhandTrack.load().then(model =\u0026gt; { \n    model.detect(img).then(predictions =\u0026gt; {\n      console.log('Predictions: ', predictions) // bbox predictions\n    });\n});\n
\n

上面的代码段将打印出通过img标签传入的图像的预测边框,如果换了视频或通过摄像头提交图像帧,那么就可以“跟踪”在每一帧中出现的手。

\n

\n

使用handtrack.js跟踪图像中的手,你可以调用renderPredictions()方法在canvas对象中绘制检测到的边框和源图像。

\n

使用NPM

\n

你可以使用以下命令将handtrack.js作为npm包来安装:

\n
npm install --save handtrackjs\n
\n

下面给出了如何在React应用程序中导入和使用它的示例。

\n
import * as handTrack from 'handtrackjs';\nconst img = document.getElementById('img');\n// Load the model.\nhandTrack.load().then(model =\u0026gt; {\n  // detect objects in the image.\n  console.log(\u0026quot;model loaded\u0026quot;)\n  model.detect(img).then(predictions =\u0026gt; {\n    console.log('Predictions: ', predictions); \n  });\n});\n
\n

\n

Handtrack.js的API

\n

Handtrack.js提供了几种方法。两个主要的方法是load()和detect(),分别用于加载手部检测模型和获取预测结果。

\n

load()方法接受可选的模型参数,允许你控制模型的性能。这个方法以webmodel格式(也托管在jsdelivr上)加载预训练的手部检测模型。

\n

detect()方法接受输入源参数(img、video或canvas对象)并返回图像中手部位置的边框预测结果。

\n
const modelParams = {\n  flipHorizontal: true,   // flip e.g for video \n  imageScaleFactor: 0.7,  // reduce input image size .\n  maxNumBoxes: 20,        // maximum number of boxes to detect\n  iouThreshold: 0.5,      // ioU threshold for non-max suppression\n  scoreThreshold: 0.79,    // confidence threshold for predictions.\n}\nconst img = document.getElementById('img');\nhandTrack.load(modelParams).then(model =\u0026gt; {\n    model.detect(img).then(predictions =\u0026gt; {\n    console.log('Predictions: ', predictions); \n  });\n});\n
\n

预测结果格式如下:

\n
[{\n  bbox: [x, y, width, height],\n  class: \u0026quot;hand\u0026quot;,\n  score: 0.8380282521247864\n}, {\n  bbox: [x, y, width, height],\n  class: \u0026quot;hand\u0026quot;,\n  score: 0.74644153267145157\n}]\n
\n

Handtrack.js还提供了其他辅助方法:

\n
  • \n
  • \n

    model.getFPS():获取FPS,即每秒检测次数;

    \n\n
  • \n

    model.renderPredictions(predictions, canvas, context, mediasource):在指定的画布上绘制边框(和源图像);

    \n\n
  • \n

    model.getModelParameters():返回模型参数;

    \n\n
  • \n

    model.setModelParameters(modelParams):更新模型参数;

    \n\n
  • \n

    dispose():删除模型实例;

    \n\n
  • \n

    startVideo(video):在给定的视频元素上启动摄像头视频流。返回一个promise,可用于验证用户是否提供了视频权限;

    \n\n
  • \n

    stopVideo(video):停止视频流。

    \n\n
\n

库大小和模型大小

\n

库大小为810 KB,主要是因为它与tensorflow.js库捆绑在一起(最新版本存在一些未解决的问题)。

\n

模型大小为18.5 MB,在初始加载页面时需要等待一会儿。TF.js模型通常分为多个文件(在本例中为四个4.2 MB的文件和一个1.7 MB的文件)。

\n

工作原理

\n

Handtrack.js使用了Tensorflow.js库,一个灵活而直观的API,用于在浏览器中从头开始构建和训练模型。它提供了一个低级的JavaScript线性代数库和一个高级的层API。

\n

创建Handtrack.js库

\n

\n
创建基于Tensorflow.js的JavaScript库的步骤
\n

数据汇编

\n

这个项目中使用的数据主要来自Egohands数据集。其中包括4800张人手的图像,带有边框,使用谷歌眼镜捕获。

\n

模型训练

\n

使用Tensorflow对象检测API训练模型。对于这个项目,我们使用了Single Shot MultiBox Detector和MobileNetV2架构。然后将训练好的模型导出为savedmodel。

\n

模型转换

\n

Tensorflow.js提供了一个模型转换工具,可以用它将savedmodel转换为可以在浏览器中加载的webmodel格式。最后,在转换过程中删除了对象检测模型图的后处理部分。这个优化可以让检测和预测操作的速度加倍。

\n

库的包装和托管

\n

这个库由一个主类组成,这个类提供了一些用于加载模型、检测图像的方法以及一组其他有用的函数,例如startVideo、stopVideo、getFPS()、renderPredictions()、getModelParameters()、setModelParameters(),等等。方法的完整描述可以在Github上找到.

\n

然后使用rollup.js捆绑源文件,并在npm上发布(包括webmodel文件)。目前Handtrack.js与Tensorflow.js(v0.13.5)捆绑在一起,主要是因为在编写这个库的时候,Tensorflow.js(v0.15)在加载图像/视频标签为张量时会发生类型错误。如果新版本修复了这个问题,我也将更新到最新版本。

\n

什么时候应该使用Handtrack.js?

\n

如果你对基于手势的交互式体验感兴趣,Handtrack.js可能会很有用。用户不需要使用任何额外的传感器或硬件就可以立即获得基于手势的交互体验。

\n

\n

下面列出了一些(并非所有)相关的场景:

\n
  • \n
  • \n

    将鼠标移动映射到手部移动,达到控制的目的。

    \n\n
  • \n

    当手和其他物体重叠时可以表示某些有意义的交互信号(例如触碰物体或选择物体)。

    \n\n
  • \n

    人手运动可以作为某些动作识别的代理(例如,自动跟踪视频或图像中下棋或打高尔夫球的动作),或者知识简单地计算图像或视频中出现了多少人。

    \n\n
  • \n

    互动艺术装置,一组有趣的交互式艺术装置控件。

    \n\n
  • \n

    教授他人ML/AI知识。Handtrack.js库提供了一个很有意思的界面,用于演示模型参数的变化(置信度阈值、IoU阈值、图像大小等)如何影响检测结果。

    \n\n
  • \n

    创建演示,任何人都可以轻松运行或体验这些东西。

    \n\n
\n

\n

局限性

\n

浏览器是单线程的:所以必须确保预测操作不会阻塞UI线程。每个预测可能需要50到150毫秒,所以用户会注意到这个延迟。在将Handtrack.js集成到每秒需要多次渲染整个屏幕的应用程序中时(例如游戏),我发现有必要减少每秒的预测数量。

\n

逐帧跟踪手部动作:如果想要跨帧识别手势,需要编写额外的代码来推断手在进入、移动和离开连续帧时的ID。

\n

不正确的预测:偶尔会出现不正确的预测(有时候会将脸检测为手)。我发现,不同的摄像头和光线条件都需要不同的模型参数设置(尤其是置信度阈值)才能获得良好的检测效果。更重要的是,这个可以通过额外的数据进行改进。

\n

下一步

\n

Handtrack.js代表了新形式AI人机交互的早期阶段。在浏览器方面已经有一些很好的想法,例如用于人体姿势检测的posenet。

\n

以及用于在浏览器中检测面部表情的handsfree.js。

\n

与此同时,我将在以下这些方面花更多的时间:

\n

创建更好的模型:创建一个强大的基准来评估底层的手部模型。收集更多可提高准确性和稳定性的数据。

\n

额外的词汇表:在构建样本时,我发现这种交互方法的词汇表很有限。最起码还需要支持更多的状态,比如拳头和摊开的手掌。这意味着需要重新标记数据集(或使用一些半监督方法)。

\n

额外的模型量化:现在,我们使用的是MobilenetV2。是否还有更快的解决方案?

\n

英文原文:https://hackernoon.com/handtrackjs-677c29c1d585

\n

更多内容,请关注前端之巅。

\n

\n

你可能感兴趣的:(Handtrack.js 开源:3行JS代码搞定手部动作跟踪)