1.识别模式
本作品使用了二哈识图2中的姿态识别模块,模型为自带。本功能可以检测画面中的人体,识别并描绘出人体的17个关键点,进而学习、识别、追踪人体的不同姿态。

2.创作背景
军体拳是由一些格斗动作组合而成的拳术,最初为军人而创编。对于普通人来说,练习军体拳具有强身健体的价值,具有防身自卫作用,还能在一些活动中进行表演展示。所以,很多学校也引进军体拳作为学生日常的课间操或体育锻炼项目。为了检验学生的学习成果,某校拟对几千个孩子进行考核,对合格的孩子颁发合格证书。由于人数众多,考核的工作量大,时间跨度比较长,不妨借助AI技术来完成这一工作。

图片来自网络
3.系统设计与工作原理
3.1功能介绍
它拥有一个AI视觉传感器,能识别考生的身体姿态。当考生每演练出一个招式,有语音播报和屏幕显示当前招式已通过;当所有招式都完成时,有语音播报和屏幕显示通过考核,机器会自动发放一张合格证书。(为了控制程序的长度和演示时间,本作品中仅以准备、前三式共4个动作为例。)

3.2 系统构成
该设备由行空板K10、二哈识图2和360°舵机组成。行空板K10是主控制器,集成了显示屏、语音合成模块等器件,它是设备的大脑,用来处理输入数据、语音播报、屏幕显示和控制舵机转动;二哈识图2作为视觉传感器,用来获取并识别人的身体及姿态数据,并将数据传送给主控制器;舵机是执行器,当收到主控制器的指令后会进行相应地运转,以完成发放合格证书的任务。

3.3 工作流程图

4. 硬件准备
5. 制作步骤
步骤1 5.1硬件搭建
将二哈识图2 AI视觉传感器连接到行空板K10的I2C接口,将舵机分别连接到P1接口。

步骤2 5.2动作学习
给行空板K10或者 AI视觉传感器供电,选择“姿态识别模式”进行学习。本项目中选取了前4个动作进行学习,学习完成后动作名称与对应的ID号如下图所示。

步骤3 程序设计
本作品的程序使用Mind+ V.8.1RC3.0编写,设计思路参照工作流程图。程序如下所示。

步骤4 结构设计与加工
本作品的结构与造型图纸使用LaserMaker2.0.16绘制,然后使用激光切割机进行加工,使用的板材为3MM椴木板。


步骤5 组装成型
(1)安装控制板

(2)安装二哈识图2

(3)组装证书卷轴

(4)将卷轴固定到舵机摇臂上,并和舵机一起装到底板上

(5)将前面和底面两块木板件组合起来

(6)装上合格证书

(7)装上背面模板件,整理捆扎连接线

(8)装上左右面及上面的木板件

步骤6 调试完善
通电测试各项功能是否能正常实现。对程序和结构进行修改迭代,不断完善作品。

6.作品展示
6.1 成品图
6.2多角度图




