欢迎访问我的网站,希望内容对您有用,感兴趣的可以加入我们的社群。

使用mediapipe进行动作识别

人工智能 迷途小书童 3年前 (2022-08-09) 3433次浏览 0个评论

环境

  • windows 10 64bit
  • mediapipe 0.8.10.1

前言

本文使用 google 家的 mediapipe 机器学习框架,结合 opencvnumpy,实现了一个实时识别 站立坐下走动挥手 共4个动作的简单系统。

mediapipe 能做的事情非常多,感兴趣的童鞋可以去研究研究。

mediapipe action recognition

代码实践

首先,需要安装 mediapipe

  1. pip install -U mediapipe

接着,来看代码,部分加了注释

  1. import cv2
  2. import mediapipe as mp
  3. import numpy as np
  4. def calculate_angle(a, b, c):
  5. '''
  6. 计算角度
  7. :param a:
  8. :param b:
  9. :param c:
  10. :return:
  11. '''
  12. a = np.array(a)
  13. b = np.array(b)
  14. c = np.array(c)
  15. radians = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(a[1] - b[1], a[0] - b[0])
  16. angle = np.abs(radians * 180.0 / np.pi)
  17. if angle > 180.0:
  18. angle = 360 - angle
  19. return angle
  20. def calculate_dist(a, b):
  21. '''
  22. 计算欧式距离
  23. :param a:
  24. :param b:
  25. :return:
  26. '''
  27. a = np.array(a)
  28. b = np.array(b)
  29. dist = np.linalg.norm(a - b)
  30. return dist
  31. if __name__ == '__main__':
  32. mp_drawing = mp.solutions.drawing_utils
  33. mp_pose = mp.solutions.pose
  34. cap = cv2.VideoCapture('liuruoying.mp4')
  35. # 分辨率
  36. frame_width = int(cap.get(3))
  37. frame_height = int(cap.get(4))
  38. # 保存结果视频
  39. out = cv2.VideoWriter("result.mp4", cv2.VideoWriter_fourcc(*'mp4v'), 30, (frame_width, frame_height))
  40. counter = 0
  41. stage = None
  42. with mp_pose.Pose(min_detection_confidence=0.3, min_tracking_confidence=0.8) as pose:
  43. while cap.isOpened():
  44. ret, frame = cap.read()
  45. if not ret:
  46. break
  47. # 转换下颜色空间
  48. image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
  49. # 这里设置为不可写
  50. image.flags.writeable = False
  51. # 检测
  52. results = pose.process(image)
  53. # 这里设置为可写,颜色也转换回去
  54. image.flags.writeable = True
  55. image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
  56. # 提取关键点
  57. try:
  58. landmarks = results.pose_landmarks.landmark
  59. # 获取相应关键点的坐标
  60. lshoulder = [landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].x,
  61. landmarks[mp_pose.PoseLandmark.LEFT_SHOULDER.value].y]
  62. lelbow = [landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].x,
  63. landmarks[mp_pose.PoseLandmark.LEFT_ELBOW.value].y]
  64. lwrist = [landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].x,
  65. landmarks[mp_pose.PoseLandmark.LEFT_WRIST.value].y]
  66. lhip = [landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].x,
  67. landmarks[mp_pose.PoseLandmark.LEFT_HIP.value].y]
  68. lankle = [landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].x,
  69. landmarks[mp_pose.PoseLandmark.LEFT_ANKLE.value].y]
  70. lknee = [landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].x,
  71. landmarks[mp_pose.PoseLandmark.LEFT_KNEE.value].y]
  72. rshoulder = [landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].x,
  73. landmarks[mp_pose.PoseLandmark.RIGHT_SHOULDER.value].y]
  74. relbow = [landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW.value].x,
  75. landmarks[mp_pose.PoseLandmark.RIGHT_ELBOW.value].y]
  76. rwrist = [landmarks[mp_pose.PoseLandmark.RIGHT_WRIST.value].x,
  77. landmarks[mp_pose.PoseLandmark.RIGHT_WRIST.value].y]
  78. rhip = [landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].x,
  79. landmarks[mp_pose.PoseLandmark.RIGHT_HIP.value].y]
  80. rankle = [landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value].x,
  81. landmarks[mp_pose.PoseLandmark.RIGHT_ANKLE.value].y]
  82. rknee = [landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value].x,
  83. landmarks[mp_pose.PoseLandmark.RIGHT_KNEE.value].y]
  84. # 计算角度
  85. langle = calculate_angle(lshoulder, lelbow, lwrist)
  86. rangle = calculate_angle(rshoulder, relbow, rwrist)
  87. lsangle = calculate_angle(lhip, lshoulder, lelbow)
  88. rsangle = calculate_angle(rhip, rshoulder, relbow)
  89. ankdist = calculate_dist(lankle, rankle)
  90. rwdist = calculate_dist(rhip, rwrist)
  91. lwdist = calculate_dist(lhip, lwrist)
  92. rhangle = calculate_angle(rshoulder, rhip, rknee)
  93. lhangle = calculate_angle(lshoulder, lhip, lknee)
  94. rkangle = calculate_angle(rankle, rknee, rhip)
  95. lkangle = calculate_angle(lankle, lknee, lhip)
  96. # 这块是具体的业务逻辑,各个数值,可根据自己实际情况适当调整
  97. if ((rhangle > 80 and lhangle > 80) and (rhangle < 110 and lhangle < 110) and (
  98. lkangle < 100 and rkangle < 100)):
  99. stage = 'sitting'
  100. elif (langle < 160 and langle > 40) or (rangle < 160 and rangle > 40):
  101. if ((lsangle > 20 or rsangle > 20) and (lwdist > 0.3 or rwdist > 0.3)):
  102. stage = "wave"
  103. elif ((ankdist > 0.084) and (langle > 150) and (rangle > 150)):
  104. counter += 1
  105. if counter > 1:
  106. stage = 'walking'
  107. else:
  108. stage = 'standing'
  109. counter = 0
  110. except:
  111. pass
  112. cv2.rectangle(image, (0, 0), (225, 73), (245, 117, 16), -1)
  113. cv2.putText(image, 'STAGE', (65, 12), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0), 1, cv2.LINE_AA)
  114. cv2.putText(image, stage, (60, 60), cv2.FONT_HERSHEY_SIMPLEX, 2, (255, 255, 255), 2, cv2.LINE_AA)
  115. # 画骨骼关键点
  116. mp_drawing.draw_landmarks(image, results.pose_landmarks, mp_pose.POSE_CONNECTIONS,
  117. mp_drawing.DrawingSpec(color=(245, 117, 66), thickness=2, circle_radius=2),
  118. mp_drawing.DrawingSpec(color=(245, 66, 230), thickness=2, circle_radius=2)
  119. )
  120. # 显示结果帧
  121. cv2.imshow('mediapipe demo', image)
  122. # 保存结果帧
  123. out.write(image)
  124. # 按q退出
  125. if cv2.waitKey(10) & 0xFF == ord('q'):
  126. break
  127. # 资源释放
  128. cap.release()
  129. cv2.destroyAllWindows()
喜欢 (0)

您必须 登录 才能发表评论!