Google Colaboratory上でOpenPoseを使ってYouTube動画を解析する方法

# この記事の目的
大学の研究のためにOpenPoseをGoogle Colaboratoryで使いたかったのですが...
以下の問題があり、スムーズにいきませんでした。
- OpenPoseを動かせるNoteBookを見つけて実行するも、エラーが出て動かせなかった

そこで、自己解決した方法を共有します。
同じように悩んでいる人にこの記事が届きますように！

# この記事を読んでほしい人
- Google ColaboratoryでOpenPoseを使いたい人
- OpenPoseでYouTube動画を解析したい人

# はじめに
Google Colaboratoryの始め方についてはこちらのページなどを参考にしてください。

https://qiita.com/DeepTama/items/02e299b2c616a603fb4a

この記事ではGoogle Colaboratoryが使える状態になっていることを前提としています。

# やりたいこと
Google Colaboratory上で、OpenPoseを用いてYouTube動画を解析したい

# 参考元のコード
まず「OpenPose Google Colab」と検索して出てきた様々なNoteBookを実行するも、
どうやら大本のサーバーがダウンしている様で、エラーが出てしまい実行できませんでした。

そんな中、以下のNoteBookは実行できたので、これを基にコードを作成しました。

https://colab.research.google.com/drive/1m0DU-vjjTNWrXMEMqJptQHyp3SXUGbmf?usp=sharing


# 今回作成したコード
https://github.com/qwert-top/NMM-recognition-with-OpenPose.git

この記事では、コードの主要な部分の説明のみを行います。
コード自体は上記のGitHubのページからopenpose.ipynbを入手してください。
openpose.ipynbを開いて左上にある"Open in Colab"をクリックすると、
ご自身のGoogle Colaboratory上にNoteBookをコピーすることができます。

# 利用方法 & コードの内容
### 1. OpenPoseのModelをダウンロードする
まず外部からModelを直接ダウンロードします。

https://www.kaggle.com/datasets/changethetuneman/openpose-model

kaggleにアップロードされているこのデータセットをダウンロードして、
自分のGoogle Driveの適当な場所に置きます。

どうやら、以下のGoogle Driveのリンクからもダウンロードできるようです。
（自分は試していないです）

https://drive.google.com/file/d/1QCSxJZpnWvM00hx49CJ2zky7PWGzpcEh


### 2. Modelの解凍 
Modelをダウンロードできたら、**openpose.ipynb**のNoteBook上に移動させてください。
ここから**openpose.ipynb**の実行に入ります。


