元記事 この記事は Dan Oved による TensorFlow - Medium の記事 "Introducing BodyPix: Real-time Person Segmentation in the Browser with TensorFlow.js" を元に翻訳・加筆したものです。詳しくは元記事をご覧ください。

投稿者: Dan Oved(ニューヨーク大学 ITP 大学院生および研究員)、 Tyler Zhu(Google Research エンジニア)、編集: Irene Alvarado(Google Creative Lab クリエイティブ テクノロジスト)


ブラウザと TensorFlow.js を使って人や体の部位が映っている領域を分割(セグメンテーション)できるオープンソース機械学習モデル、BodyPix のリリースについてお知らせします。デフォルトの設定を使用する場合、2018 年モデルの 15 インチ MacBook Pro では 25 fps 、iPhone X では 21 fps で人や部位のセグメンテーションの予測とレンダリングができます。






人のセグメンテーションとは、具体的にどういうことでしょうか。コンピュータ ビジョンで画像のセグメンテーションと言えば、画像内のピクセルを意味のある領域ごとにグループ化する技術のことで、通常は物体や境界を見つけることを指します。BodyPix のモデルは、人や 24 種類の部位(左手、右下肢正面、胴体後部など)に対してこの処理を行うようにトレーニングされています。つまり、BodyPix は画像内のピクセルを、1) 人と表すピクセルと 2) 背景を表すピクセルの 2 種類に分類できます。さらに、人を表すピクセルを 24 の部位のいずれかに分類することもできます。


こちらのライブデモを試していただくとわかりやすいかもしれません。


人のセグメンテーションを使うと、何ができるのでしょうか。このテクノロジーは、拡張現実(AR)から写真の編集、画像や動画に対するアート効果まで、さまざまなことに応用できるツールです。何をするかは、皆さん次第です。昨年、PoseNet(人体の姿勢の推測(Kinect が行っていること)を簡単なウェブカメラとブラウザで行えるようにした初めてのモデル)をリリースしたとき、皆さんはこのテクノロジーのさまざま種類ユースケースを考えてくれました。BodyPix でも、同じようなクリエイティブな実験が行われることを期待しています。
なぜこれをブラウザで行えるようにするのでしょうか。PoseNet と同じように、リアルタイムの人セグメンテーションも、以前は、専用のハードウェアや、システム要件が厳しくインストールが困難なソフトウェアを使わなければできないことでした。しかし、BodyPix と PoseNet なら、わずか数行のコードだけ、さらにインストール不要で使えます。このモデルを使うために、専用のレンズは必要ありません。どんな基本的なウェブカメラやモバイルカメラでも動作します。さらに、ユーザーは URL を開くだけでアプリケーションにアクセスできます。計算はすべて端末上で行われるため、データのプライバシーは守られます。以上の理由から、BodyPix はアーティストやクリエイティブなプログラマープログラミング初心者が簡単に利用できるツールと言えます。
BodyPix について詳しく説明する前に、モデルや人体の姿勢の推測 [1, 2] に関する作業を行ってくれた Google Research の Tyler Zhu 氏、TensorFlow.js ライブラリに関わっている Google Brain チームのエンジニアである Nikhil Thorat 氏と Daniel Smilkov 氏、そして、このプロジェクトにおける Dan Oved の作業に資金を提供してくれた Daniel Shiffman 氏と Google Faculty Research Award に厚く御礼申し上げます。

BodyPix を使ってみる

このモデルを使うにあたっての技術的詳細について説明しましょう。BodyPix を使うと、画像を人の一部であるピクセルとそうでないピクセルに分割できます。人の一部であるピクセルは、さらに 24 の部位のいずれかに分類できます。重要な点は、このモデルは 1 人に対して動作するということです。そのため、入力データに複数の人が含まれないようにしてください。

パート 1: TensorFlow.js および BodyPix ライブラリのインポート

BodyPix プロジェクトの基本的な設定方法について説明します。
ライブラリは、npm install @tensorflow-models/body-pix でインストールできます。その後、es6 モジュールを使ってインポートします。





