cedro3さんのVideoPose3D投稿記事のマイナー変更とCSVの１利用方法

　　　　　　　　　　　　　　　![animation_takusan_nara.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/1e7367ff-414e-4d64-e373-7a334b0f834a.gif)

上のgif動画は、単眼カメラからの姿勢推定SOFTのVideoPose3Dの棒人間動画です。VideoPose3Dは時間相関を考慮した3次元姿勢推定で、ライセンスはCC-by-NCです。
###１．はじめに
本記事は、cedro3さんのGitHubの2020-11-03最終変更したVideoPose3D.ipynb（参考URL1）に次の変更を加え、得られたCSVファイルから、重心位置と重心速度を求め、箱ひげ図を描き、統計的検定を行うものです。
・キーポイント抽出に利用する動画がyoutube動画だったものを、自分のgoogle driveのフォルダ（任意、ここではautotrace)に入れた動画（ファイル名=nara_0403.mp4、33sec)をキャプション可とする。
・出力が3Dテンソルのnpyファイルだったものを扱いやすいcsvファイルも出力可とする。
さらに、csvファイルの１使用方法（重心位置と重心速度の求め方、統計的検定）についても記載します。なお、コードはGoogle ColabのJyupyter notebookの作成を考慮し、変更のないステップも記載します。

（１）Google driveのマウント（変更あり）
　下のコマンドを実行し、Googleアカウントを選択し、「許可」するとコードが表示されるので、Jupyter notebookにコピペする。

```
from google.colab import drive
drive.mount('/content/gdrive')
```
cedro3さん記事では、 Pytorch と Caffe2 を導入 （以下手順で、CUDA, cuDNNも併せて導入される）をしていますが、現在のGoogle colaboでは導入されているので、Caffe2のインストールチェックからコードをコピペします。以後、６まで変更がないのでコピペします。
（２）次に、Caffe2 環境が構築されているかの確認（変更なし）

```
# To check if Caffe2 build was successful
!python -c 'from caffe2.python import core' 2>/dev/null && echo "Success" || echo "Failure"
# To check if Caffe2 GPU build was successful
!python -c 'from caffe2.python import workspace; print(workspace.NumCudaDevices())'
```

（３）COCOデータセット（画像を扱う機械学習のためのデータセットの一つ）の導入（変更なし）

```
!apt-get install python-dev
!pip install cython
!pip install pycocotools
!git clone https://github.com/cocodataset/cocoapi.git
!cd cocoapi/PythonAPI && make install
```

（４） Detectron の導入（変更なし）

```
!rm -r detectron
!git clone https://github.com/facebookresearch/detectron
!pip install -r detectron/requirements.txt
!cd detectron && make
!python detectron/detectron/tests/test_spatial_narrow_as_op.py
```

（５）VideoPose3D の導入 & Video Script を Detectron Tools Folder へコピー（変更なし）

```
!rm -r VideoPose3D
#copy file from VideoPose3d
!git clone https://github.com/facebookresearch/VideoPose3D
!cp VideoPose3D/inference/infer_video.py detectron/tools/infer_video.py
```
（６）Pretrained Human3.6m Coco Model をダウンロード（変更なし）

```
!mkdir VideoPose3D/checkpoint
os.chdir('VideoPose3D/checkpoint')
!wget https://dl.fbaipublicfiles.com/video-pose-3d/pretrained_h36m_detectron_coco.bin
os.chdir('../..')
```
（７）キーポイントを抽出しようとする33秒のmp4動画をffmpegで準備します。33秒の指定は「t 00:00:33」で指定する。nara_0403.mp4は解析する33秒間の動画で、autotraceフォルダに入れてあります。（変更あり）　

```
!rm -r videos
!mkdir videos   
import os
!ffmpeg -i "/content/gdrive/My Drive/autotrace/nara_0403.mp4" -ss 00:00:00 -t 00:00:33 videos/video.mp4
```
（８）Detectron を用いて2D座標を計算（変更なし）

```
!rm -r output
!mkdir output
!python detectron/tools/infer_video.py \
    --cfg detectron/configs/12_2017_baselines/e2e_keypoint_rcnn_R-101-FPN_s1x.yaml \
    --output-dir output \
    --image-ext mp4 \
    --wts https://dl.fbaipublicfiles.com/detectron/37698009/12_2017_baselines/e2e_keypoint_rcnn_R-101-FPN_s1x.yaml.08_45_57.YkrJgP6O/output/train/keypoints_coco_2014_train:keypoints_coco_2014_valminusminival/generalized_rcnn/model_final.pkl \
   videos
```

