云天 发表于 2021-11-26 22:15:46

Mind+Python+Mediapipe项目——AI健身之哑铃

【项目背景】    平时缺乏锻炼,爱好各种美食,没有管理好热量输入的人,身材也容易随着年龄的增长而发胖,身体健康也会更容易出现问题。    健身锻炼是预防肥胖的有效手段,还能帮你强化体能,提高自身免疫力。很多人总是等到胖起来才想到要锻炼,但是这个时候,你的体能素质已经直线下降,很多运动是无法驾驭得了的,这个时候你更容易放弃健身,选择中途而废。    不过,很多人出于各种生活、工作的原因,没有时间锻炼,无法在户外锻炼或者去健身房锻炼,只能利用琐碎时间在家锻炼。    很多人之所以健身锻炼不久就放弃了,绝大多数就是因为太枯燥了,要是能够采取丰富多彩的训练方式,相信很多人一定可以坚持下来的。【项目设计】    本项目以使用哑铃健身为例。通过AI识别人体姿态,灯光响应完成度,增加锻炼趣味性,让健身者乐于锻炼。【锻炼工具哑铃】    哑铃是一种用于增强肌肉力量训练的简单器材。很多朋友在健身或者锻炼的时候,都会使用到哑铃。    如:单臂弯举    目标肌群:肱二头肌、肱肌和肱桡肌。动作要领:稳坐于长凳上,保持大腿与地面平行,低手抓握哑铃,肘部靠近大腿内侧,并高于膝盖位置,手肘靠在大腿内侧做弯举动作。如果哑铃重量比较重,切记不要用甩的方式,避免手臂受伤。【Mediapipe+Pinpong库安装】    MediaPipe 是一款由 Google Research 开发并开源的多媒体机器学习模型应用框架。在谷歌,一系列重要产品,如 YouTube、Google Lens、ARCore、Google Home 以及 Nest,都已深度整合了 MediaPipe。



安装过程请参考:https://mc.dfrobot.com.cn/thread-311477-1-1.html
【姿态识别测试】    使用Mediapipe开源代码,对网络跳舞视频进行姿态识别测试。    测试代码:
<font face="微软雅黑">
import cv2
import mediapipe as mp
mp_drawing = mp.solutions.drawing_utils

mp_pose = mp.solutions.pose

# For webcam input:
cap = cv2.VideoCapture("wudao4.mp4")
with mp_pose.Pose(
    min_detection_confidence=0.5,
    min_tracking_confidence=0.5) as pose:
while cap.isOpened():
    success, image = cap.read()
    if not success:
      print("Ignoring empty camera frame.")
      # If loading a video, use 'break' instead of 'continue'.
      continue

    # To improve performance, optionally mark the image as not writeable to
    # pass by reference.
    image.flags.writeable = False
    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    results = pose.process(image)

    # Draw the pose annotation on the image.
    image.flags.writeable = True
    image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
    mp_drawing.draw_landmarks(
      image,
      results.pose_landmarks,
      mp_pose.POSE_CONNECTIONS)
    # Flip the image horizontally for a selfie-view display.
    cv2.imshow('MediaPipe Pose', cv2.flip(image, 1))
    if cv2.waitKey(5) & 0xFF == 27:
      break
cap.release()
</font>测试视频
https://www.bilibili.com/video/BV1MS4y1X7W3?share_source=copy_web
【手臂姿态测试】
    在“PoseModule.py”文件中定义类“poseDetector”状态检测,代码如下:
