mobileNet/new/script.js
2025-08-19 15:32:42 +08:00

123 lines
4.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const video = document.getElementById('webcam');
const canvas = document.getElementById('output');
const ctx = canvas.getContext('2d');
let detector, rafId;
async function setupCamera() {
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
try {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
video.srcObject = stream;
return new Promise((resolve) => {
video.onloadedmetadata = () => {
video.play(); // 确保视频播放才能获取到正确的宽度和高度
video.onplaying = () => { // 视频真正开始播放时
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
resolve();
};
};
});
} catch (error) {
console.error('Error accessing webcam:', error);
alert('Cannot access webcam. Please check permissions.');
}
} else {
alert('Your browser does not support webcam access.');
}
}
async function loadModel() {
const model = handPoseDetection.SupportedModels.MediaPipeHands;
const detectorConfig = {
runtime: 'mediapipe', // 或者 'tfjs'
solutionPath: 'https://cdn.jsdelivr.net/npm/@mediapipe/hands' // MediaPipe solution files path
};
detector = await handPoseDetection.createDetector(model, detectorConfig);
console.log('Hand Pose Detector loaded.');
}
const handSkeleton = {
'thumb': [0, 1, 2, 3, 4],
'indexFinger': [0, 5, 6, 7, 8],
'middleFinger': [0, 9, 10, 11, 12],
'ringFinger': [0, 13, 14, 15, 16],
'pinky': [0, 17, 18, 19, 20],
// 腕部和手掌基部的连接确保0号点连接到所有手指的起始关节
'palmBase': [0, 1, 5, 9, 13, 17, 0] // 形成手掌的近似轮廓
};
async function detectHands() {
if (detector && video.readyState === 4) {
const hands = await detector.estimateHands(video, {
flipHorizontal: false
});
ctx.clearRect(0, 0, canvas.width, canvas.height); // 清空画布
if (hands.length > 0) {
for (const hand of hands) {
// 绘制手部骨架连接线
// MediaPipe Hands 模型通常有21个关键点这些关键点有固定的索引
// 这些连接关系是标准的,可以通过硬编码定义或查找库的定义
const keypoints = hand.keypoints; // 简化访问
// 直接根据索引绘制连接线
const connectionsToDraw = [
// Thumb (拇指)
[0, 1], [1, 2], [2, 3], [3, 4],
// Index finger (食指)
[0, 5], [5, 6], [6, 7], [7, 8],
// Middle finger (中指)
[0, 9], [9, 10], [10, 11], [11, 12],
// Ring finger (无名指)
[0, 13], [13, 14], [14, 15], [15, 16],
// Pinky finger (小指)
[0, 17], [17, 18], [18, 19], [19, 20],
// Palm base connections (手掌基部连接)
[0, 5], [5, 9], [9, 13], [13, 17], [17, 0] // Connect wrist to finger bases and form a loop
];
ctx.strokeStyle = '#00FFFF'; // 青色
ctx.lineWidth = 2; // 线宽
for (const connection of connectionsToDraw) {
const start = keypoints[connection[0]];
const end = keypoints[connection[1]];
if (start && end) { // 确保关键点存在
ctx.beginPath();
ctx.moveTo(start.x, start.y);
ctx.lineTo(end.x, end.y);
ctx.stroke();
}
}
// 绘制关键点
ctx.fillStyle = '#FF0000'; // 红色
for (const keypoint of keypoints) {
// keypoint.x, keypoint.y 是像素坐标
// keypoint.z 是深度信息 (相对坐标)通常不用于2D绘制
ctx.beginPath();
ctx.arc(keypoint.x, keypoint.y, 4, 0, 2 * Math.PI); // 绘制半径为4的圆
ctx.fill();
}
// 绘制手部关键点标记如果仍想使用util函数绘制
// handPoseDetection.util.drawLandmarks(ctx, hand.keypoints, {color: '#FF0000', radius: 4});
// 由于我们已经手动绘制了,这行可以注释掉或移除,避免重复绘制。
}
}
}
rafId = requestAnimationFrame(detectHands);
}
async function app() {
await setupCamera();
await loadModel();
detectHands();
}
app();