（９）VideoPose3Dの入力に合わせたDetectronの出力を用意（変更なし）

```
!rm -r ./VideoPose3D/data/detectronoutput
!mkdir ./VideoPose3D/data/detectronoutput
!cp output/video.mp4.npz VideoPose3D/data/detectronoutput/video.mp4.npz
os.chdir('VideoPose3D/data') # This script must be launched from the "data" directory
!python prepare_data_2d_custom.py -i detectronoutput -o myvideos
os.chdir('../../')
```

（１０）VideoPose3Dを使用して3Dジョイントを計算（変更なし）

```
# 以下2.2で実施しないと失敗する
!pip install matplotlib==2.2
!rm -r VideoPose3D/video.mp4
!cp ./videos/video.mp4 VideoPose3D/video.mp4
os.chdir('VideoPose3D')
!python run.py -d custom -k myvideos -arc 3,3,3,3,3 -c checkpoint --evaluate pretrained_h36m_detectron_coco.bin --render --viz-subject video.mp4 --viz-action custom --viz-camera 0 --viz-video video.mp4 --viz-output output.mp4 --viz-export outputfile --viz-size 6
```
（１１）結果の表示（ジョイントのエクスポート）（変更あり）
npyファイルはバイナリーの3dテンソルなので、2次元のcsvファイルに直してダウンロードします。5番目のコマンドのreshape(990,51)は実行例の33秒のフレーム数990を入力しています。

```
import numpy as np
data  = np.load('outputfile.npy')
lst = data
import numpy as np #ins nara
outputvideo=data.reshape(990,51).copy() #ins nara del0308
np.savetxt('outvideo.csv',outputvideo,delimiter=',',fmt='%.10f') 
for item in lst:
      prit(item)
```
（１２）結果の表示（ジョイントビデオ）（変更なし）

```
#display video
def show_local_mp4_video(file_name, width=640, height=480):
  import io
  import base64
  from IPython.display import HTML
  video_encoded = base64.b64encode(io.open(file_name, 'rb').read())
  return HTML(data='''<video width="{0}" height="{1}" alt="test" controls>
                        <source src="data:video/mp4;base64,{2}" type="video/mp4" />
                      </video>'''.format(width, height, video_encoded.decode('ascii')))

show_local_mp4_video('output.mp4', width=960, height=720)
```
（１３）ジョイントビデオのダウンロード（変更あり）
4番目のコマンドが追加されています。3つのファイルが「ダウンロード」フォルダにダウンロードされます。

```
from google.colab import files
files.download('output.mp4')
files.download('outputfile.npy')
files.download('outvideo.csv')
```
###２．CSVファイルの使い方
####２．１　重心と重心速度
　CSVファイルは、33.33msec毎の1フレームごとキーポイント17点の腰を原点とするワールド座標系の3次元座標なので座標は全部で51個になります。カメラに向かって踊っている人の左手方向がX軸の正、下が、Y軸の正、後ろ方向がZ軸の正の右手座標系です。以下はCSVファイルに付加すれば使い勝手が向上するヘッダーの情報です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/44d794e9-15af-79b4-e2b3-fdf1f6a4bccb.png)
２人の棒人間動画のCSVファイルから統計解析SOFT のR言語（実際に使用したのはRコマンダー）を用いて重心位置と重心速度を求め、箱ひげ図描き統計的検定をしました。重心位置は参考URL２より求めました。次の表は上のヘッダ情報のキーポイント名称と重心を求めるための各部位の重量の情報です。従って、重心の座標はキーポイント座標の重み付け平均になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/660498a9-87c1-1e64-5dd5-3dcb43a91d04.png)

以下はRコマンダーの重心（grv_x､grv_y､grv_z)を求めるコードです。csvファイルをクリップボードに張り付けてDatasetにインポートしています。最後に重心をDatasetにcbindしています。