<font face="微软雅黑">
import math
import mediapipe as mp
import cv2
class poseDetector():

    def __init__(self, mode=False, upBody=False, smooth=True,
               detectionCon=0.5, trackCon=0.5):

      self.mode = mode
      self.upBody = upBody
      self.smooth = smooth
      self.detectionCon = detectionCon
      self.trackCon = trackCon

      self.mpDraw = mp.solutions.drawing_utils
      self.mpPose = mp.solutions.pose
      self.pose = self.mpPose.Pose(self.mode, self.upBody, self.smooth,
                                     self.detectionCon, self.trackCon)

    def findPose(self, img, draw=True):
      imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
      self.results = self.pose.process(imgRGB)
      if self.results.pose_landmarks:
            if draw:
                self.mpDraw.draw_landmarks(img, self.results.pose_landmarks,
                                           self.mpPose.POSE_CONNECTIONS)
      return img

    def findPosition(self, img, draw=True):
      self.lmList = []
      if self.results.pose_landmarks:
            for id, lm in enumerate(self.results.pose_landmarks.landmark):
                h, w, c = img.shape
                # print(id, lm)
                cx, cy = int(lm.x * w), int(lm.y * h)
                self.lmList.append()
                if draw:
                  cv2.circle(img, (cx, cy), 5, (255, 0, 0), cv2.FILLED)
      return self.lmList

    def findAngle(self, img, p1, p2, p3, draw=True):

      # Get the landmarks
      x1, y1 = self.lmList
      x2, y2 = self.lmList
      x3, y3 = self.lmList

      # Calculate the Angle
      angle = math.degrees(math.atan2(y3 - y2, x3 - x2) -
                           math.atan2(y1 - y2, x1 - x2))
      if angle < 0:
            angle += 360

      # print(angle)

      # Draw
      if draw:
            cv2.line(img, (x1, y1), (x2, y2), (255, 255, 255), 3)
            cv2.line(img, (x3, y3), (x2, y2), (255, 255, 255), 3)
            cv2.circle(img, (x1, y1), 10, (0, 0, 255), cv2.FILLED)
            cv2.circle(img, (x1, y1), 15, (0, 0, 255), 2)
            cv2.circle(img, (x2, y2), 10, (0, 0, 255), cv2.FILLED)
            cv2.circle(img, (x2, y2), 15, (0, 0, 255), 2)
            cv2.circle(img, (x3, y3), 10, (0, 0, 255), cv2.FILLED)
            cv2.circle(img, (x3, y3), 15, (0, 0, 255), 2)
            cv2.putText(img, str(int(angle)), (x2 - 50, y2 + 50),
                        cv2.FONT_HERSHEY_PLAIN, 2, (0, 0, 255), 2)
      return angle
</font>    测试手臂姿态代码:
<font face="微软雅黑">
import numpy as np
import time
import PoseModule as pm
import cv2
cap = cv2.VideoCapture(0)
detector = pm.poseDetector()
count = 0
dir = 0
pTime = 0
success=True
while success:
    success, img = cap.read()
    img = cv2.resize(img, (640, 480))

    img = detector.findPose(img, False)
    lmList = detector.findPosition(img, False)
   
    if len(lmList) != 0:
      # 右臂
      angle = detector.findAngle(img, 12, 14, 16)
      # 左臂
      #angle = detector.findAngle(img, 11, 13, 15,False)
      per = np.interp(angle, (210, 310), (0, 100))
      light = int(np.interp(angle, (220, 310), (119, 0)))
      # print(angle, per)
      # 计算个数
      
      if per == 100:
            
            if dir == 0:
                count += 0.5
                dir = 1
      if per == 0:
            
            if dir == 1:
                count += 0.5
                dir = 0
      #print(count)
      cv2.putText(img, str(int(count)), (45, 460), cv2.FONT_HERSHEY_PLAIN, 7,(255, 0, 0), 8)
    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img, str(int(fps)), (50, 100), cv2.FONT_HERSHEY_PLAIN, 5,(255, 0, 0), 5)
    cv2.imshow("Image", img)
    cv2.waitKey(1)
</font>

【Pinpong库测试】

测试代码:<font face="微软雅黑">
# -*- coding: utf-8 -*-

#实验效果:控制WS2812单线RGB LED灯
#接线:使用windows或linux电脑连接一块microbit主控板,ws2812灯接到D9口
import time
from pinpong.board import Board,Pin,NeoPixel

NEOPIXEL_PIN = Pin.P0
PIXELS_NUM = 120 #灯数

Board("microbit").begin()#初始化,选择板型和端口号,不输入端口号则进行自动识别
#Board("microbit","COM36").begin()#windows下指定端口初始化
#Board("microbit","/dev/ttyACM0").begin()   #linux下指定端口初始化
#Board("microbit","/dev/cu.usbmodem14101").begin()   #mac下指定端口初始化

