亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript實(shí)現(xiàn)手勢(shì)識(shí)別的示例詳解

 更新時(shí)間:2024年12月24日 11:00:46   作者:小噔小咚什么東東  
這篇文章主要為大家詳細(xì)介紹了JavaScrip如何利用?TensorFlow.js?中的?HandPose?模型,實(shí)現(xiàn)一個(gè)基于視頻流的手勢(shì)識(shí)別系統(tǒng),感興趣的可以了解下

利用 TensorFlow.js 中的 HandPose 模型,實(shí)現(xiàn)一個(gè)基于視頻流的手勢(shì)識(shí)別系統(tǒng),通過 HTML5 視頻流獲取攝像頭數(shù)據(jù),并結(jié)合 HandPose 模型來識(shí)別用戶的手勢(shì)。最終的目標(biāo)是能夠通過攝像頭實(shí)時(shí)識(shí)別并顯示手指數(shù)量的手勢(shì)。

項(xiàng)目概述

這個(gè)項(xiàng)目的實(shí)現(xiàn)包括以下幾個(gè)步驟:

  • 獲取視頻流并設(shè)置攝像頭。
  • 加載 HandPose 模型,并顯示加載進(jìn)度。
  • 通過模型識(shí)別手勢(shì)。
  • 基于手指的狀態(tài)輸出對(duì)應(yīng)的手勢(shì)數(shù)字(例如“1”代表一個(gè)手指,“2”代表兩個(gè)手指等)。

獲取視頻流并設(shè)置攝像頭

首先,需要通過瀏覽器的 navigator.mediaDevices.getUserMedia API 獲取用戶的攝像頭視頻流,并在網(wǎng)頁上顯示該視頻流。具體代碼如下:

async function setupCamera() {
  const video = document.getElementById('video');
  const stream = await navigator.mediaDevices.getUserMedia({
    video: true,
  });
  video.srcObject = stream;

  return new Promise((resolve) => {
    video.onloadedmetadata = () => {
      resolve(video);
    };
  });
}

此函數(shù)將視頻流顯示在 HTML 中的 <video> 元素上,并在視頻加載完成后返回該視頻元素。

加載 HandPose 模型并顯示加載進(jìn)度

為了進(jìn)行手勢(shì)識(shí)別,我們需要加載 TensorFlow.js 提供的 HandPose 模型。HandPose 模型是一個(gè)用于估計(jì)手部關(guān)鍵點(diǎn)位置的深度學(xué)習(xí)模型,可以幫助我們識(shí)別手的姿勢(shì)。 在加載 HandPose 模型時(shí),我們希望顯示加載進(jìn)度。這是通過 progressCallback 實(shí)現(xiàn)的,它會(huì)在每次加載進(jìn)度更新時(shí)觸發(fā):

async function loadHandPoseModel() {
  const loadingContainer = document.getElementById('loading-container');
  loadingContainer.style.display = 'block'; // 顯示加載進(jìn)度條

  const model = await handpose.load({
    flipHorizontal: false,  // 不要水平翻轉(zhuǎn)模型
    progressCallback: (fraction) => {
      const progress = Math.round(fraction * 100); // 計(jì)算加載的百分比
      showLoadingProgress(progress); // 更新進(jìn)度條
    }
  });

  loadingContainer.style.display = 'none'; // 隱藏加載進(jìn)度條
  return model;
}

通過此函數(shù),可以實(shí)時(shí)展示模型加載的進(jìn)度條,提升用戶體驗(yàn)。

識(shí)別手勢(shì)

在加載完 HandPose 模型之后,我們就可以使用該模型來識(shí)別手勢(shì)了。模型會(huì)估計(jì)手部的 21 個(gè)關(guān)鍵點(diǎn)位置,并通過這些關(guān)鍵點(diǎn)來推測(cè)手指是否伸展。 我們需要遍歷這些關(guān)鍵點(diǎn),分析每個(gè)手指是否伸出。如果手指的末端關(guān)鍵點(diǎn)(例如食指末端)高于相鄰的關(guān)節(jié)點(diǎn),表示該手指伸展。通過此邏輯,我們可以判斷用戶伸出的手指數(shù)量:

