智能居家瑜伽教练

更新时间Invalid dateWL20210167

概况

当下我国经济持续发展,全国各族人民生活水平在不断提高,人们对美好生活的需要日益增长。社会各界人士对生活的要求不只是停留在“吃饱穿暖”“日常娱乐”等浅表层面,他们对生活“质量”“舒适度”也有了更高的期待。然而,当下快节奏的工作生活给人们身体健康带来很大威胁,许多人处在“亚健康”状态,即便如此,由于各方压力,也无暇顾及健身等对身心健康有益的事。2016年8月26日,中共中央政治局召开会议,审议通过"健康中国2030"规划纲要。会议认为,健康是促进人的全面发展的必然要求,是经济社会发展的基础条件,是民族昌盛和国家富强的重要标志,也是广大人民群众的共同追求。党的十八届五中全会明确提出推进健康中国建设,从"五位一体"总体布局和"四个全面"战略布局出发,对当前和今后一个时期更好保障人民健康作出了制度性安排,党的十九大也提出了“实施健康中国战略”,是以习近平同志为核心的党中央从长远发展和时代前沿出发,作出的一项重要战略安排。 它基于人民对美好生活的需求,旨在全面提高人民健康水平、促进人民健康发展,为新时代建设健康中国明确了具体落实方案。建设健康中国的根本目的是提高全体人民的健康水平,人民健康也是社会主义现代化强国的重要指标。

近年来,我们可喜得看到,随着人们生活水平和健康意识的不断提高,人们越来越多的主动进行体育锻炼,以达到强身健体的目的。在下面叙述中,我们以当代十分流行的瑜伽健身运动为例,进行说明。瑜伽起源于古印度,如今是一项具有5000年历史的关于身体、心理以及精神的健身项目。但是专业的瑜伽课程具有相当高的费用,且需要跟班走,按时上课,这些问题也导致了许多人有意愿学瑜伽,但是现实情况不允许的现象。在现今繁重的工作学习任务等各方面压力下,人们通常无法承担大量时间金钱的损失,即无法花费大量金钱购买昂贵的瑜伽健身课程,也无法花费大量时间去瑜伽房进行实地练习。这种阻碍导致了很多人深陷有心练习瑜伽但迟迟无法行动的尴尬处境。部分人为了寻求解决方式,则会把体育锻炼的场景选择为自己家中,通过瑜伽视频进行健身锻炼,这也会衍生出一个巨大隐患——动作规范性问题,即人们自己锻炼很难达到理想标准从而削弱运动锻炼的作用,甚至会适得其反,危害到自己的身体健康,这种情况在瑜伽中更为普遍。人们对于花费小,方便性高,效果专业的健身解决方案的需求日益增加。

而另一方面,随着图像识别技术的不断发展与进步,它的高价值应用发生在你我身边,从辅助学习,工作通勤到社会服务涉及到了人们生活中的各个方面。再加上近年来传感器技术与物联网技术在近些年的不断发展与进步,使得智能居家健身指导这一设想离人们的生活越来越近。智能居家健身指导从设想变成了现实。

针对上述需求与问题,我们便有了“居家瑜伽教练”的设计想法,通过机器学习,深度识别,仅一个摄像头就可以起到教练的效果。不仅降低了学习成本,还打破了时间空间的限制。同时该系统具有开发图像纠错的功能,通过外设摄像头采集图像信息,然后根据图像信息对锻炼人员的姿势进行评估以及纠错,从而达到纠正锻炼姿势实现锻炼预期效果的目标。

我们相信,该项目的实现具有很大应用前景,并具有很强的延伸性可拓展到生活中的其他领域,这必定能使得各类健身运动能够真正的普及大众,为人民的健康做出一份贡献。

作品视频展示: https://www.bilibili.com/video/BV1eR4y1j7zz?p=1&share_medium=android&share_plat=android&share_session_id=e091c3bf-50a4-459c-84ac-a611bd6b41f2&share_source=COPY&share_tag=s_i&timestamp=1644306419&unique_k=Y7rB4CW

物料清单

