Handtrack.js库实现实时监测手部运动(推荐)

yizhihongxing

下面我将详细介绍如何使用Handtrack.js库实现实时监测手部运动。

1. 简介

Handtrack.js是一个基于Tensorflow.js的开源JavaScript库,用于实时监测手部运动。它使用深度学习模型实现手部位置的检测,并可以通过调用API实时对手部位置进行跟踪。Handtrack.js可以在浏览器中运行,而无需安装任何其他软件。

2. 前提条件

在使用Handtrack.js之前,你需要了解HTML、CSS和JavaScript语言,并具备一定的编程基础。

3. 安装Handtrack.js

在使用Handtrack.js之前,你需要先将其安装到你的项目中。你可以使用npm或直接下载前端JS文件进行安装。在这里,我们介绍如何通过npm安装Handtrack.js:

  1. 在终端中,进入你的项目所在的目录。
  2. 运行以下命令,安装Handtrack.js:

npm install handtrackjs

  1. 等待安装完成后,在你的项目中引入手部跟踪库:

javascript
import * as handTrack from 'handtrackjs';

4. 使用Handtrack.js

使用Handtrack.js需要以下几个步骤:

4.1 加载模型

首先,需要在你的HTML文件中引入Handtrack.js的模型文件。你可以在下面的GitHub链接中找到预训练的模型(model.json、metadata.json和weights.bin):

https://github.com/victordibia/handtracking

你只需要将这三个文件下载并保存到你的项目中,然后在HTML文件中引用它们即可:

<script src="path/to/model.json"></script>
<script src="path/to/metadata.json"></script>
<script src="path/to/weights.bin"></script>

然后,使用以下代码加载模型:

const model = await handTrack.load({
  model: 'path/to/model.json',
  metadata: 'path/to/metadata.json',
  weights: 'path/to/weights.bin'
});

4.2 检测手部位置

加载模型后,你可以使用以下代码来检测手部位置:

const video = document.createElement('video');
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

navigator.mediaDevices.getUserMedia({video: true}).then(stream => {
  video.srcObject = stream;
  video.play();
});

video.addEventListener('loadeddata', async () => {
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;

  const predictions = await model.detect(video);
  predictions.forEach(prediction => {
    const {x, y, width, height} = prediction.bbox;
    ctx.strokeRect(x, y, width, height);
  });

  requestAnimationFrame(() => {
    this.detectHands(video, model);
  });
});

这段代码会创建一个video元素和一个canvas元素,并从摄像头中获取视频流。然后,将视频流绘制到canvas元素上,并使用Handtrack.js的API检测手部位置并将其绘制到canvas上。

4.3 实时跟踪手部位置

要实现实时跟踪手部位置,你需要对检测代码进行轮询,并在检测新的手部位置时更新canvas元素。以下是一个示例:

let startTime = new Date().getTime();

async function detectHands(video, model) {
  const currentTime = new Date().getTime();
  if (currentTime - startTime >= 100) {
    startTime = currentTime;

    const predictions = await model.detect(video);
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');

    ctx.clearRect(0, 0, canvas.width, canvas.height);
    predictions.forEach(prediction => {
      const {x, y, width, height} = prediction.bbox;
      ctx.strokeRect(x, y, width, height);
    });
  }

  requestAnimationFrame(() => {
    this.detectHands(video, model);
  });
}

这段代码将轮询Handtrack.js的API,每隔约100毫秒检测一次手部位置。如果有新的手部位置,则将其绘制到canvas元素上。

5. 示例代码

下面是两个使用Handtrack.js检测手部位置的示例代码:

5.1 手势识别

这个示例演示了如何识别简单的手势,例如“OK”和“心形”:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Handtrack.js Gesture Recognition</title>
  <script src="path/to/handtrack.js"></script>
