ロボットの頭部をAIでデザインできないかと試してみたい ー3Dモデル表現方法の変更ー
これまでDeep Learningの入力/出力となるデータとして例えば1x64x64x64といった形式のNumpyデータを使ってきました。64というのは空間をX方向、Y方向、Z方向に分割するときの解像度(数字が大きいほど形状を細かく表現できる)ですが、残った1次元(1チャネル)は64x64x64で区切られた小区画の中にサーフェスモデル(OBJ形式)の頂点が存在する確率になります。VAEやGANのネットワークで生成する3Dデータもこの形式なので、実際にネットワークの出力結果を3Dのモデラーで使うためにはNumpy形式のデータからOBJ形式に変換しなければなりません。OBJ形式には頂点だけではなく3または4個の頂点で作られる面の情報が必要なので、点データの近傍を検索して貪欲算法で近傍点とで構成する面を出力するというプログラムを作ってOBJ形式データを作っていました。
で、今回はDeep Learningのネットワークがどうこうという以前にOBJ形式⇒1チャネルのNumpy配列⇒OBJ形式という変換をやってみてどのくらい元の形状を再現できるのか、というのがテーマです。
以下はテストに使ったオリジナルの3Dモデルです。Thingiverseで見つけたモデルをZBrushで読み込んだ後ダイナメッシュで細かいメッシュのモデルに変案しています。
ニューラルネットで処理できるよう1x64x64x64のNumpy配列に変換します。これをmatplotlibで表示するとこんな感じです。
だいたいの形状は表現できていると思うのですが、これを上述の貪欲算法のプログラムでOBJ形式に変換して表示してみると、ちょっと残念な感じになってしまいました。
近傍の点同士を面としてつなげる閾値の設定にもよるのですが、目とか耳のあたりの凹凸が埋まってわからなくなっている反面、ちょっと細めのアンテナは消えてしまっています。ちなみにMeshLabなどのツールでは一様でない点群データからサーフェスを生成する一般的なアルゴリズム(ボールピボットアルゴリズムというのがあるらしい)を実装していますが、これを単純に適用した結果は上記よりもさらに残念なものでした。なんとなくこんなもんかと思って、この形式のNumpyデータをニューラルネットの入力に使っていたのですが、これだとネットの学習がうまくいって良いデータが生成されたとしてもOBj形式に変換するときに劣化してしまいます。
今回、もうちょっとなんとかしたいということで考えたのはもともとのOBJ形式がもっていた面の情報をNumpy形式データに取り込むこと。具体的にはある区画に頂点が存在するかという1チャンネルの情報ではなく、頂点を含む面の方向、正確には頂点を含む面に垂直なベクトル(法線ベクトル)を示す3チャンネルの情報を使うことにしました。OBJ形式データには頂点とその頂点が構成する面の情報があるので、面に対する法線ベクトルを計算して3x64x64x64のNumpyデータを出力します。NumpyデータからOBJ形式に復元するさいには、法線ベクトルと垂直な平面上に位置する近傍点を優先して面データを作成します。3x64x64x64のNumpyデータからこの方式でOBJを復元すると以下のようになりました。
オリジナルにはおよばないもののだいぶ形状を復元できるようになりました。
Pytorchの使い方もわかってきたところで、現在3x64x64x64のデータでVAE(変分オートエンコーダ)の学習をおこなっています(いまいま、まる4日PCを動かし続けている…)。どんな3Dデータが生成できているか、期待しながら待っているところです。