```
l_jyouwan_x=(l_shoulder_x+l_elbow_x)/2
l_jyouwan_y=(l_shoulder_y+l_elbow_y)/2
l_jyouwan_z=(l_shoulder_z+l_elbow_z)/2
r_jyouwan_x=(r_shoulder_x+r_elbow_x)/2
r_jyouwan_y=(r_shoulder_y+r_elbow_y)/2
r_jyouwan_z=(r_shoulder_z+r_elbow_z)/2

l_zenwan_x=(l_elbow_x+l_wrist_x)/2
l_zenwan_y=(l_elbow_y+l_wrist_y)/2
l_zenwan_z=(l_elbow_z+l_wrist_z)/2
r_zenwan_x=(r_elbow_y+r_wrist_y)/2
r_zenwan_y=(r_elbow_y+r_wrist_y)/2
r_zenwan_z=(r_elbow_z+r_wrist_z)/2

l_momo_x=(l_hip_x+l_knee_x)/2
l_momo_y=(l_hip_y+l_knee_y)/2
l_momo_z=(l_hip_z+l_knee_z)/2
r_momo_x=(r_hip_x+r_knee_x)/2
r_momo_y=(r_hip_y+r_knee_y)/2
r_momo_z=(r_hip_z+r_knee_z)/2

l_leg_x=(l_knee_x+l_ankle_x)/2
l_leg_y=(l_knee_y+l_ankle_y)/2
l_leg_z=(l_knee_z+l_ankle_z)/2
r_leg_x=(r_knee_x+r_ankle_x)/2
r_leg_y=(r_knee_y+r_ankle_y)/2
r_leg_z=(r_knee_z+r_ankle_z)/2


cntr_x=3*head_x+2*spine2_x+14*spine1_x
left_x=l_shoulder_x+2*l_jyouwan_x+2*l_zenwan_x+7*l_hip_x+6*l_momo_x+3*l_leg_x
right_x=r_shoulder_x+2*r_jyouwan_x+2*r_zenwan_x+7*r_hip_x+6*r_momo_x+3*r_leg_x
grv_x=(cntr_x+right_x+left_x)/61

cntr_y=3*head_y+2*spine2_y+14*spine1_y
left_y=l_shoulder_y+2*l_jyouwan_y+2*l_zenwan_y+7*l_hip_y+6*l_momo_y+3*l_leg_y
right_y=r_shoulder_y+2*r_jyouwan_y+2*r_zenwan_y+7*r_hip_y+6*r_momo_y+3*r_leg_y
grv_y=(cntr_y+right_y+left_y)/61

cntr_z=3*head_z+2*spine2_z+14*spine1_z
left_z=l_shoulder_z+2*l_jyouwan_z+2*l_zenwan_z+7*l_hip_z+6*l_momo_z+3*l_leg_z
right_z=r_shoulder_z+2*r_jyouwan_z+2*r_zenwan_z+7*r_hip_z+6*r_momo_z+3*r_leg_z
grv_z=(cntr_z+right_z+left_z)/61
Dataset<-cbind(Dataset,grv_x)
Dataset<-cbind(Dataset,grv_y)
Dataset<-cbind(Dataset,grv_z)
```
重心速度は、Datasetをダウンロードし、エクセルで計算し、再度Rにアップしました。
####２．２　箱ひげ図と統計的検定
以下の6つの図は、Rで書いた箱ひげ図で、最初の3つはそれぞれｘ、ｙ、ｚの重心位置、次の3つはｘ、ｙ、ｚの重心速度です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/59d481c9-0893-c584-e68d-06fbf422d6c7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/6ff7175f-37fa-8d56-c7f0-8a6546ea3e88.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/b27fcf93-7522-7956-0319-0fb37a7d1865.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/250ffe82-9839-c92c-0187-638b293b81a5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/7c23d2d5-46ed-9bbc-4b89-16c428d3090b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/e05d17cf-df42-6287-2155-7b9c1434e5dd.png)
　以下は、統計的検定結果です。重心位置はクラスカルウォリスのχ２乗で検定し、いずれもお中央値は5%で有意差ありとなった。重心速度は、分散比のF検定を行い、y方向の重心速度を除いて危険率5%で有意差ありとなった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/774977/db202ef2-f905-34d8-4946-84ce7b99f076.png)
###３．おわりに
皆さんも、GoogleColaboでCSVファイルを出力して、Rで遊んでください。

謝辞
TKさんには、動画の提供とディスカッションをしていただきました。ここに謝意を表します。
参考URL
１．https://github.com/cedro3/others/blob/master/VideoPose3D.ipynb
２．https://www.ieice.org/publications/conference-FIT-DVDs/FIT2009/pdf/J/J_014.pdf