または、何もインストールせずに、ページ内でバンドルします。



パート 2a: 人のセグメンテーション




画像に人のセグメンテーション アルゴリズムを適用した例。イメージのクレジット: “Microsoft Coco:Common Objects in Context Dataset”、 http://cocodataset.org

基本的には、人のセグメンテーションを行うと、画像が人の一部であるピクセルと、そうでないピクセルに分割されます。内部的には、モデルに画像を渡すと、0 から 1 の間の浮動小数点数値で表される 2 次元画像に変換されます。それぞれのピクセルは、そこに人が映っている確率を示しています。「セグメンテーションしきい値」と呼ばれる値は、人の一部であると見なすピクセルのスコアの最小値を表します。このセグメンテーションしきい値を使うと、0 から 1 の浮動小数点数値が 0 か 1 に 2 値化されます(しきい値が 0.5 の場合、0.5 より大きい値は 1 に、0.5 より小さい値は 0 に変換されます)。
画像や動画に対して人のセグメンテーションを行うには、API メソッド estimatePersonSegmentation を呼び出します。次の短いコードブロックは、この使い方を示しています。




人のセグメンテーションからの出力例は、次のようになります。




このメソッドや引数についての詳しい説明は、github の readme に掲載されています。

人のセグメンテーションからの出力結果を描画する

BodyPix がブラウザで動作するもう 1 つのメリットは、Canvas Compositing などのウェブ API を利用できることです。これと BodyPix からの出力結果を使って、画像の一部をマスクしたり置換したりしてみましょう。すぐに使い始めることができるように、この機能をラップしたユーティリティ関数を用意しています。
toMaskImageData は、人のセグメンテーションの推定を表す出力結果を受け取り、引数 maskBackground に応じて、人または背景を不透明にした透過画像を生成します。これをマスクとして、元画像の上に描画することができます。これを行うには、drawMask メソッドを使います。





drawMask は、キャンバスに画像を描画し、その上から指定された不透明度のマスクで ImageData を描画します。



上の最初の画像に対して estimatePersonSegmentation を実行し、その出力を toMaskImageData に渡すと、 ImageData が生成される。その際に、maskBackground を true にした場合(デフォルト)は上の 2 番目の画像のように、または maskBackground を false に設定した場合は 3 番目の画像のようになる。
このマスクは、 drawMask を使って画像上に描画できる。

パート 2b: 部位のセグメンテーション



画像に部位のセグメンテーション アルゴリズムを適用した例。画像のクレジット: “Microsoft Coco:Common Objects in Context Dataset”、 https://cocodataset.org.hb

BodyPix は、単純に人か人でないかを分類するだけでなく、画像を 24 の部位のいずれかを表すピクセルに分割することもできます。画像をモデルに渡すと、0 から 23 の間の整数値で表される 2 次元画像に変換されます。それぞれのピクセルは、そのピクセルが 24 の部位のどれに属するかを表しています。体の外側にあたるピクセルの値は、-1 となります。
画像や動画に対して部位のセグメンテーションを行うには、API メソッド estimatePartSegmentation を呼び出します。次の短いコードブロックは、この使い方を示しています。





部位のセグメンテーションからの出力例は、次のようになります。




このメソッドや引数についての詳しい説明は、github の readme に掲載されています。

部位のセグメンテーションからの出力結果を描画する

estimatePartSegmentation からの出力と、部位 ID をインデックスとした色の配列を toColoredPartImageData に渡すと、各ピクセルが部位に対応する色になったイメージが生成されます。これをマスクとして、キャンバスの元の画像の上に描画できます。これを行うには、drawMask メソッドを使います。






上の最初の画像に対して estimatePersonSegmentation を実行し、その出力とカラースケールを toColoredPartImageData に渡すと、上の 2 番目のような ImageData が生成される。キャンバスに、元の画像の上から不透明度 0.7 で色つきの部位の画像を描画することもできる。これを行うには、 drawMask を使用する。結果は、上の 3 番目の画像のようになる。