硬件 (6)软件 (4) 其它 (2)
  • Intel realsense D415深度摄像头

    数量:1

    英特尔RealSense技术是一套深度和跟踪技术,旨在为机器和设备提供深度感知功能。RealSense技术由视觉处理器,深度和跟踪模块以及深度摄像头组成,由一个名为LibrealSense的开源跨平台SDK支持,简化了第三方软件开发人员,系统集成商,ODM和OEM的支持摄像头。

  • 小熊派IOT开发板

    数量:1

    小熊派IOT开发板是一款由南京小熊派智能科技有限公司联合华为技术有限公司基于STM32L431RCT6设计的高性能物联网开发板。此开发板物联网感知层设备具有多样性和强大得可延展性,用于提供给开发者评估及快速设计相关物联网的应用产品。

  • Intel神经网络计算棒

    数量:1

    Intel计算棒可让开发者更智能、更高效地开发和部署深度神经网络应用,满足新一代智能设备的需求。

  • Raspberry Pi

    数量:1

    Raspberry Pi(中文名为“树莓派”,简写为RPi,(或者RasPi / RPI) 是为学习计算机编程教育而设计),只有信用卡大小的微型电脑,其系统基于Linux

  • 云服务器

    数量:1

  • PC

    数量:1

步骤

本研究基于人体的姿态识别,以设计实现家庭瑜伽教练系统为目的。通过 Intel realsense 摄像头实时地获取自重健身者的健身动态视频,对健身者的动作进行捕获和分析,进行人体姿态估计,利用人体骨架关节点来描述健身者的动作姿态,从视频的图像序列中分析并跟踪健身者的动作,通过进行科学地量化分析健身者的运动特征,实现健身者姿态的分析和对比,再结合人体生理学、物理学等原理提出体育动作改进的方法辅助健身者训练,以此摆脱传统健身训练纯粹依靠经验的状态,实现直观地进行健身分析指导,实现从基于传统经验教学的健身训练方法到基于人体姿态识别的分析方法的转变。重点有以下几个部分: (1)获取视频帧中人体的二维骨架关节点信息,特征提取后要将关键点转 3D 坐标,因为健身动作幅度较大,同时存在自身遮挡的问题,而 3D 坐标点则不存在点挤压的情况,可以更好地表示健身者的姿态。 (2)运动特征的提取,针对每一个健身动作选取动作规范的特征,如关节角度,肢体朝向,运动幅度,动作速度等,建立评价的标准。 (3)数据的比对与传输,在比对前需要对数据进行清洗和标准化,统一 3D 坐标的原点,坐标轴及参考平面。考虑到边缘设备数据处理能力不强的限制,采用云服务器以及Redis数据库技术进行数据传输以及处理。 (4)系统的可视化及实时性:健身者可以通过 app 查看自己的健身动作与标准动作的差异,在健身者通过辅助系统健身的同时实时地检测健身动作的速率及规范性,及时评价和矫正。 项目的系统实现 1、系统架构图 图1 系统架构图 2、感知层技术 (1)Resealsense SDK 借助Realsense sdk驱动程序获取现实世界reb图像数据以及deepth图像数据 3、传输层技术 (1)UART串口传输 由于需要设置统一波特率,因而我们无法使用GPIO的输入输出功能实现串口传输,所以我们使用了小熊派以及树莓派均具备的UART串口进行传输数据,连接小熊派以及树莓派,实现两者之间的信息交互。 我们使用小熊派作为附加设备,专为树莓派提供碰一碰入网的功能性支持,通过UART我们可以方便的、快捷的、安全的传输WIFI信息,对树莓派提供碰一碰入网支持。在后续开发中,我们考虑将小熊派作为一个更多元化的输入输出设备,通过部署在云服务器的简易IOT服务实现更多元化的输入和输出。 (2)NFC技术 NFC可以使硬件设备实现方便快捷的信息交互,本系统中,我们使用小熊派作为附加设备,对其NFC示例进行了学习与修改,实现了为树莓派提供NFC碰一碰入网的功能性支持,通过UART我们可以方便的、快捷的、安全的传输WIFI信息。 在后续开发中,我们考虑将小熊派作为一个更多元化的输入输出设备,通过部署在云服务器的简易IOT服务实现更多元化的输入和输出。 (3)WS协议 由于传统HTTP协议存在单向连接的问题,WebSocket解决客户端发起多个HTTP请求到服务器资源浏览器必须要经过长时间的轮询问题。实现客户与服务器之间更加快速有效交互。 (4)Redis缓存技术 Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 通过redis中间件实现了服务器Python Web服务器进程和C++推理进程的通信,既能够享受到C++语言的高速,又能够获取Python Web_Socket程序开发的便捷性。 4、控制层技术 (1)JS与websocket结合 用户通过JS生成的网页连接服务端的WebSocket,进行信息交互,实现用户实时可视化获取姿态信息反馈功能。 5、数据挖掘 (1)Openpose 借助Openpose工具实现RGB图像骨架化提取,并与Deepth结合获取三维骨架化数据。 (2)OpenCV 前期先从深度摄像头提取出的各种姿态特征作为Opencv Random Forest的训练数据,从而训练出瑜伽姿态随机森林分类模型。 根据树莓派实时传输的三维骨架化数据提取出的人体身体长度比例以及关节点夹角等物理特征作为服务器Opencv Random Forest 分类的特征数据,从而预测出骨架化姿态。 (3)混合人工智能 大数据处理筛选优秀姿态特征,根据姿态特征协调Random Forest提高姿态分类准确率,以及实现减小生成随机树的数量,加快推理速度。 6、云应用 (1)宝塔面板 宝塔面板,简单高效的对华为云服务器进行管理。 (2)华为云服务器 在华为云服务器中开放Redis服务以及部署WebSocket服务,使得服务器多进程间以及服务器与边缘树莓派之间能够以简单的形式直进行信息交换,以及实现远程Web访问功能。