6.3演示视频
7.总结与反思
当前版本的作品性能比设想的要弱一些,仅够用以表达创意。最初想将军体拳的每个招式都进行分解,分解成2-3个姿态,并使用多角度的图片作为学习数据,通过Mind+2.0的模型训练模块生成自训练模型导入到二哈识图2中进行调用。但是目前Mind+2.0的模型训练还不支持姿态识别的自训练模型导入,在收集相关图片时也遇到了一些困难;所以采用二哈识图2直接学习的方案,而且每个招式只选择了固定角度的一个姿态进行学习。在实际使用中,需要考生在机器前以某个固定的角度进行展示,实用性降低了不少。
发放合格证书的机构比较拉跨,作品还缺少一些交互功能,有待后期的迭代版本加以解决、完善。
/*!
* MindPlus
* esp32s3bit
*
*/
#include "asr.h"
#include <SimpleList.h>
#include "unihiker_k10.h"
#include <DFRobot_Libraries.h>
#include "DFRobot_HuskylensV2.h"
#include "arduino_image_cache.h"
// 动态变量
volatile float mind_n_count, mind_n_TongGuo, mind_n_idex, mind_n_ZhaoShi;
SimpleList<String> mind_l_TongGuoJiLu, mind_l_JunTiQuanZhaoShi;
// 函数声明
void DF_LieBiaoChuShiHua();
void DF_FaFangZhengShu();
void DF_PanDuanShiFuTongGuo();
void DF_JiBenZhaoShiKaoHe();
void DF_XiTongZhongZhi();
// 创建对象
DFRobot_Servo360 servo360_P1;
HuskylensV2 huskylens;
UNIHIKER_K10 k10;
uint8_t screen_dir=2;
ASR asr;
// 主程序开始
void setup() {
k10.begin();
servo360_P1.attach(P1);
Wire.begin();
while (!huskylens.begin(Wire)) {
delay(100);
}
k10.initScreen(screen_dir);
k10.creatCanvas();
asr.setAsrSpeed(2);
servo360_P1.speed(0);
huskylens.switchAlgorithm(ALGORITHM_POSE_RECOGNITION);
DF_LieBiaoChuShiHua();
mind_n_count = 0;
mind_n_TongGuo = 0;
}
void loop() {
k10.canvas->canvasDrawBitmap(0,0,240,320,image_data1);
k10.canvas->canvasText("军体拳AI考核系统", 20, 10, 0xFFFF00, k10.canvas->eCNAndENFont24, 50, false);
k10.canvas->updateCanvas();
huskylens.getResult(ALGORITHM_POSE_RECOGNITION);
DF_JiBenZhaoShiKaoHe();
DF_PanDuanShiFuTongGuo();
if ((mind_n_TongGuo==1)) {
delay(3000);
asr.speak("恭喜你,已通过考核");
k10.canvas->canvasText("恭喜你,已通过考核", 10, 80, 0x00FFFF, k10.canvas->eCNAndENFont24, 50, false);
k10.canvas->canvasText("正在打印合格证书......", 10, 110, 0x00CCCC, k10.canvas->eCNAndENFont16, 50, false);
k10.canvas->updateCanvas();
DF_FaFangZhengShu();
delay(1000);
asr.speak("请拿好您的合格证书");
DF_XiTongZhongZhi();
}
}
// 自定义函数
void DF_LieBiaoChuShiHua() {
mind_l_TongGuoJiLu.clear();
for (int index = 0; index < 4; index++) {
mind_l_TongGuoJiLu.push_back("0");
}
mind_l_JunTiQuanZhaoShi.clear();
mind_l_JunTiQuanZhaoShi.push_back("格斗准备");
mind_l_JunTiQuanZhaoShi.push_back("弓步冲拳");
mind_l_JunTiQuanZhaoShi.push_back("穿喉弹踢");
mind_l_JunTiQuanZhaoShi.push_back("马步横打");
}
void DF_FaFangZhengShu() {
servo360_P1.speed(50);
delay(1500);
servo360_P1.speed(0);
}
void DF_PanDuanShiFuTongGuo() {
mind_n_idex = 0;
mind_n_count = 0;
for (int index = 0; index < 4; index++) {
mind_n_idex += 1;
mind_n_count += (String(mind_l_TongGuoJiLu[mind_n_idex-1]).toInt());
}
if ((mind_n_count==4)) {
mind_n_TongGuo = 1;
}
}
void DF_JiBenZhaoShiKaoHe() {
mind_n_ZhaoShi = 0;
for (int index = 0; index < 4; index++) {
mind_n_ZhaoShi += 1;
if (((huskylens.getCachedResultByID(ALGORITHM_POSE_RECOGNITION, mind_n_ZhaoShi) != NULL))) {
asr.speak(mind_l_JunTiQuanZhaoShi[mind_n_ZhaoShi-1]);
asr.speak("已通过");
k10.canvas->canvasText((String(mind_l_JunTiQuanZhaoShi[mind_n_ZhaoShi-1]) + String("已通过")), 10, 50, 0x33CCFF, k10.canvas->eCNAndENFont24, 50, false);
k10.canvas->updateCanvas();
mind_l_TongGuoJiLu.replace(mind_n_ZhaoShi-1, "1");
}
}
}
void DF_XiTongZhongZhi() {
mind_n_TongGuo = 0;
mind_l_TongGuoJiLu.clear();
for (int index = 0; index < 4; index++) {
mind_l_TongGuoJiLu.push_back("0");
}
k10.canvas->canvasClear();
}
附件

返回首页
回到顶部




评论