np = NeoPixel(Pin(NEOPIXEL_PIN), PIXELS_NUM)

while True:
np = (0, 255 ,0) #设置第一个灯RGB亮度
np = (255, 0, 0) #设置第二个灯RGB亮度
np = (0, 0, 255) #设置第三个灯RGB亮度
np = (255, 0, 255) #设置第四个灯RGB亮度
time.sleep(1)

np = (0, 255, 0)
np = (255, 0, 0)
np = (255, 255, 0)
np = (0, 0, 255)
time.sleep(1)

np.rainbow(0,PIXELS_NUM,0,0x0000FF)
time.sleep(1)
for i in range(PIXELS_NUM):
    np.rotate(1)
    time.sleep(1)

for i in range(PIXELS_NUM):
    np.shift(1)
    time.sleep(1)

np.clear()
time.sleep(1)

np.range_color(0,PIXELS_NUM,0xFF0000)
time.sleep(1)
np.range_color(0,PIXELS_NUM,0x00FF00)
time.sleep(1)
np.range_color(0,PIXELS_NUM,0x0000FF)
time.sleep(1)

np.clear()
time.sleep(1)

</font>





【完整程序】

<font face="微软雅黑">
import numpy as np
import time
import PoseModule as pm
import cv2
import time
from pinpong.board import Board,Pin,NeoPixel
NEOPIXEL_PIN = Pin.P0
PIXELS_NUM = 120 #灯数
Board("microbit").begin()#初始化
cap = cv2.VideoCapture(0)
detector = pm.poseDetector()
count = 0
dir = 0
pTime = 0
npX = NeoPixel(Pin(NEOPIXEL_PIN), PIXELS_NUM)
success=True
npX.clear()
time.sleep(1)
while success:
    success, img = cap.read()
    img = cv2.resize(img, (640, 480))

    img = detector.findPose(img, False)
    lmList = detector.findPosition(img, False)
   
    if len(lmList) != 0:
      # 右臂
      angle = detector.findAngle(img, 12, 14, 16)
      # 左臂
      #angle = detector.findAngle(img, 11, 13, 15,False)
      per = np.interp(angle, (210, 310), (0, 100))
      light = int(np.interp(angle, (220, 310), (119, 0)))
      # print(angle, per)
      # 计算个数
      
      if per == 100:
            
            if dir == 0:
                count += 0.5
                dir = 1
      if per == 0:
            
            if dir == 1:
                count += 0.5
                dir = 0
      #print(count)
      #npX.range_color(light,119,0x000000)
      #npX.range_color(0,light,0xFF0000)
      print(light)
      npX.range_color(light,119,0x000000)
      npX.rainbow(0,light,0,0x0000FF)
      cv2.putText(img, str(int(count)), (45, 460), cv2.FONT_HERSHEY_PLAIN, 7,(255, 0, 0), 8)
    cTime = time.time()
    fps = 1 / (cTime - pTime)
    pTime = cTime
    cv2.putText(img, str(int(fps)), (50, 100), cv2.FONT_HERSHEY_PLAIN, 5,(255, 0, 0), 5)
    cv2.imshow("Image", img)
    cv2.waitKey(1)
</font>
【演示视频】https://www.bilibili.com/video/BV1P44y1e7ZC?share_source=copy_web

张欣 发表于 2022-12-10 20:36:41

你好,不太会用这个,出错的比较多,能加个联系方式沟通吗

谭周强 发表于 2023-1-30 14:54:52

老师 我这边出现报错 可以看一下吗

花生编程 发表于 2023-1-31 08:12:06

厉害厉害

花生编程 发表于 2023-1-31 08:14:14

赞!!!

三春牛-创客 发表于 2023-1-31 08:19:02

厉害厉害

三春牛-创客 发表于 2023-1-31 08:46:54

这个很不错哦

曾剑波 发表于 2023-10-11 21:43:01

这个可以来学习一下
页: [1]
查看完整版本: Mind+Python+Mediapipe项目——AI健身之哑铃