关键代码

①服务器识别代码封装

  1. public:
  2.  /* 
    
  3.  Introction: 
    
  4.      读取数据,并获取最优训练特征 
    
  5.  Parameters: 
    
  6.      string[] fileList: 
    
  7.          读取文件列表 
    
  8.      int num: 
    
  9.          文件数量 
    
  10. Returns: 
    
  11.     结构体对象 struct data: 
    
  12.         struct data { 
    
  13.             float** trainingData;   //特征转化完毕的训练数据 
    
  14.             int* fList;             //最优特征序列号 
    
  15.             int column;             //最优特征数量 
    
  16.         }; 
    
  17. */
  18. struct data getBestTrainFeature(string fileList[],int num);  
    
  19. struct data getBestTrainFeature();  
    
  20. void init();  
    
  21. /* 
    
  22.     Instrocduction: 
    
  23.         随机森林模型训练 
    
  24.     Parameters: 
    
  25.         string mod:区分训练和加载模型 
    
  26.         string fileList[]:训练文件地址序列 
    
  27.         int nums:训练文件数量 
    
  28.         string testList[]:测试文件地址序列 
    
  29.         int numt:测试文件数量 
    
  30. */  
    
  31. void trainAndTest(string mod, string fileList[], int nums, string testList[], int numt);  
    
  32. /* 
    
  33.     Instrocduction: 
    
  34.         默认训练数据与模型地址 
    
  35. */  
    
  36. void trainAndTest(string mod);  
    
  37. /* 
    
  38.     Instrocduction: 
    
  39.         默认训练数据,输入测试模型地址 
    
  40. */  
    
  41. void trainAndTest(string mod, string path);
    

