動いて書いてダイエット！ MediaPipeで文字書き用フィットネスプログラム作ってみた【PunchWriter ver0.1】

<iframe width="560" height="315" src="https://www.youtube.com/embed/c9BU8LsaFKs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

#はじめに
先日、健康診断に引っ掛かりました。腹回りがヤバい著者です。

在宅ワークが普及しつつある昨今。みなさんは体を動かしていますか？
特に座り仕事だと、ついつい運動不足になりがちです。
肩こりもつらいですよね。

そんなあなたと私の問題を解決するプログラム「**PunchWriter**」を作ってみました！
なんとこれがあれば、**体を動かしながら仕事ができます！！！**

#目次
- [PunchWriter とは](#punchwriter-とは)
- [PunchWriter のつかいかた](#punchwriter-のつかいかた)
 - [インストール](#インストール)
 - [最初の準備](#最初の準備)
 - [操作方法](#操作方法)
- [PunchWriter の中身の話](#punchwriter-の中身の話)
 - [構成](#構成)
 - [罪状](#罪状)
 - [課題点](#課題点)

# PunchWriter とは

「身体で動かすテキストエディタ」です。
動作イメージは、本記事の先頭の動画を見てください。
コードはPythonで書かれていて、GitHubに公開しています（https://github.com/mzkohno/PunchWriter）。
目的はカロリーの消費です。運動不足の解消です。

# PunchWriter のつかいかた
### 動作環境
Linux OS（動作確認環境：Ubuntu 20.04.3 LTS (64bit)）
**＊[後述する理由](#罪状)で、まだ Windows / MacOS ならびにWSLに対応しておりません。**すみません。。。

### インストール
ソースコードはGitHub上に上げています。

https://github.com/mzkohno/PunchWriter

こちらをクローンとかダウンロードとかしてください。

### 最初の準備
1. Python用のMediaPipe環境を構築します。
https://google.github.io/mediapipe/getting_started/python.html
さらに、Tkinter, pyokakaなどが入っていなければ、pip install してください。

2. PunchWriter.py コード中のグローバル変数 `NIHONGO_FONT` を、お使いの環境に合わせて変更してください。
日本語フォントのパスであればOKです。

### 操作方法
##### 起動

```
$ python3 PunchWriter.py
```
##### 記入モード

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vRbqIlPug8QrReK7N-gr1k8ysNwoIu_u9pxohqzBjncg6A472L0c4PbbldYsgiunytNjd0RKFr5es-C/embed?start=false&loop=false&delayms=3000" frameborder="0" width="500" height="400" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>

・右側パンチ（NEXT）　：次の文字へ
・左側パンチ（BACK）　：前の文字へ
・下パンチ　　　　　　：文字のアセットの変更
・上パンチ（片手）　　：現在の選択文字の仮決定
・上パンチ（両手同時）：仮決定した文字のテキストボックスへの出力
・バンザイポーズ　　　：テキストボックスの改行
・ヒザ蹴り　　　　　　：仮決定した文字から最後の一文字削除
・スクワット　　　　　：変換モードに変更（仮決定した文字がある場合）
＊パンチ後に次のアクションに移るためには、両手を一度中央のセットポジションに置く必要があります

##### 変換モード
<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vShnACmie8oL2sunG6UD0VhuMYkq0V_K4uqd8j6GVtHa3HGUeAapXYbhc3xrkL74LVeHJXRaVnfWy_c/embed?start=false&loop=false&delayms=3000" frameborder="0" width="500" height="400" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>
・上パンチ　　　　　　：現在の変換候補のテキストボックスへの出力
・ヒザ蹴り　　　　　　：現在の変換候補の削除
・スクワット　　　　　：次の変換候補へ
すべて出力or削除でき次第、記入モードへ戻る
＊パンチ後に次のアクションに移るためには、両手を一度中央のセットポジションに置く必要があります

##### 終了方法
カメラ画面　　　：Escキーで終了
テキストボックス：CLOSEボタンで終了

# PunchWriter の中身の話
MediaPipeを使っているので、実はこれEdge AI で動いていると言えます。
以下に現バージョンの技術的な内容と課題を記載します。

### 構成
![構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652177/75a3ed52-44ad-737e-1b92-b18d637b7c2d.png)
１つのソースファイルで完結してるので、構成も大変簡単です。
カメラ画像処理用のスレッド (OpenCV)と、テキストボックス表示用のスレッド (Tkinter)に分けています。
MediaPipe ならびにpyokakaは、OpenCV スレッドの中で動かしています。
使っているML model はPose のみです。
各スレッドでやっていることは以下の通りです。

**[OpenCV スレッド]**
・カメラの画像を取得する
・モーキャプによりローマ字文字列を作成する（記入モード）
・変換したい文字列をpyokakaで変換する
・変換したひらがなをGoogle翻訳にHTTP request する。
・結果を受け取り、正しい翻訳結果を選択する（変換モード）
・決定した文字列をグローバル変数TYPE_CHAR に代入する

**[Tkinterスレッド]**
・TYPE_CHAR に値が入っている場合、UIに値を出力。その後、TYPE_CHAR の値をクリアする

### 罪状
お気づきの方もいるかもしれませんが、なんとこれ **UIスレッドが複数あります**。ゆるしてください、石を投げないでください。
このせいで、現行バージョンはLinuxOSでしか動きません。。。
どう考えてもよくない実装ですので、次のバージョンまでには解決します。

### 課題点
上記の罪状により、本コードは以下の課題を抱えています。
・Linux OS 以外で動かない
・終了時に、画面2つを同時に閉じることができない（独立している）
・テキストボックスをCLOSEボタンではなくXで閉じると、正常終了しない

また例えば他にも、以下のようなやりたいことがあります。
・Z軸を活かすことができなかった。将来的に前パンチもコマンドに取り入れたい
・テキストエディタのUIに改善の余地あり
・現在の消費カロリーの表示がしたい

次バージョンでは、これらの課題に取り組む予定です。

# おわりに
「フィットネス × テキストエディタ」 という新たな取り組みに挑戦した本プログラム。
まだまだ課題の多いコードですが、将来的に何かに組み込んで使えるようにしたいですね。

# 参考
本プログラムを開発するにあたり、こちらのコードを大変参考にさせていただきました。
面白いコードをありがとうございます。皆さんもお試しください。

https://github.com/Kazuhito00/Tokyo2020-Pictogram-using-MediaPipe

他、関係するページは以下です。
https://google.github.io/mediapipe/
https://pypi.org/project/pyokaka/