こんにちは。AMBL株式会社のR&D部のエイドリアンです。この記事はAMBLアドベントカレンダー2022の記事です。
概要
腕立ては好きですか?私は好きです。が、使ってる筋肉を意識しながら己の限界まで頑張ろうとすると、「あれ?今って何回やったっけ?」となりがちです。結果として達成感がなく、自分がちゃんと成長したかどうかさえ分からなくなってしまいます。ですので、今回は腕立てをカウントしてくれるものをちらっと作ってみました!
今ここで限界を超えろ。それしか道はねぇ。
~ヤミ・スケヒロ~
やりたいこと
やりたいこと極めて単純です:腕立てを数える!
ではどうすればいいでしょうか?まず最初に腕立てについて考えてみましょう!
普通の腕立て
ここによりますと、腕立ての手順は下記の通りだそうです。
- 四つん這いの状態になり、手を肩幅よりも少し広めにして着きましょう。
- 足を伸ばしてつま先を立て、頭から足首までがまっすぐになるようにしましょう。
- まっすぐな姿勢をキープしながら脇を締めて肘を曲げ、体を床に着くギリギリまでゆっくりと下ろしましょう。
- 床を押して肘を伸ばし、体を持ち上げましょう。③と④を繰り返しましょう。
スタート、エンド (0, 100%)
出典: https://www.shopjapan.co.jp/diet_labo/training/article_026/
途中(50%)
出典: https://www.shopjapan.co.jp/diet_labo/training/article_026/
注目していただきたいのは、1のつま先を立てと4の体を持ち上げの部分です。この2つのポイントが我々の腕立てカウンター(以下Push-up counter)の重要な部分になります。
方法
ここでPush-up counterの方法を紹介します。簡単な処理フローは下記の図で表しております。
それでは順番に説明していきます。
①画像取得
うん、画像がないと始まらないので、次に行きます。
②姿勢検知
今回は(も)GoogleさんMediapipeの姿勢検知(もしくは骨格検知)モデル、Holisticモデルを採用します。必要にやりやすいし、精度、Performance共に申し分ない(遊ぶには)なのでおすすめです。
腕立てを検知する、肩、手首、足首の3つの点が必要です。ですので、下記のMediapipeのLandmarksから11,27,15を使います。
出典: https://google.github.io/mediapipe/solutions/pose.html#pose-landmark-model-blazepose-ghum-3d
③角度算出
そしてそれぞれの座標から内積を求め、下記のtheta
の角度を算出します。
普通の腕立てでは、手と足は地面に近い位置にあり、上記の三角形が形成されるでしょう。
内積の算出についてはこちらを参照してください。
ま、面倒くさいならどうぞ!
import numpy as np
def calculate_angle(a, b, c):
a = np.array(a) # First
b = np.array(b) # Mid
c = np.array(c) # End
radians = np.arctan2(c[1] - b[1], c[0] - b[0]) - np.arctan2(
a[1] - b[1], a[0] - b[0]
)
angle = np.abs(radians * 180.0 / np.pi)
if angle > 180.0:
angle = 360 - angle
return angle
④判定ロジック
そして最後に参照してtheta
に基づき、降下down
と上昇up
の2つのモーションに分け、それぞれに対して閾値を設定しカウントします。
では、実際にデモを見てみましょう!
デモ
最後に
はい、(なんとなく)できました!同じロジックを使えばスクワット、懸垂等のエクササイズのカウントもできるでしょう。
今回のソースコードはこちらです!
では、よい エクササイズ を!!
腕立ての限界は己の筋肉ではない
〜エイドリアン〜