技術とエンタメと、その他・・・

主に、技術ネタ、エンタメ系のネタを書いていく予定です。また、自分が参加したイベントに関する記事も投稿予定。

ピクトグラムになるために Scratch 3.0用の独自拡張機能を使った話の概要(PoseNet2Scratch)

どんな話なのかは、動画で見ていただくのが分かりやすいと思うので、まずはデモ動画をのせてみます。

また、ブラウザ上でご自身で試していただけるバージョンも以下に用意してみました。
以下のお試しができるものは、公式の Scratch にはない独自拡張機能が組み込まれていて、それをオンラインで共有することが可能な「adacraft」というものを使っています(Twitter上で、このような環境で公開できるのではないかと教えていただき、公開してみました)。

【実際に試せるもの】
●adacraft: pictogram_PoseNet2Scratch
 https://adacraft.org/player/?project=4c3801b7
※ お試しされる場合は、両肩より上がカメラにうつる感じで

なお、冒頭のツイートの動画は、PoseNet2Scratch を作られた @jishiha さんが公開されている環境の「Stretch3」を使って実装していました。こちらは、adacraft のようなオンライン共有機能はないものの、機械学習系をはじめとした多数の独自拡張機能が組み込まれており、面白い仕組みが作れて楽しいので試すのをオススメしたい環境です(記事の最後に補足を書きます)。

作った経緯

Twitter で、ピクトグラムを使ったいろいろなネタを見かけて、その中に「自分がピクトグラムになれる・自分でピクトグラムを作れる」というものがありました(この記事の最後の部分に事例をいくつか掲載しています)。

それを見て当初は、「JavaScript版 の MediaPipe」と「p5.js」の組み合わせでやってみたいな、と頭に思い浮かべていました。
JavaScript版 の MediaPipe は、カメラ映像に対してブラウザ上で画像認識をさせるような仕組みを試すのに、ちょこちょこ使っていたものでした。

例えば、顔・体・手を認識できる MediaPipe Holistic というもので、こういうものを作ってみたり...

また、複数の手を認識できる MediaPipe Hands というもので、このようなことをやってみたりもしました。

上記のツイートの動画の事例の両方とも、描画まわりは「p5.js」というライブラリを利用しています。

今回の場合、画像認識に MediaPipe JavaScript版を利用するなら、MediaPipe Pose(今回のものと同じ仕様)か、MediaPipe Holistic(Pose と似ているが、顔と手の部分でとれるキーポイントが格段に多いもの)のどちらかを使えば、というところです。

このようなことを考えていた中、Scratch 3.0用に作られた独自拡張機能で、機械学習を用いた人の姿勢推定を行える「PoseNet2Scratch」もあるというのを思い出し、「単純な実装をする場合は、描画まわりとか座標の処理など Scratch を使うのが楽でシンプルになるかも?」と思いました。
そして思いついてから実装をしてみて、割と短い時間で冒頭の仕組みを試作できました。

どんな実装をしたか?

今回、短時間で作れて自分が動画を撮るのに楽なように、上半身のみを対象として作っています。
今回の姿勢推定に使われている「PoseNet」は以下の記事などにあるように、全身の特定の箇所のキーポイント(全部で16箇所)を取得できます。

●ポーズ推定  |  TensorFlow Lite
 https://www.tensorflow.org/lite/examples/images/pose.png?hl=ja

f:id:youtoy:20210729090358j:plain

その中で、以下の 9箇所分のキーポイントを用いています。

【利用したキーポイント】
 鼻、左耳、右耳、左肩、右肩、
 左ひじ、右ひじ、左手首、右手首

利用したキーポイントと使われ方

認識結果として得られるキーポイントの各座標(x, y)をどのように使ったかという話は、以下のようになっています。

    • 顔のパーツの表示位置の基準を決める座標となっている
  • 左耳、右耳
    • カメラに顔が近づいたり、逆に遠ざかったりしたとき、顔のパーツの大きさを変える仕組みに利用(2点間の距離の大きさによって、顔のパーツの大きさの比率を変化させる)、それと合わせて肩から肘・肘から手までのパーツの大きさを変える仕組みにも流用(※ 実装の簡単化のため)
  • 左肩、右肩
    • 肩から肘にかけてのパーツの表示位置と表示する際の回転角を決めるのに利用している(左ひじ、右ひじの座標とセットで)
  • 左手首、右手首
    • 肘から手にかけてのパーツの表示位置と表示する際の回転角を決めるのに利用している(左ひじ、右ひじの座標とセットで)
  • 左ひじ、右ひじ
    • 上記のとおり「 左肩、右肩」、「左手首、右手首」の座標と組み合わせて利用している

