アイコン

佐藤さとる

梶研 [関節を座標に & 正面を出したい]

2024年05月07日

thumbnail

関節を座標に & 正面を出したい

出席率

  • 3年セミナー:??%

スケジュール

短期的な予定

  • mocopi と お料理センシング
    • シーンとランドマークを決める(~2月上旬)
    • SVM で動作判別する
    • 機械学習を深める
      • 機械学習の手法を知る
      • 使う手法を決める
      • データセットを探す
      • LSTM してみる
      • 主成分分析してみる
      • クラスタリング
      • 自己相関
    • お料理センシング
      • お料理でどんな動作があるかを知る
      • レシピを決める
      • センシングする
      • ?
    • 論文書く
    • 発表
  • BLEビーコンのuuidを書き換えたい
    • 通信内容を読み解く
    • shellコマンドで通信してみる
    • 実装してみる
  • BookWorm
    • Pasori と デスクトップアプリを接続する(技術検証)
    • nfc読み込み機能 & 画面を作る
    • API と連携させる
    • 管理者画面を作る

長期的な予定

  • ~?月 シーン検知?をする
  • ~?月 論文を書く
  • ~?月 論文発表したい

進捗報告

目的

料理中の動作を mocopi を使ってセンシングする。
このデータから最終的に位置推定を行う。

  • 一定の区間でどの動作をしているかを当てる (クラス分類)
  • 料理の手順を元にシーン検知を補正する
    • 例) 焼く動作 → 卵割る動作 はおかしい
  • 位置とシーンを相補的に補正する
    • 例) 冷蔵庫の前で焼く動作 はおかしい

前回

骨格を表示したら、はちゃめちゃなった
image.png (80.7 kB)

角度の単位を rad にしてみた
image.png (70.7 kB)
左肘以外は大丈夫ぽい?

blender で確認したら全然違った
スクリーンショット 2024-04-23 11.17.12.png (727.2 kB)

原因

単位は deg(度数法, はちゃめちゃな方) であってた
ベクトルの回転方法が正しくなかった

回転させる関数が、ベクトルのスタート位置(親関節)を考慮していなかった
例)
腰(ROOT) の座標が 0, 0, 0, つま先が 0, -90, 0 としたとき、
つま先を45度曲げても 0, -88, 2(適当) 程度のはずが、
この関数は 76.58131721, -47.27897899, 0 になってしまう

1def rotate(vec, roll, pitch, yaw): 2 r_x = np.array( 3 [[1, 0, 0], [0, np.cos(roll), -np.sin(roll)], [0, np.sin(roll), np.cos(roll)]] 4 ) 5 r_y = np.array( 6 [ 7 [np.cos(pitch), 0, np.sin(pitch)], 8 [0, 1, 0], 9 [-np.sin(pitch), 0, np.cos(pitch)], 10 ] 11 ) 12 r_z = np.array( 13 [[np.cos(yaw), -np.sin(yaw), 0], [np.sin(yaw), np.cos(yaw), 0], [0, 0, 1]] 14 ) 15 16 vec = np.dot(r_x, vec) 17 vec = np.dot(r_y, vec) 18 vec = np.dot(r_z, vec) 19 20 return vec

修正後

1def rotate(origin, end, roll, pitch, yaw): 2 vec = np.array(end) - np.array(origin) 3 4 ... 5 6 return vec + origin

人間が再現できる骨格だが、不思議な姿勢
image.png (65.2 kB)

回転をライブラリに任せる
image.png (64.1 kB)
image.png (71.8 kB)
腕がおかしい

リファクター

ライブラリを使って回転するようにした

1rot = Rotation.from_rotvec(np.array([y_rotate, x_rotate, z_rotate])) 2skeleton_copy[joint]["offset"] = rot.apply(data["offset"])
image.png (64.1 kB) image.png (64.4 kB)

正解
スクリーンショット 2024-05-06 19.00.14.png (478.9 kB)
肩のあたりが少し違う
デフォルトの姿勢は+90度(?)された状態ぽい
→ 簡単に直せるが、動作認識では問題ない(と考えられる)ため気にしない

正面を出す

考え方

  1. 腰や肩の左右を通る面の直角方向を正面とする
  2. 全ての点に近似する平面の直角方向を正面とする

1 は簡単だが、捻る動作に弱いため 2 を使う
最小二乗法 というのを使えばいいらしい

1import numpy as np 2 3# y = w[0] + w[1]x[1] + w[2]x[2]型。 4#今回はw = [1, 2, 3]とする。 5X = np.random.random((100, 2)) * 10 # 0から1*10の範囲をとる100*2の行列 6y = 1 + 2 * X[:, 0] + 3 * X[:, 1] + np.random.randn(100) 7#x0とx1の座標からyを作成。randnで本来の値にノイズを加えている。 8 9import matplotlib.pyplot as plt 10from mpl_toolkits.mplot3d import axes3d # 3D表示に使う 11from scipy import linalg # linalg.solve(A, b)  Ax = bの解を求める関数 12 13Xtil = np.c_[np.ones(X.shape[0]), X] # Xの行列の左端に[1,1,1,...,1]^Tを加える。(7)式を確認しよう 14A = np.dot(Xtil.T, Xtil) # 標準形A,bに当てはめる。 15b = np.dot(Xtil.T, y) 16w = linalg.solve(A, b) # (8)式をwについて解く。 17 18xmesh, ymesh = np.meshgrid(np.linspace(0, 10, 20), 19 np.linspace(0, 10, 20)) 20zmesh = (w[0] + w[1] * xmesh.ravel() + 21 w[2] * ymesh.ravel()).reshape(xmesh.shape) 22 23fig = plt.figure() 24ax = fig.add_subplot(111, projection='3d') 25ax.scatter(X[:, 0], X[:, 1], y, color='k') 26ax.plot_wireframe(xmesh, ymesh, zmesh, color='r') 27plt.show()

Pythonで最小二乗法をしてみよう
image.png (92.2 kB)
簡単にできた

骨格でやってみる
image.png (75.8 kB)
おかしい

原因

  1. 基準面が x-z だった
  2. x, y, z が入れ替わってた

※基準面を骨格に合わせて座標を変換している (多分)
x-z だった場合、y軸方向で上下させて傾けている感じ?
image.png (76.0 kB)

なんか違う気がする

  • お辞儀したら傾いてしまう
  • 基準面によって正面が出せない方向がある

そもそも正面を出す目的は3次元を2次元平面に落とし込むとき、
なるべく大きな動作になるようにするためであり、
必ずしも正面である必要はない(と思う)

別の案

  1. y軸と並行な腰を通る直線($L_1$)を取る
  2. その直線から最も遠い点($P_1$)を取る
  3. Aから最も遠い点($P_2$)を取る
  4. $L_1$ と並行で $P_1$ $P_2$を結ぶ直線($L_2$) と重なる平面を使う

進路関係

余談

プロフィールサイト作り直した

prev.satooru.mesatooru.me
image.png (257.1 kB)

image.png (584.7 kB)

ペンギンを愛でた

IMG_6649.JPG (1.5 MB) IMG_6657.JPG (2.8 MB)

サークルで稲武野外学習してきた

IMG_6752.JPG (5.5 MB) IMG_6686.JPG (4.7 MB) IMG_6715.JPG (7.0 MB)