pythonとmediapipeを用いて肩と腰の角度を取得
現在、腰痛の改善を目的に座った姿勢が腰に良い姿勢か否かを判定するプログラムを作成しています。
今回は肩と腰の角度をpythonとmediapipeを用いて取得することができました。
まだ、試作の段階なのでコードの説明は省かせていただきます。
課題として、角度を求めるだけでは良い姿勢か悪い姿勢かを判定することができません。今後は、AIを用いて簡単に判定できるプログラムを作成していきます。
get_shoulder_hip.py
import cv2
import os
import numpy as np
import mediapipe as mp
import math
#体の部位の座標(x,y,z)と部位の可視性(v)を取得
def get_coordinate(landmark_num):
parts_array = {"x":0, "y":0, "z":0,"v":0}
parts_array["x"] = results.pose_landmarks.landmark[landmark_num].x
parts_array["y"] = results.pose_landmarks.landmark[landmark_num].y
parts_array["z"] = results.pose_landmarks.landmark[landmark_num].z
parts_array["v"] = results.pose_landmarks.landmark[landmark_num].visibility
return parts_array
#腰を中心とした、肩-腰-膝の角度を取得
def get_angle(array_hip,array_shoulder,array_knee):
x0,y0,z0=array_hip["x"],array_hip["y"],array_hip["z"]
x1,y1,z1=array_shoulder["x"],array_shoulder["y"],array_shoulder["z"]
x2,y2,z2=array_knee["x"],array_knee["y"],array_knee["z"]
##腰の角度の算出
vec1=[x1-x0,y1-y0,z1-z0]
vec2=[x2-x0,y2-y0,z2-z0]
absvec1=np.linalg.norm(vec1)
absvec2=np.linalg.norm(vec2)
inner=np.inner(vec1,vec2)
cos_theta=inner/(absvec1*absvec2)
theta=math.degrees(math.acos(cos_theta))
return theta
#肩を中心とした、耳ー肩ー腰の角度を取得
def shoulder_angle(array_shoulder,array_hip,array_ear):
x0,y0,z0=array_shoulder["x"],array_shoulder["y"],array_shoulder["z"]
x1,y1,z1=array_hip["x"],array_hip["y"],array_hip["z"]
x2,y2,z2=array_ear["x"],array_ear["y"],array_ear["z"]
##肩の角度の算出
vec1=[x1-x0,y1-y0,z1-z0]
vec2=[x2-x0,y2-y0,z2-z0]
absvec1=np.linalg.norm(vec1)
absvec2=np.linalg.norm(vec2)
inner=np.inner(vec1,vec2)
cos_theta=inner/(absvec1*absvec2)
theta=math.degrees(math.acos(cos_theta))
return theta
##main##
#ファイルの存在チェック
print(os.path.exists('picture/sample.jpg'))
# 初期設定
mp_holistic = mp.solutions.holistic
holistic = mp_holistic.Holistic(
static_image_mode=True,
min_detection_confidence=0.5)
#ファイルの読み込み
image = cv2.imread('picture/sample.jpg')
results = holistic.process(
cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
#左側の部位ごとの座標の取得
L_ear = get_coordinate(7)
L_shoulder = get_coordinate(11)
L_hip = get_coordinate(23)
L_knee = get_coordinate(25)
#右側の部位ごとの座標の取得
R_ear = get_coordinate(8)
R_shoulder = get_coordinate(12)
R_hip = get_coordinate(24)
R_knee = get_coordinate(26)
#腰と肩の角度の計算
if (L_shoulder["v"] > 0.60) and (L_hip["v"] > 0.60) and (L_knee["v"] > 0.60):
if (R_shoulder["v"] > 0.60) and (R_hip["v"] > 0.60) and (R_knee["v"] > 0.60):
R_angle = get_angle(R_hip,R_shoulder,R_knee)
L_angle = get_angle(L_hip,L_shoulder,L_knee)
#腰の角度
hip_angle = (L_angle + R_angle)/2
print(f"腰の角度(右腰と左腰の平均):{hip_angle}")
if (R_ear["v"] > 0.60) and (L_ear["v"] > 0.60):
R_shoulder_angle = shoulder_angle(R_shoulder,R_hip,R_ear)
L_shoulder_angle = shoulder_angle(L_shoulder,L_hip,L_ear)
#肩の角度
shoulder_angle = (R_shoulder_angle + L_shoulder_angle)/2
print(f"肩の角度(右肩と左肩の平均):{shoulder_angle}")
elif (R_ear["v"] > 0.60):
R_shoulder_angle = shoulder_angle(R_shoulder,R_hip,R_ear)
print(f"右肩の角度:{R_shoulder_angle}")
elif (L_ear["v"] > 0.60):
L_shoulder_angle = shoulder_angle(L_shoulder,L_hip,L_ear)
print(f"左肩の角度:{L_shoulder_angle}")
else:
print("肩の角度は検出できなかった")
else:
hip_angle = get_angle(L_hip,L_shoulder,L_knee)
print(f"左腰の角度:{hip_angle}")
if (L_ear["v"] > 0.60):
L_shoulder_angle = shoulder_angle(L_shoulder,L_hip,L_ear)
print(f"左肩の角度:{L_shoulder_angle}")
else:
print("肩の角度は検出できなかった")
else:
if (R_shoulder["v"] > 0.60) and (R_hip["v"] > 0.60) and (R_knee["v"] > 0.60):
#腰の角度
hip_angle = get_angle(R_hip,R_shoulder,R_knee)
print(f"右腰の角度:{hip_angle}")
if (R_ear["v"] > 0.60):
R_shoulder_angle = shoulder_angle(R_shoulder,R_hip,R_ear)
print(f"左肩の角度:{R_shoulder_angle}")
else:
print("腰、肩の角度は検出できなかった")