② Web服务器实现

  1. def web_sever():
  2.  time_now=time.time()  
    
  3.  s_web = socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    
  4.  s_web.bind(('',10086))  
    
  5.  s_web.listen(3)  
    
  6.  print("Web服务器已开启")  
    
  7.  while True:  
    
  8.      try:  
    
  9.          c_socket,c_addr = s_web.accept()  
    
  10.         handshake(c_socket)  
    
  11.         print('网络已接入:',c_addr)  
    
  12.         while True:  
    
  13.             try:  
    
  14.                 jsonData = recv_data(c_socket.recv(1024))  
    
  15.             except:  
    
  16.                 continue  
    
  17.             if(jsonData[0] != "{"):  
    
  18.                 print(jsonData)  
    
  19.                 continue  
    
  20.             text = json.loads(jsonData)  
    
  21.             print ("收到指令:",text)  
    
  22.             if(text["function"]=="get"):  
    
  23.                 try:  
    
  24.                     timec=int(sever_redis.get("timecpp"))  
    
  25.                 except:  
    
  26.                     timec=time.time()-1  
    
  27.                 if(timec>=time_now):  
    
  28.                     #当没有新数据时刻  
    
  29.                     pose_name=sever_redis.get("pose")  
    
  30.                     pose_advice=sever_redis.get("advice")  
    
  31.                     pose_score=sever_redis.get("score")  
    
  32.                     ret_dict={}  
    
  33.                     ret_dict["function"]="message"  
    
  34.                     ret_data={}  
    
  35.                     ret_data["pose"]=str(pose_name).replace("b'","").replace("'","")  
    
  36.                     ret_data["score"]=str(pose_score).replace("b'","").replace("'","")  
    
  37.                     ret_data["advice"]=str(pose_advice).replace("b'","").replace("'","")  
    
  38.                     ret_dict["data"]=ret_data  
    
  39.                     time_now = timec  
    
  40.                 else:  
    
  41.                     #当没有新数据时  
    
  42.                     ret_dict={}  
    
  43.                     ret_dict["function"]="message"  
    
  44.                     ret_data={}  
    
  45.                     ret_data["pose"]=str("null")  
    
  46.                     ret_data["score"]=str("null")  
    
  47.                     ret_data["advice"]=str("null")  
    
  48.                     ret_dict["data"]=ret_data  
    
  49.                 rev = json.dumps(ret_dict)  
    
  50.                 print("返回数据:",rev)  
    
  51.                 send_msg(c_socket,rev.encode('utf-8'))  
    
  52.             elif(text["function"]=="write"):  
    
  53.                 data = text["data"]  
    
  54.                 sever_redis.set("json",data)  
    
  55.             elif(text["function"]=="exit"):  
    
  56.                 break  
    
  57.             else:  
    
  58.                 continue  
    
  59.     except KeyboardInterrupt:  
    
  60.         #ctrl+c终止程序 防止卡主  
    
  61.         print('检测到异常 即将推出')  
    
  62.         break  
    
  63.     c_socket.close()
    

③ 边缘控制代码

  1. -- coding:utf-8 --

  2. import serial
  3. import time
  4. import json
  5. import os
  6. ser = serial.Serial("/dev/ttyAMA0", 9600)
  7. ser.flushInput()
  8. def main():
  9. while True:  
    
  10.     count = ser.inWaiting()  
    
  11.     if count != 0:  
    
  12.         recv = ser.read(count)  
    
  13.         print (recv)  
    
  14.         try:  
    
  15.             print ("decode start!!")  
    
  16.             json_data = json.loads(recv)  
    
  17.             print(json_data)  
    
  18.             try:  
    
  19.                 print ("decode success!!!")  
    
  20.                 print ("init data")  
    
  21.                 ser.write("yes".encode("utf-8"))  
    
  22.                 ser.flushInput()  
    
  23.                 print ("success:wifi connected!!")  
    
  24.                 os.system("mate-terminal -e 'bash -c \"cd /home/hit-ices && sh /home/hit-ices/intel/openvino/bin/setupvars.sh &&sh run.sh;exec bash\"'")  
    
  25.                 break  
    
  26.                 pass  
    
  27.             except ValueError as e:  
    
  28.                 print ("failed!!!")  
    
  29.                 ser.write("no".encode("utf-8"))  
    
  30.                 ser.flushInput()  
    
  31.                 pass  
    
  32.         except:  
    
  33.             ser.write("no".encode("utf-8"))  
    
  34.             ser.flushInput()  
    
  35.             print(recv)  
    
  36.             print("uart init!!")  
    
  37.     time.sleep(0.1)  
    
  38. if name == 'main':
  39. main()
    

小结

项目创新特色

