From 24f9ff2428c8b9ce8a7e0942fa1b282c9e692baf Mon Sep 17 00:00:00 2001 From: 51hhh Date: Wed, 20 Aug 2025 10:49:44 +0800 Subject: [PATCH] =?UTF-8?q?[MF]=E4=BF=AE=E6=94=B9game=E9=AA=A8=E9=AA=BC?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E9=94=99=E8=AF=AF=EF=BC=8C=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/{ => 石头剪刀布}/game.html | 6 +- new/index.html | 38 ---------- new/script.js | 122 -------------------------------- {game => 手势分类}/index.html | 0 {game => 手势分类}/script.js | 14 ++-- {game => 手势分类}/style.css | 2 +- 6 files changed, 11 insertions(+), 171 deletions(-) rename game/{ => 石头剪刀布}/game.html (99%) delete mode 100644 new/index.html delete mode 100644 new/script.js rename {game => 手势分类}/index.html (100%) rename {game => 手势分类}/script.js (97%) rename {game => 手势分类}/style.css (99%) diff --git a/game/game.html b/game/石头剪刀布/game.html similarity index 99% rename from game/game.html rename to game/石头剪刀布/game.html index cc9b82b..8655122 100644 --- a/game/game.html +++ b/game/石头剪刀布/game.html @@ -939,8 +939,8 @@ for (const [startIdx, endIdx] of HAND_CONNECTIONS) { const start = keypoints[startIdx]; const end = keypoints[endIdx]; - // 只有当连接的两个关键点都存在且置信度较高时才绘制 - if (start && end && start.score > 0.3 && end.score > 0.3) { + // 只有当连接的两个关键点都存在 + if (start && end) { canvasCtx.beginPath(); canvasCtx.moveTo(start.x, start.y); canvasCtx.lineTo(end.x, end.y); @@ -954,7 +954,7 @@ canvasCtx.shadowBlur = 10; // 关键点发光更强 for (const keypoint of keypoints) { - if (keypoint.score > 0.3) { // 同样只绘制置信度高的关键点 + if (keypoint) { // 同样只绘制置信度高的关键点 canvasCtx.beginPath(); canvasCtx.arc(keypoint.x, keypoint.y, 6, 0, 2 * Math.PI); // 绘制半径为6的圆 canvasCtx.fill(); diff --git a/new/index.html b/new/index.html deleted file mode 100644 index 9c16dc3..0000000 --- a/new/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - Hand Pose Detection - - - -
- - -
- - - - - - - - - - - - - - diff --git a/new/script.js b/new/script.js deleted file mode 100644 index ff511b1..0000000 --- a/new/script.js +++ /dev/null @@ -1,122 +0,0 @@ -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(); diff --git a/game/index.html b/手势分类/index.html similarity index 100% rename from game/index.html rename to 手势分类/index.html diff --git a/game/script.js b/手势分类/script.js similarity index 97% rename from game/script.js rename to 手势分类/script.js index 2497250..e38e248 100644 --- a/game/script.js +++ b/手势分类/script.js @@ -1,7 +1,7 @@ /** * ============================================================================= * 动态版 - 手部姿态识别与模型管理脚本 (v3.0) - * 由人体姿态识别修改为手部姿态识别,并确保非镜像显示 + * 由人体姿态识别修改为手部姿态识别 * ============================================================================= */ @@ -180,14 +180,14 @@ async function addExample(classId) { } } -// --- 模型与预测逻辑 (小修改) --- +// --- 模型与预测逻辑 --- /** - * 开始或停止姿态预测 (少量文案修改) + * 开始或停止姿态预测 */ function togglePrediction() { if (classifier.getNumClasses() === 0) { - alert("请先为至少一个手势采集样本后再开始预测!"); // 文案修改 + alert("请先为至少一个手势采集样本后再开始预测!"); return; } isPredicting = !isPredicting; @@ -344,8 +344,8 @@ function drawHand(hand) { for (const connection of HAND_CONNECTIONS) { const start = keypoints[connection[0]]; const end = keypoints[connection[1]]; - // 检查关键点的 score,确保是可靠的 - if (start && end && start.score > 0.3 && end.score > 0.3) { + // 检查关键点是否存在 + if (start && end) { canvasCtx.beginPath(); canvasCtx.moveTo(start.x, start.y); canvasCtx.lineTo(end.x, end.y); @@ -356,7 +356,7 @@ function drawHand(hand) { // 绘制关键点 canvasCtx.fillStyle = '#FF0000'; // 红色 for (const keypoint of keypoints) { - if (keypoint.score > 0.3) { // 同样检查 score + if (keypoint) { // 同样检查 canvasCtx.beginPath(); // 关键点半径设置小一点,因为手部关键点比人体姿态更密集 canvasCtx.arc(keypoint.x, keypoint.y, 4, 0, 2 * Math.PI); diff --git a/game/style.css b/手势分类/style.css similarity index 99% rename from game/style.css rename to 手势分类/style.css index 63851ac..7f8ae4c 100644 --- a/game/style.css +++ b/手势分类/style.css @@ -92,7 +92,7 @@ h3 { width: 100%; height: 100%; /* 核心修改:移除以下两行,实现非镜像显示 */ - /* transform: scaleX(-1); */ + transform: scaleX(-1); } #video {