これらのメソッドの詳しい説明や使用法については、github の readme をご覧ください。

BodyPix の高速化と精度向上

パフォーマンスと精度に最も大きく影響するのは、モデルのサイズと出力ストライドです。この 2 つの値を設定することで、精度を落として高速化したり、速度を落として精度を上げたりすることができます。
  • モデルのサイズは、モデルを読み込む際に mobileNetMultiplier 引数で設定します。設定できる値は、0.25、0.50、0.75、1.00 のいずれかです。この値は、MobileNet のアーキテクチャとチェックポイントに対応します。値が大きいほど、各層のサイズが大きくなり、速度と引き替えにモデルの精度が向上します。小さな値を設定すると、精度と引き替えに速度が向上します。
  • 出力ストライドは、セグメンテーションを実行する際に設定する引数で設定できる値は 8、16、32 のいずれかです。大まかに言えば、これは姿勢の推定の精度と速度に影響します。出力ストライドの値を小さくすると、精度が上がりますが、速度は遅くなります。値を 大きく すると、予測時間は短くなりますが、精度は 低く なります。




さらに、画像のサイズもパフォーマンスに影響します。セグメンテーションの推測を行った後、結果は元の画像サイズにスケーリングされるので、元画像が大きいほど、結果のスケーリングや描画を行う際の計算量が多くなります。高速に処理するには、画像を縮小してから API に渡してください。
BodyPix を触ってみたい方は、ぜひここでお試しください。次のセクションでは、モデルの作成方法を知りたい方のために、技術的な詳細についてさらに説明します。

BodyPix ができるまで

BodyPix は、畳み込みニューラル ネットワーク アルゴリズムを使っており、ResNet モデルと MobileNet モデルの両方をトレーニングしました。ResNet ベースのモデルの方が精度は高いのですが、このブログ投稿では MobileNet ベースのモデルを取り上げます。MobileNet モデルは、モバイル端末や一般消費者向けのコンピュータで効率的に実行でき、オープンソース化されています。MobileNet モデルでは、高密度 2D セグメンテーション マップを予測するため、従来型の分類モデルの最終プーリング層および完全結合層が 1x1 の畳み込み層に置き換わっています。次の図は、入力イメージの処理に MobileNet を使う場合の流れを示しています。


入力画像から出力層まで、MobileNet の層ごとの活性化を示した例(説明の都合上、特徴マップのダウンサイジングは省略)

人のセグメンテーション

BodyPix の中核になっているのは、人の体のセグメンテーションを行うアルゴリズムです。つまり、入力画像の各ピクセルについて二分決定を行い、そのピクセルが人であるかそうでないかを推測します。その仕組みについて見てみましょう。



人の領域を分割するタスクを示した画像。これは、ピクセルごとの二分決定タスクと考えることができる。1 はピクセルが人の領域に属することを、0 はピクセルが人の領域に属さないことを示す(説明の都合上、セグメンテーションの解像度を落としている)。

画像が MobileNet ネットワークを通過すると、シグモイド活性化関数が出力を 0 と 1 の間の値に変換します。この値は、ピクセルが人に属するかそうでないかを示す確率と解釈できます。セグメンテーションしきい値(例: 0.5)は、人の一部と見なすピクセルのスコア最小値を決定します。これにより、出力結果がバイナリ セグメンテーションに変換されます。



画像に人のセグメンテーション アルゴリズムを適用した場合のデータ表現の例。左から右に: 入力画像、シグモイド後のネットワークのセグメンテーション予測、しきい値を適用した後のバイナリ セグメンテーション。図: Ashley Jane Lewis。 画像のクレジット: “Microsoft Coco:Common Objects in Context Dataset”、 https://cocodataset.org

部位のセグメンテーション

部位のセグメンテーションの予測にも、同じ MobileNet 表現を使っています。しかし、ここでは、 追加の 24 チャンネルの出力テンソル P24 は部位の数)について予測を行うことで、前述の処理を繰り返しています。各チャンネルには、ある部位が存在するかどうかの確率が符号化されています。