まず以下のコードでModelの解凍が行われます。
青文字の部分を、自分がModelをダウンロードしたフォルダのアドレスに各自書き換えてください。
```python:openpose.ipynb
!cp "Modelをダウンロードしたフォルダのアドレス" /content
# Workaround for server connection problem ("file DOWNLOAD HASH mismatch"),see, e.g.,
# https://github.com/CMU-Perceptual-Computing-Lab/openpose/issues/1602#issuecomment-641653411
!apt-get install unzip

# !wget -O models.zip  --no-check-certificate -r 'https://drive.google.com/uc?id=1QCSxJZpnWvM00hx49CJ2zky7PWGzpcEh&export=download'
!unzip -o models.zip -d openpose
```
### 3. OpenPoseをインストールする
```python:openpose.ipynb
git_repo_url = 'https://github.com/CMU-Perceptual-Computing-Lab/openpose.git'
project_name = splitext(basename(git_repo_url))[0]
!rm -rf openpose
# clone openpose
!git clone -q --depth 1 $git_repo_url
# --recursive necessary in the line below, as otherwise you can (sometimes) get "lpthreads" errors in cmake ("undefined reference to `pthread_create'" etc). See, for example, https://github.com/facebookarchive/caffe2/issues/1234
!sed -i 's/execute_process(COMMAND git checkout --recursive master WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\/3rdparty\/caffe)/execute_process(COMMAND git checkout f019d0dfe86f49d1140961f8c7dec22130c83154 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}\/3rdparty\/caffe)/g' openpose/CMakeLists.txt
!cd openpose && git submodule update --init --recursive --remote
```
本来はこれでうまくいくはずなのですが、
"file DOWNLOAD HASH mismatch"というエラーコードがでてしまいます。
そのため、以下のコードで問題のファイルを削除し、代わりに直接ダウンロードしたModelから使うようにします。
```python:openpose.ipynb
# use 'sed' to comment out the line in the OpenPose repo that downloads the model from the failed link
! sed -i 's/executeShInItsFolder "getModels.sh"/# executeShInItsFolder "getModels.sh"/g' ./openpose/scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.1.sh
! sed -i 's/executeShInItsFolder "getModels.sh"/# executeShInItsFolder "getModels.sh"/g' ./openpose/scripts/ubuntu/install_openpose_JetsonTX2_JetPack3.3.sh
! sed -i 's/download_model("BODY_25"/# download_model("BODY_25"/g' ./openpose/CMakeLists.txt
! sed -i 's/78287B57CF85FA89C03F1393D368E5B7/# 78287B57CF85FA89C03F1393D368E5B7/g' ./openpose/CMakeLists.txt
! sed -i 's/download_model("body (COCO)"/# download_model("body (COCO)"/g' ./openpose/CMakeLists.txt
! sed -i 's/5156d31f670511fce9b4e28b403f2939/# 5156d31f670511fce9b4e28b403f2939/g' ./openpose/CMakeLists.txt
! sed -i 's/download_model("body (MPI)"/# download_model("body (MPI)"/g' ./openpose/CMakeLists.txt
! sed -i 's/2ca0990c7562bd7ae03f3f54afa96e00/# 2ca0990c7562bd7ae03f3f54afa96e00/g' ./openpose/CMakeLists.txt
! sed -i 's/download_model("face"/# download_model("face"/g' ./openpose/CMakeLists.txt
! sed -i 's/e747180d728fa4e4418c465828384333/# e747180d728fa4e4418c465828384333/g' ./openpose/CMakeLists.txt
! sed -i 's/download_model("hand"/# download_model("hand"/g' ./openpose/CMakeLists.txt
! sed -i 's/a82cfc3fea7c62f159e11bd3674c1531/# a82cfc3fea7c62f159e11bd3674c1531/g' ./openpose/CMakeLists.txt
```

### 4. 解析したいYouTubeの動画を指定する
解析したいYouTube動画のURLの"watch?v="の後の文字列をコピーして、
YOUTUBE_IDに代入します。

```python:openpose.ipynb
from IPython.display import YouTubeVideo
YOUTUBE_ID = 'ここにURL '
YouTubeVideo(YOUTUBE_ID)
```
また、動画を切り取りたい場合は、以下で指定します。
```python:openpose.ipynb
# cut the video
!ffmpeg -y -loglevel info -i youtube.mp4 -ss 何秒から切り取るか -t 何秒間切り取るか video.mp4
```
 例えば動画の10秒目から7秒間切り取りたい場合は、-ss 10 -t 7とします。
 
### 5. OpenPoseで指定した動画を解析する
OepnPoseは通常右肩、左肩、右手首、左手首などの人の関節18個の特徴点を検出します。
今回のコードのように"--face" とすることで、さらに顔について眉毛、目、鼻、口などの70個の特徴点を検出できます。
また、"--hand"とすると、手について手首付け根、各指の関節など42個の特徴点を求めることができます。
```python:openpose.ipynb
# detect poses on the these 5 seconds
!cd $OPENPOSE_PATH && rm ../openpose.avi
!cd $OPENPOSE_PATH && chmod -R 755 './build/'
!cd $OPENPOSE_PATH && ./build/examples/openpose/openpose.bin --video ../video.mp4 --write_json ./output/ --display 0  --write_video ../openpose.avi --face
# convert the result into MP4
!ffmpeg -y -loglevel info -i openpose.avi output.mp4
```

### 6. 解析した動画を確認する
以下のコードを実行することで、
元の動画に解析結果を重ねた動画を確認できます。
```python:openpose.ipynb
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)
```


### 7. 解析結果のkeypointsを圧縮し、ダウンロードする

```python:openpose.ipynb
# ダウンロードしたいフォルダを zip 圧縮する
!zip -r /content/keypoints.zip /content/openpose/output
# 圧縮した zip ファイルをダウンロードする
from google.colab import files
files.download("/content/keypoints.zip")
```

### 8. 保存したkeypoints.zipを解凍する
自動的に保存されたKeypointsのファイルはzipファイルになっているので、解凍します。
解凍方法はいろいろありますが、Google Driveに保存する場合はZIP Extractorで十分です。

# 実行により得られるものは？
OpenPoseの実行により得られるものは**2つ**あります。
1. 解析結果の動画（**6. 解析した動画を確認する**）
2. keypointsのファイル（**7. 解析結果のkeypointsを圧縮し、ダウンロードする**）

ダウンロードしたkeypoints.zipの中には、解析した動画のフレームの数だけファイルがあります。
1秒間に30フレームの頻度で各点の座標値が検出され、それぞれのファイルに記されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680442/6447169b-63cd-6f7b-eec0-0a8818d8cef4.png)


# おわりに
今回は、Google Colaboratory上でOpenPoseを使ってYouTube動画を解析する方法を紹介しました。
研究を始めるにあたって、Google Colaboratory上でOpenPoseを実行できるNoteBookを探すのにかなり苦労したので、同じように苦労している人を手助けすることができれば幸いです。

得られたkeypointsのファイルを使ってさらに詳しく解析する方法を、今後記事にしたいと考えています！