了解下handsfree.js-集成手势面部表情的前端库

一 介绍

Handsfree是一个通过计算机视觉集成手势,面部表情和各种姿势识别的前端库。其核心ai技术用到了tensorflow,可在浏览器上触发交互事件,比如滚动网页,检测人脸并展示相关表情,控制桌面游戏。也可以通过websocket接口控制任意与电脑连接的设备。

原来这个库有详细的文档和相关代码示例,但不清楚为什么最近都找不到了,作者也很多年没有更新了,这个库使用起来比较简单,所以抽时间整理下,也有相关其他库可替代,比如Handtrack.js,用来检测人手部动作。

二 使用方法

初始化

  1. 在 DOM 中包含 Handsfree.js JavaScript 和样式表即可。

    ini 复制代码
    <link rel="stylesheet" href="https://unpkg.com/handsfree@8.5.1/build/lib/assets/handsfree.css" />
     <script src="https://unpkg.com/handsfree@8.5.1/build/lib/handsfree.js"></script>

    引用后会将Handsfree类以及指针的基本样式添加到页面中。下一步是创建一个实例Handsfree

    arduino 复制代码
    const config = {
      showDebug: true,
      hands: true
    }
    const handsfree = new Handsfree(config)
    handsfree.start()
  1. 使用npm

    yaml 复制代码
    npm i handsfree
    handsfree = new Handsfree({
      showDebug: true,
      hands: {
        enabled: true
      }
    })
    handsfree.start()

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

handsfree可添加插件,例如下面的 consoleLogger,可打印instance实例,获取很多有用信息的属性。

javascript 复制代码
handsfree.start()
handsfree.use('consoleLogger', (instance) => {
  console.log(instance.head.pointer.x)
  console.log(instance.head.pointer.y)
})

元素类名

当页面状态发生变化的时候,body标签会自动加上class类名,或者加上显隐状态

csharp 复制代码
handsfree-show-when-stopped handsfree-hide-when-loading // 默认隐藏loading,没有开启时展示开始按钮
handsfree-show-when-started handsfree-hide-when-loading // 默认隐藏loading,当开始运行时展示停止按钮

三 代码示例

可复制代码在电脑跑下看看效果,开启摄像头权限后,用手捏住上下滑动即可滑动对应的dom节点背景图。

xml 复制代码
<head>
  <!-- Include Handsfree.js -->
  <link rel="stylesheet" href="https://unpkg.com/handsfree@8.5.1/build/lib/assets/handsfree.css" />
  <script src="https://unpkg.com/handsfree@8.5.1/build/lib/handsfree.js"></script>
  <style>
    .handsfree-canvas-video {
      background: #000;
      opacity: 0.1;
    }
  </style>
</head>
​
<body>
  <!-- Start/stop button with helper classes -->
  <div class="text-center">
    <button class="handsfree-show-when-stopped handsfree-hide-when-loading" onclick="toggleModel('hands')">Start Hand Tracking</button>
    <button class="handsfree-show-when-loading" disabled>Loading ...</button>
    <button class="handsfree-show-when-started handsfree-hide-when-loading" onclick="handsfree.stop()">Stop Handsfree</button>
  </div>
  
  <!-- Pincher table with helper classes to toggle things on/off -->
  <section>
    <h1>Pinch fingers and drag to scroll the area under the pointers.</h1>
    
    <table class="multi-hand-scrollers">
      <tr>
        <td width="50%"><div><div></div></div></td>
        <td width="50%"><div><div></div></div></td>
      </tr>
      <tr>
        <td width="50%"><div><div></div></div></td>
        <td width="50%"><div><div></div></div></td>
      </tr>
    </table>
​
    <!-- We'll have the debugger injected into here -->
    <div id="debugger-holder"></div>
  </section>
  
  <!-- Instantiate and start it -->
  <script>
    const handsfree = new Handsfree({
      showDebug: true,
      setup: {
        wrap: {
          $parent: document.querySelector('#debugger-holder')
        }
      }
    })
    handsfree.enablePlugins('browser')
​
    function toggleModel(name) {
      const config = {}
      config[name] = !handsfree.model[name].enabled
      config.autostart = true
      handsfree.update(config)
    }
  </script>
​
  <!-- Demo styles -->
  <style>
    button {
      font-size: 1em;
      padding: .5em;
    }
    
    h1, table {
      margin-top: 60px;
    }
    
    section {
      width: 800px;
      max-width: 100%;
      margin: auto;
    }
​
    table {
      width: 100%
    }
    
    .finger-pincher {
      display: inline-block;
      width: 32px;
      height: 32px;
      border-radius: 32px;
      background: #000;
      margin: auto;
    }
    .finger-pincher:last-child {
      background: #f00;
    }
​
    .text-center {
      text-align: center;
    }
  
    table {
      width: 100%;
      display: table;
      table-layout: fixed;
    }
    .multi-hand-scrollers td {
      padding: 0;
    }
    .multi-hand-scrollers td > div {
      max-height: 300px;
      overflow: auto;
    }
    .multi-hand-scrollers td > div > div {
      height: 1000px;
      width: 1000px;
      background: url("https://i.imgur.com/W4ja4fR.png");
      background-repeat: space;
      background-size: 32px;
      opacity: 0.25;
    }
  </style>
</body>

作者的其他示例

四 局限性

浏览器是单线程的:所以必须确保预测操作不会阻塞 UI 线程。每个预测可能需要 50 到 150 毫秒,所以用户会注意到这个延迟。

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

不正确的预测:偶尔会出现不正确的预测(有时候会将脸检测为手)或者同时捏住三根手指的时候无法正确判断。而且不同的摄像头和光线条件都需要不同的模型参数设置(尤其是置信度阈值)才能获得良好的检测效果。

相关推荐
kyriewen3 小时前
别再 console.log 了:5 个 Chrome DevTools 调试技巧,用过就回不去了
前端·javascript·面试
IT_陈寒5 小时前
Python搞不定字符串编码?这破玩意坑我两小时!
前端·人工智能·后端
DigitalOcean6 小时前
Laravel 开发者已在 DigitalOcean 上开通超过 10 万台服务器
前端·laravel
星始流年7 小时前
从 Tool 到 Skill——基于 LangChain 的服务端Skill实现
前端·langchain·agent
李惟7 小时前
开源本地通信库,纯客户端 RPC,像聊天一样通信
前端
YAwu117 小时前
深入解析 React 炫彩鼠标跟随标题组件:从坐标定位到动画性能
前端·react.js
GuWenyue7 小时前
排序效率低?5分钟吃透快速排序,性能飙升至O(nlogn)
前端·javascript·面试
OpenTiny社区7 小时前
🎨 看完 GenUI SDK 源码我悟了!
前端·vue.js·github
叁两7 小时前
前端转型AI Agent该如何学习?(前置篇)
前端·人工智能·node.js
何时梦醒7 小时前
深入理解递归与快速排序 —— 从基础入门到手写实现
前端·javascript