部位の領域を分割するタスクを示す例。これは、ピクセルごとに 複数のチャンネル に対して行う二分決定タスクと考えることができる。各部位のチャンネルに対して、1 はピクセルがその部位の領域に属することを、0 は属さないことを示す(左から右に: 入力イメージ、顔の右側チャンネル、顔の左側チャンネル)。
入力画像から、24 の追加チャンネルの部位に関するセグメンテーション出力まで、MobileNet の層ごとの活性化を示した例(説明の都合上、特徴マップのダウンサイジングは省略)。

画像のそれぞれの場所について、 出力テンソル P に 24 のチャンネルがあるので、この 24 のチャンネルから最適な部位を探す必要があります。推論の際には、出力部位テンソル P の各ピクセル位置 ( u, P) について、次の式を使って最も高い確率を持つ最適な body_part_id を選択します。


この結果は、各ピクセルがそのピクセルが属する部位を示す整数となっている 2 次元画像(元のイメージと同じサイズ)になります。全体の画像から人を切り抜く際には、人のセグメンテーションの出力結果を使っています。対応する人のセグメンテーションの出力結果がセグメンテーションしきい値より小さい場合、値に -1 を設定します。


24 チャンネルの部位のセグメンテーションと、人のセグメンテーションを組み合わせて、1 チャンネルの部位 ID 出力を生成する方法を示した例。図: Ashley Jane Lewis。 画像のクレジット: “Microsoft Coco:Common Objects in Context Dataset”、 https://cocodataset.org
最終的な 1 チャンネルの部位 ID 出力を示した例。24 チャンネルの部位マスクを組み合わせる際には、前述の argmax 式と、人のセグメンテーションによる領域の切り抜きを使う(説明の都合上、各 body_part_id を重複しない色で示し、出力解像度を落としている)。

実データおよびシミュレーション データによるトレーニング

画像のピクセルを 24 の部位の領域に分割するタスクのために、手作業で大量のトレーニング データに情報を付加するのは、時間のかかる作業です。そこで、内部的には、コンピュータ グラフィックスを使って正解となる部位セグメンテーション情報が付加された画像をレンダリングしました。モデルのトレーニングを行うにあたっては、レンダリングした画像に実際の COCO イメージ(2D キーポイントとインスタンス セグメンテーション情報を付加したもの)を混ぜ合わせました。この混合トレーニング戦略とマルチタスク損失を使うことで、ResNet モデルはシミュレーション情報だけで 24 の部位の予測機能を学習することができました。最終的に、COCO 画像に対する教師 ResNet モデルの予測を蒸留し、BodyPix 用の生徒 MobileNet モデルを作成しました。

実際の画像とコンピュータ グラフィックスで生成した画像の両方で、教師 ResNet モデルをトレーニングする仕組みを示した例。正解となる部位情報は、コンピュータ グラフィックスで生成した画像にのみ存在する。
教師 ResNet モデルの予測を蒸留し、生徒 MobileNet ベースの BodyPix モデルを作成する方法を示した例。

PoseNet と同じく、BodyPix も、一般向けの端末のローカル環境で広く使うことができるモーション キャプチャに向けた小さな一歩になると考えています。3D 体形のキャプチャ、高速に振動する軟組織筋の動作、衣服による外見や形状の違いなど、これから解決しなければならない研究課題は、まだかなり多く残されています。この点を見据えつつも、私たちはモーション キャプチャ テクノロジーがさらに便利になって広く普及し、さまざまな業界で応用される未来を思い描いています。
皆さんが BodyPix モデルを使ってみることができるように、いくつかの例とユーティリティ メソッドを提供しています。ここから着想を得て、モデルに触れていただければ幸いです。皆さんは、どのようなものを作ってくれるでしょうか。そのご報告を楽しみにしています。ぜひ #tensorflowjs、#bodypix、#PoweredByTF でプロジェクトをシェアしてください。

Reviewed by Kaz Sato - Staff Developer Advocate, Google Cloud