function detectFingers(landmarks) {
  let fingers = 0;

  // 判斷每根手指的伸展情況
  const thumb = landmarks[4];  // 拇指
  const index = landmarks[8];  // 食指
  const middle = landmarks[12];  // 中指
  const ring = landmarks[16];  // 無名指
  const pinky = landmarks[20];  // 小拇指

  if (index[1] < thumb[1]) fingers++;  // 食指伸展
  if (middle[1] < index[1]) fingers++;  // 中指伸展
  if (ring[1] < middle[1]) fingers++;  // 無名指伸展
  if (pinky[1] < ring[1]) fingers++;  // 小拇指伸展

  return fingers;
}

通過此函數(shù),能夠判斷出當(dāng)前用戶伸出的手指數(shù)量。

輸出手勢(shì)結(jié)果

通過識(shí)別出的手指數(shù)量,我們可以展示一個(gè)對(duì)應(yīng)的數(shù)字手勢(shì)。例如,如果用戶伸出一個(gè)手指,我們顯示“1”;如果伸出兩個(gè)手指,則顯示“2”,依此類推。手勢(shì)識(shí)別結(jié)果會(huì)實(shí)時(shí)更新在網(wǎng)頁上:

async function detectGesture(video, model) {
  const predictions = await model.estimateHands(video);

  // 如果沒有檢測(cè)到手部,則顯示"檢測(cè)中..."
  if (predictions.length === 0) {
    document.getElementById('result').innerText = "檢測(cè)中...";
    requestAnimationFrame(() => detectGesture(video, model));
    return;
  }

  const landmarks = predictions[0].landmarks; // 獲取手部的關(guān)鍵點(diǎn)
  const fingers = detectFingers(landmarks);

  let resultText = "檢測(cè)中...";

  // 基于手指的狀態(tài)判斷手勢(shì)
  switch (fingers) {
    case 1:
      resultText = "一";
      break;
    case 2:
      resultText = "二";
      break;
    case 3:
      resultText = "三";
      break;
    case 4:
      resultText = "四";
      break;
    case 5:
      resultText = "五";
      break;
    default:
      resultText = "無法識(shí)別手勢(shì)";
      break;
  }

  // 更新檢測(cè)結(jié)果顯示
  document.getElementById('result').innerText = resultText;

  // 每一幀進(jìn)行檢測(cè)
  requestAnimationFrame(() => detectGesture(video, model));
}

每一幀都會(huì)重新檢測(cè)手勢(shì),以確保輸出實(shí)時(shí)更新。

整合所有部分

最后,將所有的功能整合在一起,啟動(dòng)視頻流并開始手勢(shì)識(shí)別:

async function main() {
  // 等待模型加載
  const model = await loadHandPoseModel();
  
  // 設(shè)置視頻流并開始播放
  const video = await setupCamera();
  video.play();

  // 開始手勢(shì)識(shí)別
  detectGesture(video, model);
}

main();

通過以上步驟,實(shí)現(xiàn)了一個(gè)基于 HandPose 模型的手勢(shì)識(shí)別系統(tǒng)。利用瀏覽器提供的 getUserMedia API 獲取視頻流,并通過 TensorFlow.js 提供的 HandPose 模型來估計(jì)手的關(guān)鍵點(diǎn),最終實(shí)現(xiàn)了對(duì)手勢(shì)的實(shí)時(shí)識(shí)別。

完整代碼

// 顯示加載進(jìn)度條
function showLoadingProgress(progress) {
  const progressBar = document.getElementById('progress');
  progressBar.style.width = progress + '%';
}

// 1. 獲取視頻流并設(shè)置攝像頭
async function setupCamera() {
  const video = document.getElementById('video');
  const stream = await navigator.mediaDevices.getUserMedia({
    video: true,
  });
  video.srcObject = stream;

  return new Promise((resolve) => {
    video.onloadedmetadata = () => {
      resolve(video);
    };
  });
}

// 2. 加載 HandPose 模型并顯示加載進(jìn)度
async function loadHandPoseModel() {
  const loadingContainer = document.getElementById('loading-container');
  loadingContainer.style.display = 'block'; // 顯示加載進(jìn)度條

  const model = await handpose.load({
    flipHorizontal: false,  // 不要水平翻轉(zhuǎn)模型
    progressCallback: (fraction) => {
      const progress = Math.round(fraction * 100); // 計(jì)算加載的百分比
      showLoadingProgress(progress); // 更新進(jìn)度條
    }
  });

  loadingContainer.style.display = 'none'; // 隱藏加載進(jìn)度條
  return model;
}

