こちらはProcessing Advent Calendar 2021 9日目の記事です(間違えて12/8に予約投稿してしまいました泣)。
TensorFlowは機械学習界隈でよく使われるライブラリの1つですが、それをJavaScriptでも使用できるようにしたのがTensorFlow.jsです。TensorFlow.js内でも機械学習モデルの訓練ができるのですが、どちらかというと別環境にて訓練した学習済みモデルをWebブラウザ上で動かすために使われているイメージがあります。
そんなTensorFlow.jsとp5.jsを組み合わせることでWeb上でのクリエイティブコーディング的な表現を広げることができます。過去にこれらを組み合わせたサンプルコード&デモをいくつか作成してきたのですが、ブログにはあんまり載せていなかったのでこれを機会にまとめて紹介しようと思います(そのため古いコードもあります、多分動くので許してください)。
※TensorFlow.jsをより使いやすくしたものとしてml5.jsがあります。ただ後ほど紹介するPoseNetをはじめ最新verのモデルに対応していなかったりするので私はTensorFlow.jsをそのまま使うことが多いです(数年前に確認しただけなので最近は違うかも)。
PoseNet Line Effect
1つ目はポーズ推定をするためのPoseNetを使用したサンプルです。画像内の人物の関節位置(顔や手足など17部位)を取得できます。Webカメラの映像と組み合わせると色々夢が広がりそうです。インタラクティブなゲーム系と相性が良さそう。
上記サンプルでは顔パーツの座標を使ってカスタムシェイプを描画しているだけなのでぜひもっと良い感じに改造してみてください。過去の作例も下にいくつか載せておきます。
※なんか知らないうちにPoseNetはPose Detectionという骨格推定系のモデルをまとめたパッケージに内包されました。
I AM INSTAGRAMER.#p5js #bboy#posenet#tensorflowjs#creativecoding pic.twitter.com/s8XTUCq83A
— 沿岸の街 (@eatora22) 2019年12月31日
Bboy FixedMan by #PoseNet
— 沿岸の街 (@eatora22) 2019年12月10日
特定の部位に着目したパフォーマンスの事後チェックにも使えそう?#p5js#eijey#posenet#designium#tensorflowjs#breakdance#creativecoding pic.twitter.com/vSomznPmuP
#PoseNet 使ってドラム演奏してみた(ドラムはできない)。SE素材は魔王魂さん。#tensorflowjs #p5js #creativecoding #デザイニウム pic.twitter.com/4iu5QEXl22
— 沿岸の街 (@eatora22) 2019年11月21日
BodyPix Noise Effect
2つ目は人物のセグメンテーションをするためのBodyPixを使用したサンプルです。画像内の人物の領域を分割してくれます(グリーンバックで撮影した人のマスクを抜く感じに近い)。セグメンテーションのモデルはよく見かけますが、更にBodyPixでは手足や胴体などの部位に合わせたセグメンテーションもできます。
上記サンプルではマイクで取得した音量に合わせて、セグメンテーションした領域をパーリンノイズでぐにゃぐにゃさせています(もっとスマートなやり方もありそう)。過去の作例も下に載せておきます(おなじくTensorFlow.jsを使用したface-api.jsによる表情の推定と組み合わせたやつもあります)。
BodyPix (ResNet) × Perlin Noise test.
— 沿岸の街 (@eatora22) 2020年2月6日
良い感じになってきました。フットワーク中も意外とマスク頑張っている。#creativecoding #tensorflow #p5js #breakdance pic.twitter.com/SyRnpyFS6j
Multi Camera & Prediction Test.
— 沿岸の街 (@eatora22) 2020年1月30日
感情が波紋のように広がる感じを意識しました。#EmotionBehindColor#creativecoding #tensorflowjs#designium#faceapijs#bodypix#p5js#wip pic.twitter.com/k0AIZvqbYk
3D Pose Estimation Sample by BlazePose
3つ目はPoseNetのような2次元の座標に加え3次元座標の骨格推定もできるBlazePoseを使用したサンプルです。keypointsだと2次元座標、keypoints3Dだと3次元座標を取得できるっぽいです。z座標については腰の中心の深さを原点として他の部位(ランドマーク)の深さ(奥行き)を決定します。また、BlazePoseはTensorFlow.jsとMediaPipeの2つのランタイム経由で使えるのですがサンプルでは前者を使用しました(後者はp5js環境へのインポートがうまくいきませんでした、誰か教えてください)。
上記サンプルでは各部位の2次元座標に合わせて部位名の表示、左上に3次元座標に合わせたboxを表示という感じになっています(見辛い)。visual-effectブランチに変なビジュアライズをしようとした形跡があります。他の用途としては3Dモデルのアバターを操作したりするのに使えるかもしれません。
I created 3D Pose Estimation Sample by BlazePose & p5.js.
— 沿岸の街 (@eatora22) 2021年10月22日
You can try with web camera:https://t.co/LbWh0SE1ui#BlazePose #TensorFlowJS #p5js #MadeWithTFJS #CreativeCoding pic.twitter.com/bu0eI80VnA
おまけ
TensorFlow.jsで色々作っている人たちのコミュニティでプレゼンをしたことがあるのでついでに載せておきます(拙い英語お許しください)。クリエイティブコーディング良いよね的な話や上記したサンプル含む作例の紹介をしたりしました。作例たちは以下の動画にもまとめてあります(GoogleMagentaのモデルで音楽生成的なことやNode.jsでサーバー側での推論実行なども)。あとMoveNetを使用した書道もどきも。
もっとついでな話をすると、TensorFlow.js用にモデルの変換を行うにはtensorflowjs_converterを使用します(Python環境で学習させたモデルを使ったりする)。2年前ぐらいに試そうとしたんですが全然上手くいかず投げ出した記憶があります。TensorFlow.jsに限らずモデルの変換あるあるなんですが、ニューラルネットワーク内で使っているこの層はjs側でまだ対応してないとかよく言われます。シンプルなモデルならうまくいくのかな。Python界隈ではすごいモデルが日々生み出されているので強い方はぜひ変換にトライして面白い表現を生み出してください(そしてその知見を共有してください泣)。
さいごに
以上、TensorFlow.jsとp5.jsを組み合わせたサンプルをご紹介しました。環境依存に悩まずWeb上で色々できるようになって素晴らしいですね(先駆者たちに感謝)。全然関係ないですが、本ブログやnoteではお散歩の記録や変な考察などよく分からない記事をたくさん書いているのでよかったら読んでみてください。最後までお付き合いいただきありがとうございました。