重畳表示する素材の用意

顔や体、腕の部分で表示しているパーツは、Scratch公式の画像エディタで作ったものを利用しています。

f:id:youtoy:20210729211100j:plain

作ったといっても、円を描いたり、長方形を描いたりというシンプルな作図です。肘から手の部分のみ、「大きさの異なる 2つの円と、長方形を描画した後に変形させて台形にした四角 1つ」を組み合わせて形を作っています。

f:id:youtoy:20210729211341p:plain

重畳表示の処理周り(大きさや位置・回転方向の実装まわり)

大きさを変化させる部分は、見た目カテゴリの大きさの比率を変えるブロックを利用しています。 随時、「左耳と右耳の間」と「 左肩と右肩の間」のそれぞれの横方向(x座標方向)の距離を計算し、その計算結果を使って、適当に調整した計数をかけあわせて表示サイズの比率を動的に変更しています。

回転角を決める部分は、「肩と肘」・「肘と手首」のそれぞれの 2点がなす角を公式通りに計算して使っています(Scratch でアークタンジェントを計算するブロックがあるので、公式そのままの実装です)。
「肘と手首」については、どちらが画面上で左側にあるかという、左右方向の位置関係によって算出される角度が変わってくるので、条件分岐と一方の条件のほうは 180度値を足し込む処理を加えていたり、ということをやっています。

説明はざっくりですが、以上のような実装を行って冒頭の内容を実現しました。
以下は、肘から手にかけてのパーツを処理するブロックのプログラムです。

f:id:youtoy:20210729211543j:plain

まとめ

以上が、今回作ったピクトグラムになれる PoseNet2Scratch実装の作品(※ 対応は上半身のみ)の仕組み等の概要でした。

Stretch3 の補足

冒頭の動画に出ていた作品を実装した Stretch3 について、簡単に補足をします。

教育界隈で良く出てくるビジュアルプログラミングなどが行える環境の Scratch 3.0 は、オープンソースで公開されており、GitHub リポジトリからソースを取得して JavaScript による機能追加等を行うことができます。
具体的には、以下の 2つのリポジトリの内容を取得し、組み合わせて使う形です。

●LLK/scratch-gui: Graphical User Interface for creating and running Scratch 3.0 projects.
 https://github.com/LLK/scratch-gui
●LLK/scratch-vm: Virtual Machine used to represent, run, and maintain the state of programs for Scratch 3.0
 https://github.com/LLK/scratch-vm

私自身、公式の Scratch にはないリアルタイム通信機能(IoT界隈で良く登場する MQTT)を、MQTT.js を使って Scratch に追加実装したこともありました。
(以下の動画は、スマホのブラウザ上で行った操作を、MQTT を介して独自実装を加えた Scratch に伝えている様子)

Stretch3 は、自分が作ってみたような公式にはない Scratch 3.0 に対する独自拡張を、1つだけではなく様々含み、また開発環境がオンラインで公開されたものになります。
独自の拡張機能としては、画像分類の学習・推論の両方を扱えたり、Teachable Machine の画像・音声・ポーズプロジェクトを全て扱えたり(Web上にホスティングされた機械学習モデルを呼び出す側を実装できる)、冒頭の動画で使った姿勢推定の PoseNet が使えたり、他にも複数の機械学習系の拡張機能が追加されています(QRコード読み込みなど、機械学習系以外の拡張も複数あったりします)。

ちなみに、機械学習系の拡張機能の話は、過去に以下のような記事を書いてたりもするので、よろしければご覧ください。

ネットで見かけたピクトグラムネタ(プログラムで何かやったというもの)

自分以外にもピクトグラム絡みの作品を、いろいろな環境で作られている方の話を見かけたため、いくつか掲載してみます。

Scratch で ピクトグラムメーカー

MediaPipe(Python版) でピクトグラム

ソースコード
github.com

ブラウザ上で体験できる JavaScript実装もの

ソースコード
github.com

MediaPipe(JavaScript版) でピクトグラム

Scratch でガッツリ実装されている

Azure Kinectピクトグラム

撮影角度を合わせるという観点の作品