112 lines
6.5 KiB
Markdown
Raw Permalink 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.

# Web-Based Real-Time Pose Classifier
这是一个功能强大的、完全在浏览器中运行的实时姿态识别与训练工具。它利用 TensorFlow.js 和姿态检测模型 (MoveNet),允许用户通过摄像头实时定义、训练和识别自定义的身体姿态,而无需任何服务器端处理。
## ✨ 功能亮点
- **实时姿态检测**: 使用高效的 **MoveNet** 模型在视频流中实时捕捉人体的17个关键点。
- **在线模型训练**: 通过 **K-近邻 (KNN)** 算法,用户可以直接在浏览器中为不同的姿态(例如“站立”、“举手”、“深蹲”)采集样本并训练分类模型。
- **实时姿态预测**: 训练完成后,应用可以立即对摄像头前的姿态进行分类,并显示预测结果及置信度。
- **精准视觉反馈**: 实时在用户画面上绘制姿态骨架确保关键点被正确识别实现了视频与Canvas的完美对齐与重叠。
- **模型持久化**:
- **导出模型**: 用户可以将训练好的模型一键导出为 `.json` 文件,方便保存和备份。
- **导入模型**: 用户可以随时将之前导出的模型文件导入应用,瞬间恢复训练状态,无需重新采集样本。
- **纯前端实现**: 所有计算(包括模型推理和训练)都在客户端浏览器中完成,保护用户隐私且无需服务器成本。
## 🚀 如何使用
1. **打开页面**: 用支持现代JavaScript的浏览器如Chrome, Firefox打开 `index.html`
2. **授予权限**: 浏览器会请求摄像头访问权限,请点击“允许”。应用会自动加载模型并启动摄像头。
3. **采集样本 (训练)**:
- 面对摄像头摆出你想定义的第一个姿态例如“姿态A”
- 多次点击“采集样本”按钮建议从不同角度采集至少20个样本以保证准确性。
- 对其他姿态“姿态B”、“姿态C”重复此过程。样本数量会实时更新。
4. **模型管理 (可选)**:
- **导出**: 训练完成后,点击“导出模型”按钮,会将当前训练好的模型保存为一个`pose-knn-model.json`文件。
- **导入**: 在新的会话或新设备上,点击“导入模型”,选择之前导出的`.json`文件,即可恢复模型。
5. **开始预测 (推理)**:
- 点击“开始预测”按钮。
- 应用将开始实时分析你的姿态,并在下方显示预测结果。
- 再次点击“停止预测”可暂停。
建议使用live server插件开启本地服务器并访问index.html文件。
## 存在问题
css样式中描绘关节骨架与实际对比偏小现在使用的方法是模型输出关节后与视频大小一起缩放。暂时不清楚是缩放导致还是模型输出。
## 📁 项目结构
```
/
├── poseClassifier.js # 核心逻辑脚本,包含所有功能实现
├── index.html # 应用主页面包含所有UI元素
├── style.css # 页面样式文件
└── script.js # 核心逻辑脚本,包含所有功能实现
```
## 🤖 技术栈
- **TensorFlow.js**: 核心机器学习库,用于在浏览器中运行模型和处理张量(Tensors)。
- **Pose Detection API (`@tensorflow-models/pose-detection`)**: 用于运行姿态检测模型。
- **MoveNet.SinglePose.Lightning**: 我们选择的具体模型,它在速度和精度之间取得了极佳的平衡。
- **KNN Classifier (`@tensorflow-models/knn-classifier`)**: 一个基于TensorFlow.js实现的K-近邻分类器,用于在线学习。
- **原生 HTML5 / CSS3 / JavaScript (ES6+)**: 构建用户界面和实现应用逻辑。
---
## 📜 `script.js` 核心函数解析
### 主应用逻辑
`async function init()`
- **职责**: 应用的入口函数。负责初始化KNN分类器、加载MoveNet姿态检测模型、设置摄像头、绑定所有事件监听器并启动主循环。
`async function setupCamera()`
- **职责**: 请求并获取用户摄像头的视频流。成功后,将视频流赋给`<video>`元素,并设置`<canvas>`的绘图分辨率与视频的原始分辨率(`videoWidth`/`videoHeight`)完全一致,这是解决坐标偏移的关键。
`function setupEventListeners()`
- **职责**: 为所有UI元素如“采集样本”、“开始预测”、“导入/导出模型”按钮)绑定`click``change`事件,将用户交互与业务逻辑连接起来。
`async function mainLoop()`
- **职责**: 这是应用的核心循环,通过`requestAnimationFrame`实现。在每一帧中它会从视频中获取当前姿态清空并重绘Canvas如果处于预测状态则进行姿态分类并更新结果。
`async function addExample(classId)`
- **职责**: 当用户点击“采集样本”时调用。它获取当前帧的姿态将其转换为用于分类的特征张量并添加到KNN分类器中与指定的`classId`关联。
`function togglePrediction()`
- **职责**: 控制预测状态的开关。它会检查模型是否已训练,然后切换`isPredicting`标志位并更新UI。
### 模型管理函数
`function exportModel()`
- **职责**: 将训练好的模型导出。它通过`classifier.getClassifierDataset()`获取内部数据将Tensor对象转换为可序列化的普通数组最后生成一个JSON字符串并触发浏览器下载。
`function importModel(event)`
- **职责**: 从用户选择的`.json`文件导入模型。它使用`FileReader`读取文件内容将JSON字符串解析回对象再将普通数组转换回Tensor对象最终通过`classifier.setClassifierDataset()`加载到分类器中。
### 辅助与UI更新函数
`function flattenPose(pose)`
- **职责**: 数据预处理函数。它提取姿态中的所有关键点坐标进行归一化除以视频宽高并“扁平化”为一个一维的Tensor。这是KNN分类器需要的输入格式。
`function drawPose(pose)`
- **职责**: 视觉反馈函数。它在Canvas上绘制姿态的关键点圆点和骨骼连接线让用户能直观地看到模型识别出的姿态。
`function updateSampleCounts()`
- **职责**: 更新界面上显示的每个姿态类别的样本数量。
`function updatePredictionUI()`
- **职责**: 根据当前是否正在预测,动态地启用/禁用相关按钮(如“采集样本”按钮在预测时应被禁用),并更新按钮文本。
`function enableControls()`
- **职责**: 在应用成功初始化后,启用所有交互按钮。
`function cleanup()`
- **职责**: 在页面关闭或刷新前释放资源主要是清理TensorFlow.js模型和分类器占用的内存防止内存泄漏。