</head>
<body>
  <video id="video" width="640" height="480" autoplay></video>
  <canvas id="canvas" width="640" height="480"></canvas>
  <script>
    const video = document.getElementById('video');
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');

    const model = await handTrack.load({
      model: 'path/to/model.json',
      metadata: 'path/to/metadata.json',
      weights: 'path/to/weights.bin'
    });

    navigator.mediaDevices.getUserMedia({video: true}).then(stream => {
      video.srcObject = stream;
      video.play();
    });

    video.addEventListener('loadeddata', async () => {
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;

      requestAnimationFrame(() => {
        detectHands(video, model);
      });
    });

    async function detectHands(video, model) {
      const predictions = await model.detect(video);
      const okEmoji = '\u{1F44C}';
      const heartEmoji = '\u2764\uFE0F';

      predictions.forEach(prediction => {
        const {x, y, width, height} = prediction.bbox;
        ctx.strokeRect(x, y, width, height);

        if (width > 100 && height > 100) {
          const centerX = x + width / 2;
          const centerY = y + height / 2;

          if (centerX > video.videoWidth / 2 - 50 && centerX < video.videoWidth / 2 + 50
            && centerY > video.videoHeight / 2 - 50 && centerY < video.videoHeight / 2 + 50) {
            ctx.font = '48px serif';
            ctx.fillText(okEmoji, centerX, centerY);

          } else if (centerX > video.videoWidth / 2 - 100 && centerX < video.videoWidth / 2
            && centerY > video.videoHeight / 2 - 100 && centerY < video.videoHeight / 2) {
            ctx.font = '48px serif';
            ctx.fillText(heartEmoji, centerX, centerY);
          }
        }
      });

      requestAnimationFrame(() => {
        detectHands(video, model);
      });
    }
  </script>
</body>
</html>

5.2 点击和拖拽

这个示例演示了如何使用鼠标来拖动一个元素,并使用Handtrack.js检测手动是否放下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Handtrack.js Click and Drag</title>
  <style>
    #box {
      width: 100px;
      height: 100px;
      background-color: red;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
  </style>
  <script src="path/to/handtrack.js"></script>
</head>
<body>
  <video id="video" width="640" height="480" autoplay></video>
  <canvas id="canvas" width="640" height="480"></canvas>

  <div id="box"></div>

  <script>
    const video = document.getElementById('video');
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');

    const model = await handTrack.load({
      model: 'path/to/model.json',
      metadata: 'path/to/metadata.json',
      weights: 'path/to/weights.bin'
    });

    navigator.mediaDevices.getUserMedia({video: true}).then(stream => {
      video.srcObject = stream;
      video.play();
    });

    let isHandDown = false;
    let mouseX = 0;
    let mouseY = 0;

    video.addEventListener('loadeddata', async () => {
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;

      requestAnimationFrame(() => {
        detectHands(video, model);
      });
    });

    async function detectHands(video, model) {
      const predictions = await model.detect(video);
      const box = document.getElementById('box');

      predictions.forEach(prediction => {
        const {x, y, width, height} = prediction.bbox;
        ctx.strokeRect(x, y, width, height);

        if (width > 100 && height > 100) {
          const centerX = x + width / 2;
          const centerY = y + height / 2;

          mouseX = centerX;
          mouseY = centerY;

          const isHandUp = centerY < video.videoHeight / 2;

          if (isHandUp && !isHandDown) {
            isHandDown = true;
            box.style.backgroundColor = 'green';
            box.style.cursor = 'grabbing';
            box.style.userSelect = 'none';
            box.onmousedown = function(event) {
              event.preventDefault();
              box.style.position = 'absolute';

              box.style.left = event.pageX - box.offsetWidth / 2 + 'px';
              box.style.top = event.pageY - box.offsetHeight / 2 + 'px';

              const moveHandler = function(event) {
                box.style.left = event.pageX - box.offsetWidth / 2 + 'px';
                box.style.top = event.pageY - box.offsetHeight / 2 + 'px';
              };

              const upHandler = function() {
                isHandDown = false;
                box.style.backgroundColor = 'red';
                box.style.cursor = 'grab';
                box.style.userSelect = 'auto';
                document.removeEventListener('mousemove', moveHandler);
                document.removeEventListener('mouseup', upHandler);
              };

              document.addEventListener('mousemove', moveHandler);
              document.addEventListener('mouseup', upHandler);
            };
          } else if (!isHandUp && isHandDown) {
            isHandDown = false;
          }
        }
      });

      if (isHandDown) {
        box.style.left = mouseX - box.offsetWidth / 2 + 'px';
        box.style.top = mouseY - box.offsetHeight / 2 + 'px';
      }

      requestAnimationFrame(() => {
        detectHands(video, model);
      });
    }
  </script>
</body>
</html>