(1)多设备协同入网 树莓派拥有有线与无线两种入网方式,由于有线入网配置复杂,用户学习成本极高,且需要大量外接设备,削弱了设备的便携性、可拓展性。因此,项目采用了更为方便便捷的、无学习成本的碰一碰无线入网方式。鉴于树莓派没有自带的NFC功能组件,项目使用小熊派作为附加设备,专为树莓派提供碰一碰入网的功能性支持,通过UART我们可以方便的、快捷的、安全的传输WIFI信息,对树莓派提供碰一碰入网支持。 在后续开发中,可考虑将小熊派作为一个更多元化的输入输出设备,通过部署在云服务器的简易IOT服务实现更多元化的输入和输出。

(2)混合人工智能 由于AI经过算法提取的部分特征会出现信息冗余乃至与人们的日常认知不符,我们采用混合人工智能的方式,将计算得出的特征集进行人工筛选,取更高效,更标准的姿态数据,根据姿态特征协调RADOM FOREST提高姿态分类准确率,以及实现减小生成随机树的数量,加快推理速度。

(3)三维骨架化信息 瑜伽运动对于锻炼者的动作姿态,各身体部位角度有较高的要求,但传统的骨架化数据都是基于二维数据,无法准确获得人体三维特征。使用深度/RGB结合的AI成像摄像头获取数据,通过OPENPOSE开源库获取带有深度属性的三维骨架化信息,对于深度模型的准确性、可拓展性提供了一个良好的支持。 通过公式计算出人体每个骨架之间的角度,将这些角度信息作为人体姿态识别的判别标准,运用人体不同姿态时各躯干之间角度不同的原理,来区分人体姿态,以此来确保姿态识别的准确性。、

(4)计算棒协助树莓派增加设备运算力、提取图像特征值 在开发过程中,发现树莓派对于快速连续处理RGB/深度图像的任务有较大压力,时常出现树莓派系统卡顿乃至崩溃的现象。为此,项目采用接入运算帮的方式协助树莓派处理数据,在今后的产品设计上,我们将考虑更改算法、更换设备等方式解决算力不足的问题。

(5)TCP套接字管理设备接入 通过IOT服务平台项目可做到了设备与服务器,服务器与设备,设备与设备,服务器与用户之间实时信息传输。方便设备的集中管理,信息的集中化输入输出,开发过程中的协调与通信。

(6)Redis缓存减轻数据处理的运算压力 Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。采用Redis缓存的方式,缓存初始数据、输出数据和用户访问数据。减缓了服务器的运算与带宽等方面的压力。另外,由于开发过程中涉及到多语言通信的问题,项目使用了自行编写的简单的消息队列,Redis作为多种语言进程之间的通讯中转,成功解决多语言通讯问题。

(7)华为云服务器云存储 在华为云服务器中开放redis,使得服务器多进程以及服务器与边缘树莓派之间能够以简单的形式直进行信息交换。使用MYSQL存储标准姿态库。

(8)多设备协同 在开发过程中,遇到了用户终端、小熊派、树莓派和云服务器等设备之间的硬件通讯问题: ①用户终端与小熊派:采用NFC碰一碰通讯,传输WIFI配置信息。 ②小熊派与树莓派:采用UART串口通讯,传输WIFI配置信息。 ③小熊派与云服务器:采用TCP_Socket套接字传输设备信息,上报设备状况。 ④树莓派与云服务器:采用TCP_Socket套接字传输设备信息,上报设备状况,接受服务端指令。

总体来说,小熊派负责树莓派配置入网,树莓派负责关节点特征提取,云服务器负责姿态识别以及姿态评估校准运算。

您正在浏览的内容为涂鸦开发者平台注册用户自主发布,版权归原作者所有,涂鸦开发者平台不拥有其著作权,亦不承担相应法律责任,涂鸦开发者平台不对该等内容作出不违反、不侵权的陈述与保证。您应知晓并了解您对于该等内容的复制、改编、转发传播等任何其他使用行为应当符合法律法规并应取得相关权利人的许可,您的该等行为所造成的全部相应后果(包括但不限于侵权、违约、受损、与第三方的纠纷等)均应由您个人承担。内容知识产权相关条款可查看涂鸦开发者平台用户协议。如果您发现有涉嫌侵权的内容,请立即通过平台上的联系方式联系平台进行举报并发送有关证据,一经查实,平台将立刻删除涉嫌侵权内容。

喜欢举报