// 3. 識(shí)別手勢(shì)
async function detectGesture(video, model) {
  const predictions = await model.estimateHands(video);

  // 如果沒有檢測(cè)到手部,則顯示"檢測(cè)中..."
  if (predictions.length === 0) {
    document.getElementById('result').innerText = "檢測(cè)中...";
    requestAnimationFrame(() => detectGesture(video, model));
    return;
  }

  const landmarks = predictions[0].landmarks; // 獲取手部的關(guān)鍵點(diǎn)
  const fingers = detectFingers(landmarks);

  let resultText = "檢測(cè)中...";

  // 基于手指的狀態(tài)判斷手勢(shì)
  switch (fingers) {
    case 1:
      resultText = "一";
      break;
    case 2:
      resultText = "二";
      break;
    case 3:
      resultText = "三";
      break;
    case 4:
      resultText = "四";
      break;
    case 5:
      resultText = "五";
      break;
    default:
      resultText = "無法識(shí)別手勢(shì)";
      break;
  }

  // 更新檢測(cè)結(jié)果顯示
  document.getElementById('result').innerText = resultText;

  // 每一幀進(jìn)行檢測(cè)
  requestAnimationFrame(() => detectGesture(video, model));
}

// 4. 判斷手勢(shì)
function detectFingers(landmarks) {
  let fingers = 0;

  // 判斷每個(gè)手指是否伸出:如果手指的末端關(guān)鍵點(diǎn)在其他關(guān)鍵點(diǎn)的上方,說明該手指伸出
  // 對(duì)于每根手指,檢查其關(guān)鍵點(diǎn)位置
  // 手指順序: [1: thumb, 2: index, 3: middle, 4: ring, 5: pinky]

  // 檢查每根手指的伸展情況
  const thumb = landmarks[4];  // 拇指
  const index = landmarks[8];  // 食指
  const middle = landmarks[12];  // 中指
  const ring = landmarks[16];  // 無名指
  const pinky = landmarks[20];  // 小拇指

  if (index[1] < thumb[1]) fingers++;  // 如果食指的末端在拇指的末端前面,說明食指伸展
  if (middle[1] < index[1]) fingers++;  // 如果中指的末端在食指的末端前面,說明中指伸展
  if (ring[1] < middle[1]) fingers++;  // 如果無名指的末端在中指的末端前面,說明無名指伸展
  if (pinky[1] < ring[1]) fingers++;  // 如果小拇指的末端在無名指的末端前面,說明小拇指伸展

  // 在"四"和"五"的判斷上,可以加大判斷容忍度,避免誤判
  if (ring[1] < middle[1] && pinky[1] < ring[1]) {
    // 可能"四"或者"五"的手勢(shì)識(shí)別較弱,可以通過容忍度來改進(jìn)
    fingers = (fingers === 4) ? 5 : fingers;
  }

  return fingers;
}

async function main() {
  // 等待模型加載
  const model = await loadHandPoseModel();
  
  // 設(shè)置視頻流并開始播放
  const video = await setupCamera();
  video.play();

  // 開始手勢(shì)識(shí)別
  detectGesture(video, model);
}

main();

html 文件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>手勢(shì)識(shí)別</title>
  <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
  <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/handpose"></script>
  <script src="https://unpkg.com/@tensorflow/tfjs-backend-webgl"></script>
</head>
<body>
  <h1>手勢(shì)識(shí)別</h1>
  <video id="video" width="640" height="480" autoplay></video>
  <div id="result">檢測(cè)中...</div>

  <div id="loading-container">
    <div id="progress-bar">
      <div id="progress"></div>
    </div>
    <div id="loading-text">正在加載模型...</div>
  </div>

  <script src="app.js"></script>
</body>
</html>

效果展示

到此這篇關(guān)于JavaScript實(shí)現(xiàn)手勢(shì)識(shí)別的示例詳解的文章就介紹到這了,更多相關(guān)JavaScript手勢(shì)識(shí)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論