这个代码块创建了一个红色的盒子,当你将手举起并放下时,盒子开始变绿色,并且你可以使用鼠标拖动它。当你将手提起时,盒子变为红色,不能拖动。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Handtrack.js库实现实时监测手部运动(推荐) - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • JS冷知识之不起眼但有用的String.raw方法

    下面是关于JS中String.raw方法的详细讲解。 String.raw方法是什么 String.raw 是一个 ES6 引入的模板字符串的标签函数(tagged template)。当标签函数使用在模板字符串上时,该模板字符串中所有的转义字符都不会被转义,而是作为字符串的普通字符被输出。 用法示例 下面我们通过两个实际的示例来说明 String.raw …

    JavaScript 2023年5月28日
    00
  • JS面向对象编程浅析

    JS面向对象编程浅析 在JavaScript中,面向对象编程(Object-Oriented Programming,OOP)是一种非常常见的编程思想。OOP的核心概念是“对象”,它可以把一系列的数据和行为聚合在一起,形成一个具有特定功能的“物体”。本文将会从以下几点详细讲解JavaScript面向对象编程的相关知识。 面向对象的基本概念 类和对象 类(Cl…

    JavaScript 2023年5月18日
    00
  • JS中使用正则表达式g模式和非g模式的区别

    使用正则表达式(RegEx)是JavaScript中的一个重要功能,它可以让我们在字符串中搜索并匹配特定的模式。JS中的正则表达式还有两种匹配模式:g模式和非g模式。在本文中,我们将详细讲解这两种模式的区别。 什么是正则表达式g模式和非g模式? 在JS中,我们通过在正则表达式文本后添加一个标志来指定其模式。g模式和非g模式具有以下区别: g模式 g模式代表全…

    JavaScript 2023年6月10日
    00
  • javascript中字符串替换函数replace()方法与c# 、vb 替换有一点不同

    下面详细解释 JavaScript 中的字符串替换函数 replace() 方法与 C#、VB 替换的不同之处。 JavaScript 中的 replace() 方法可以接收两个参数,第一个参数是被查找的字符串,第二个参数是用来替换查找到的字符串的字符串。通过这个方法,我们可以用一个字符串替换另一个字符串中的子串。 C#、VB 中的字符串替换方法也类似,在 …

    JavaScript 2023年5月28日
    00
  • JavaScript将数字转换成大写中文的方法

    将数字转换成大写中文是个很实用的功能,在前端开发中经常会遇到这样的需求。以下是详细的攻略: 方案一:使用中文数字字典映射 将数字转换成大写中文可以先通过一个中文数字字典进行映射,然后依次读取数字,并获取对应的中文数字,最后将其拼接成一个字符串即可。 以JavaScript为例,可以编写以下代码: function convertToChinese(num) …

    JavaScript 2023年6月11日
    00
  • Microsoft Flow | 微信 | LDP 整合开发

    我们在使用自己的企业应用平台时,经常会遇到以下场景: 场景1 业务系统的通知太多,希望收到通知时同步发送企业微信来随时查看。 场景2 需要和其他ERP、BI、CRM等系统对接。 通常的解决方案是自行开发一套程序来实现平台到微信的同步功能。 如果这样做,我们就需要域名空间,要学会搭建web服务器,要github备份维护代码,要当心漏洞被攻击,要编写复杂的代码。…

    JavaScript 2023年4月18日
    00
  • 探索浏览器页面关闭window.close()的使用详解

    探索浏览器页面关闭window.close()的使用详解 前言 window.close() 是一个关闭当前浏览器窗口的JavaScript方法。但是,由于该方法具有一些限制,因此在使用它时需要非常小心。在本文中,我们将深入讨论 window.close() 方法。除此之外,还将探讨如何在浏览器中打开和关闭窗口,以及如何在窗口之间传递数据。 打开新窗口 使用…

    JavaScript 2023年6月11日
    00
  • 使用JavaScript 实现各种跨域的方法

    使用JavaScript实现跨域的方法通常分为以下几种: 1. JSONP JSONP(JSON with Padding)是在跨域访问时比较流行的一种方式,它不是通过XHR请求数据,而是利用 <script> 标签可以访问不同域名下的资源的特性来实现。 实现原理 在A域下使用script标签请求B域下的数据: <script src=&q…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部