実現したいこと
pythonで2つのxyzの3次元ベクトルbvhファイルを生成したいので、
角度を計算してMOTIONのXrotation,Yrotation,Zrotationに適切な値を設定したいです。
発生している問題・分からないこと
動かした時におかしな挙動になってしまいます。
MOTIONを設定せず、OFFSETのみ設定した時の初期ポーズは適切に出力できるため事前の座標取得はうまくいっていると思うのですが、MOTIONの角度を設定した時に動かした時にうまくいきません。どうすれば良いでしょうか
こちらの動画の腕の動きを取得したいです
動画
#動画の動きはmediapipeを使って取得しており、理想としてはこのような動きを取得したいです。
出力したい動き
bvhのMOTION部分には各要素の角度が100フレーム分ありますが、文字数制限のため6フレームのみ記入しています、
該当のソースコード
python
1import numpy as np 2import math 3 4#numpy配列をスペースありのstring文字列に変換 5def np2str(array): 6 for i in range(len(array)): 7 array[i]=round(array[i], 3) 8 9 #array[1],array[2]=array[2],array[1] 10 11 out=" ".join(map(str,array)) 12 13 return out 14 15#numpy配列をスペースありのstring文字列に変換 16def np2strForList(array): 17 out=[] 18 for arr in array: 19 out.append(" ".join(map(str,arr))) 20 21 22 out=" ".join(map(str,out)) 23 24 25 return out 26 27 28#xyzの角度を取得 29def rotxyz(vec1,vec2): 30 31 #各2次元ベクトル 32 vec1xy=np.array([vec1[0],vec1[1],0]) 33 vec1yz=np.array([0,vec1[1],vec1[2]]) 34 vec1zx=np.array([vec1[0],0,vec1[2]]) 35 vec2xy=np.array([vec2[0],vec2[1],0]) 36 vec2yz=np.array([0,vec2[1],vec2[2]]) 37 vec2zx=np.array([vec2[0],0,vec2[2]]) 38 #各長さ 39 vec1xyLen=np.linalg.norm(vec1xy) 40 vec1yzLen=np.linalg.norm(vec1yz) 41 vec1zxLen=np.linalg.norm(vec1zx) 42 vec2xyLen=np.linalg.norm(vec2xy) 43 vec2yzLen=np.linalg.norm(vec2yz) 44 vec2zxLen=np.linalg.norm(vec2zx) 45 #各内積 46 xInner=np.dot(vec1yz,vec2yz) 47 yInner=np.dot(vec1zx,vec2zx) 48 zInner=np.dot(vec1xy,vec2xy) 49 50 #各角度 51 #xrot=np.arccos(xInner/(vec1yzLen*vec2yzLen)) 52 #yrot=np.arccos(yInner/(vec1zxLen*vec2zxLen)) 53 #zrot=np.arccos(zInner/(vec1xyLen*vec2xyLen)) 54 55 xrot=(xInner/(vec1yzLen*vec2yzLen)) 56 yrot=(yInner/(vec1zxLen*vec2zxLen)) 57 zrot=(zInner/(vec1xyLen*vec2xyLen)) 58 59 if math.isnan(xrot): 60 xrot=0 61 if math.isnan(yrot): 62 yrot=0 63 if math.isnan(zrot): 64 zrot=0 65 66 xDeg=math.degrees(xrot) 67 yDeg=math.degrees(yrot) 68 zDeg=math.degrees(zrot) 69 xDeg=round(xDeg, 3) 70 yDeg=round(yDeg, 3) 71 zDeg=round(zDeg, 3) 72 #帰り値は全てfloat型 73 return xDeg,yDeg,zDeg 74 75#フレーム数 76frames=[[[0.167, -0.453, 0.051], [-0.128, -0.474, 0.047], [0.224, -0.255, -0.007], [-0.256, -0.29, 0.014], [0.35, -0.366, -0.179], [-0.358, -0.388, -0.155]], [[0.17, -0.453, 0.049], [-0.128, -0.475, 0.044], [0.225, -0.26, -0.018], [-0.256, -0.294, 0.006], [0.347, -0.372, -0.194], [-0.358, -0.404, -0.163]], 77 [[0.172, -0.453, 0.049], [-0.128, -0.475, 0.044], [0.229, -0.261, -0.019], [-0.26, -0.299, 0.006], [0.347, -0.374, -0.196], [-0.358, -0.416, -0.163]], [[0.177, -0.453, 0.054], [-0.126, -0.475, 0.052], [0.235, -0.261, -0.015], [-0.262, -0.306, 0.022], [0.352, -0.373, -0.191], [-0.359, -0.426, -0.129]], 78 [[0.181, -0.453, 0.051], [-0.124, -0.475, 0.047], [0.243, -0.261, -0.016], [-0.262, -0.312, 0.012], [0.354, -0.374, -0.191], [-0.355, -0.432, -0.137]], [[0.184, -0.453, 0.051], [-0.122, -0.476, 0.046], [0.248, -0.261, -0.016], [-0.263, -0.318, 0.014], [0.362, -0.374, -0.191], [-0.347, -0.437, -0.129]]] 79 80 81for frame in range(len(frames)): 82 for i1 in range(6): 83 for i2 in range(3): 84 frames[frame][i1][i2]=round(frames[frame][i1][i2],3) 85print((frames)) 86 87 88 89 90 91 92VectorUp=np.array([1,0,0]) 93Motions=[] 94#フレームごとに取得 95for index, landmarks in enumerate(frames): 96 97 98 #位置の設定。(L,Rは絶対位置、Left,Rightは相対位置) 99 #部位ごとに取得========================= 100 Base=np.array([0,0,0]) 101 #上半身ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 102 LShoulder=np.array(landmarks[0])# 左肩 103 RShoulder=np.array(landmarks[1])# 右肩 104 LElbow=np.array(landmarks[2])# 左肘 105 RElbow=np.array(landmarks[3])# 右肘 106 LWrist=np.array(landmarks[4])# 左手首 107 RWrist=np.array(landmarks[5])# 右手首 108 HeartAbsol=((LShoulder+RShoulder)/2)#胸(左右の肩の中間点) 109 110 111 if index==0:#初期オフセット設定 112 113 114 #体の初期位置================================================================ 115 LeftShoulder_origin=LShoulder-HeartAbsol#左腰 116 RightShoulder_origin=RShoulder-HeartAbsol#左腰 117 LeftElbow_origin=LElbow-LShoulder#右ひじ 118 RightElbow_origin=RElbow-RShoulder#左ひじ 119 LeftWrist_origin=LWrist-LElbow#右手首 120 RightWrist_origin=RWrist-RElbow#左手首 121 122 123 root=[0,0,0,0,0,0]#座標、回転 124 #腰から上半身、右足、左足の三つに分かれる 125 #左足================================================================ 126 LeftShoulder=LShoulder-HeartAbsol#左腰 127 RightShoulder=RShoulder-HeartAbsol#左腰 128 LeftElbow=LElbow-LShoulder#右ひじ 129 RightElbow=RElbow-RShoulder#左ひじ 130 LeftWrist=LWrist-LElbow#右手首 131 RightWrist=RWrist-RElbow#左手首 132 133 #角度 134 #左 135 LeftShoulder_rot=rotxyz(VectorUp,LeftShoulder) 136 LeftElbow_rot=rotxyz(LeftShoulder,LeftElbow) 137 LeftWrist_rot=rotxyz(LeftElbow,LeftWrist) 138 139 #右 140 RightShoulder_rot=rotxyz(VectorUp,RightShoulder) 141 RightElbow_rot=rotxyz(RightShoulder,RightElbow) 142 RightWrist_rot=rotxyz(RightElbow,RightWrist) 143 144 145 146 #モーション作成 147 Motions.append(np2strForList([ 148 np.array([0,0,0]),np.array([0,0,0]), 149 LeftShoulder_rot,LeftElbow_rot,LeftWrist_rot, 150 RightShoulder_rot,RightElbow_rot,RightWrist_rot 151 ])) 152 153 154bvh_content_complex_japanese = f""" 155HIERARCHY 156ROOT Base 157{{ 158 OFFSET 0.00 0.00 0.00 159 CHANNELS 6 Xposition Yposition Zposition Zrotation Yrotation Xrotation 160 JOINT LeftShoulder 161 {{ 162 OFFSET 0.00 0.00 0.00 163 CHANNELS 3 Zrotation Yrotation Xrotation 164 JOINT LeftElbow 165 {{ 166 OFFSET {np2str(LeftShoulder_origin)} 167 CHANNELS 3 Zrotation Yrotation Xrotation 168 JOINT RightWrist 169 {{ 170 OFFSET {np2str(LeftElbow_origin)} 171 CHANNELS 3 Zrotation Yrotation Xrotation 172 End Site 173 {{ 174 OFFSET {np2str(LeftWrist_origin)} 175 }} 176 }} 177 }} 178 }} 179 JOINT RightShoulder 180 {{ 181 OFFSET 0.00 0.00 0.00 182 CHANNELS 3 Zrotation Yrotation Xrotation 183 JOINT RightElbow 184 {{ 185 OFFSET {np2str(RightShoulder_origin)} 186 CHANNELS 3 Zrotation Yrotation Xrotation 187 JOINT RightWrist 188 {{ 189 OFFSET {np2str(RightElbow_origin)} 190 CHANNELS 3 Zrotation Yrotation Xrotation 191 End Site 192 {{ 193 OFFSET {np2str(RightWrist_origin)} 194 }} 195 }} 196 }} 197 }} 198}} 199MOTION 200Frames: {len(frames)} 201Frame Time: 0.0333333 202""" 203 204 205 206 207#BVHファイル書き込み 208bvh_complex_japanese_file_path = './BVHfile/bvh_check.bvh' 209with open(bvh_complex_japanese_file_path, 'w') as file: 210 file.write(bvh_content_complex_japanese.strip()) 211 file.write("\n")#改行 212 213 for i in Motions: 214 file.write(i) 215 file.write("\n")#改行 216 217 pass
以下が出力されるbvhファイルです
bvh
1HIERARCHY 2ROOT Base 3{ 4 OFFSET 0.00 0.00 0.00 5 CHANNELS 6 Xposition Yposition Zposition Zrotation Yrotation Xrotation 6 JOINT LeftShoulder 7 { 8 OFFSET 0.00 0.00 0.00 9 CHANNELS 3 Zrotation Yrotation Xrotation 10 JOINT LeftElbow 11 { 12 OFFSET 0.148 0.011 0.002 13 CHANNELS 3 Zrotation Yrotation Xrotation 14 JOINT RightWrist 15 { 16 OFFSET 0.057 0.198 -0.058 17 CHANNELS 3 Zrotation Yrotation Xrotation 18 End Site 19 { 20 OFFSET 0.126 -0.111 -0.172 21 } 22 } 23 } 24 } 25 JOINT RightShoulder 26 { 27 OFFSET 0.00 0.00 0.00 28 CHANNELS 3 Zrotation Yrotation Xrotation 29 JOINT RightElbow 30 { 31 OFFSET -0.148 -0.01 -0.002 32 CHANNELS 3 Zrotation Yrotation Xrotation 33 JOINT RightWrist 34 { 35 OFFSET -0.128 0.184 -0.033 36 CHANNELS 3 Zrotation Yrotation Xrotation 37 End Site 38 { 39 OFFSET -0.102 -0.098 -0.169 40 } 41 } 42 } 43 } 44} 45MOTION 46Frames: 6 47Frame Time: 0.0333333 480 0 0 0 0 0 0.0 57.291 57.151 51.0 39.603 19.72 -16.282 56.699 -24.503 0.0 -57.291 -57.151 -53.507 55.67 29.297 -19.541 40.915 -8.992 490 0 0 0 0 0 0.0 57.288 57.14 48.617 35.606 19.717 -13.207 57.107 -25.697 0.0 -57.288 -57.14 -52.07 55.192 29.548 -20.722 42.343 -11.809 500 0 0 0 0 0 0.0 57.288 57.142 48.426 36.07 20.28 -12.94 56.952 -26.212 0.0 -57.288 -57.142 -51.933 55.316 30.933 -21.937 41.332 -13.064 510 0 0 0 0 0 0.0 57.295 57.145 51.944 36.577 20.497 -12.6 56.935 -25.959 0.0 -57.295 -57.145 -55.276 56.031 32.594 -27.259 40.624 -12.133 520 0 0 0 0 0 0.0 57.291 57.147 49.847 38.36 21.484 -13.486 56.356 -26.559 0.0 -57.291 -57.147 -52.964 55.717 33.78 -25.769 41.355 -11.885 530 0 0 0 0 0 0.0 57.288 57.135 48.852 38.894 22.142 -13.486 56.317 -25.397 0.0 -57.288 -57.135 -52.458 56.075 34.838 -27.178 39.234 -12.924 54
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
出力したbvhファイルををblenderにインポートして動かしました。
右が上記のbvhをインポートしたもの、左がbvhファイルのFrame Time: 0.0333333以降を削除したものです。左のような動きを出力したいです