3Dモデルをいろいろ作ってみたい

3Dモデルをいろいろ作ろうとがんばっています。苦労した点、役に立ちそうな情報を発信していきます。

ロボットの頭部をAIでデザインできないかと試してみたい ー3Dの畳込み層を使ってみるー

前回の試作では3Dモデル生成のためのGAN(敵対的生成ネットワーク)の構成は2次元の画像を生成するのと全く同じでした。3次元座標情報をさながら地球儀を紙の世界地図に展開するようなかたちで2次元に展開し、ネットワークに入力していたわけです。その後、GANの実装に使われているTensorFlowライブラリの仕様を調べていたらConv3DとかUpSampling3Dといった3次元情報を直接処理する層が用意されていることを知りました。それなら、Conv2Dの代わりにConv3D、UpSampling2Dの代わりにUpSampling3Dを使えば3次元データを直接学習、生成できるだろうということで試してみたのが今回の報告です。
前回は3次元空間上の点を極座標形式(r, θ,Φ)で表して n等分したθ,Φに対してrの値を計算して3Dモデルとしていました。今回はすなおに3次元空間上の座標を(x, y, z)で表現しn×n×n個の座標に対してそこに点があるかどうか(1~-1、値が大きいほどそこに点がある可能性が高いとする)を計算して3Dモデルとします。

問題は2次元から3次元になったことで学習に必要な計算量が飛躍的に増大したことです。普段使っているPCでは1回のバッチ分の計算にも1時間近くかかる始末、何千回の繰り返しなんてとてもおぼつかない。そのため今回の学習にはGoogle Colaboratory(略称: Colab)というクラウドサービスを使わせていただきました。連続して使用できる時間などに制限はありますが、アクセラレータ付きのサーバー上でPythonプログラムを無料で実行することができます。

それでもn=64(64×64×64)の分割ではすぐにリソース制限にひっかかってしまうので、今回はn=32(32×32×32)の分割で処理を行うことにしました。学習が終わればネットワークの重み係数のファイルをダウンロードして、3Dモデルの生成を自分のPCで行うことができます。100次元の値ランダム(1~-1)のベクトルを生成して生成用のネットワークで処理するのですが1個数十秒程度で3Dモデル(32×32×32のnumpy配列)が生成されます。

ノイズの消去や閾値処理等を行ってからOBJ形式に変換(点だけの情報に面情報を付加するプログラムを作成)したのが以下のような感じ。

f:id:ichidaya:20210220171418j:plain

OBJ形式に変換直後の3Dモデル

ここから先は自分でプログラムを作るのはめんどくさいのでZBrushに読み込んで行うことにします。まず、離れ小島のような塊を削除してから左右対称に整形します。

f:id:ichidaya:20210220171724j:plain

左右対称に整形

自作のOBJ生成のロジックがいまいちでメッシュが汚いのでダイナメッシュをかけてスムーズにします。

f:id:ichidaya:20210220172026j:plain

ダイナメッシュ適用後

前回よりはだいぶロボットの顔らしくなってる! そう思いたい..

以下にいくつか生成例を載せています。

f:id:ichidaya:20210220172644j:plain

ロボット頭部の生成例1

f:id:ichidaya:20210220172722j:plain

ロボット頭部の生成例2

f:id:ichidaya:20210220172807j:plain

ロボット頭部の生成例3

頭部全体の輪郭が人の形っぽいものや、平べったいかたち、アンテナ(角?)っぽいものがついたもの、前回の極座標形式での生成よりもバリエーションが増えた気がします。

 

ロボットの頭部をAIでデザインできないかと試してみたい ー単純に適用してみたー

OBJ形式の3Dモデルをニューラルネットへの入力であるNumpy形式に変換するプログラム、逆にニューラルネットの出力のNumpy形式をOBJ形式に変換するプログラムを作ったので、参考書で定義されているGAN(敵対的生成ネットワーク)で3Dデータを生成してみました。学習データはThingiverseで見つけてきたロボットの3Dデータ。ガンダム、パシフィックリムなどのロボットの3DデータをZBrushで編集して頭部だけのデータを60体分集めました。これだけでは全然足りないので、1体分のデータを縦/横に少しずつ引き延ばして25のバリエーションを作成、全部で1500ほどを学習データ(1データは64×64次元、3チャンネル)として準備しました。

ニューラルネットの構成はセレブの顔を生成する例を何も考えずそのまま使用、人間が決めないといけないハイバーパラメータもそのまま使っています。GANではではランダムに発生させた3Dデータから出発してロボットの頭部っぽい3Dデータを生成するネットワークと本物の頭部(学習データ)と人工的に生成された頭部っぽい3Dデータを区別するネットワークが競い合って3Dモデルを発展させていきます。

で、試してみると学習の初期段階で生成されている3Dデータがこんな感じ。

f:id:ichidaya:20210131220434j:plain

学習初期段階で生成される3Dモデル

そもそもなんのかたちにもなっていないという感じですが、学習プロセスを5000回ぐらい繰り返すと、以下のようななんか(?)のかたちにはなってきました。

f:id:ichidaya:20210131220829j:plain

5000回学習後に生成された3Dモデルの例

「どこがロボットじゃーい!!?」と突っ込まれそうですが、ランダムノイズのようなデータからコンピュータが勝手にここまでの3Dデータを作ってくれるってすごいことのように思えます。

もう少し勉強していけばいろいろおもしろいことができそうです。

ロボットの頭部をAIでデザインできないかと試してみたい ーまだ始めたばかりですがー

以前に3Dモデルをプログラムで生成するツールを試作していましたが、今年はFusion 360でのモデリング作業が主となっていてなかなか手をつけることができませんでした。1年以上の間、こっちのアプローチの作業はしていない...

ichidaya.hatenablog.jp

ichidaya.hatenablog.jp

 で、最近読んだのがこの本。与えられた画像や音声のパターンを認識するだけではなくて画像やテキストをニューラルネットワークで生成することができるんですね。

 O'Reilly Japan - 生成 Deep Learning

f:id:ichidaya:20201231185910g:plain

生成 Deep Learning

 

 生成される画像データは3次元の配列(縦×横×RGB)なんですが、じゃあ3次元の形状も大きさも定まった配列で表現できれば(そして十分な学習データが用意できれば)センスの有無に関係なくロボットの顔をデザインできる!

そう考えてまず、OBJ形式の3次元データを大きさ固定の配列で表すPythonプログラムを作ってみました。

  1. OBJデータに含まれる点の座標を極座標形式(r, θ,Φ)に変換
  2. 2π/配列サイズの単位でθとΦを離散化、該当するrの値を持つ2次元配列に格納
  3. RGBの値の代わりにθ、Φで決まるベクトル上で最初の点、2番目の点、3番目の点のrを格納していく

Thingiverseで見つけてきた3Dモデルはこんな感じ。

f:id:ichidaya:20201231205638j:plain

ロボットの顔のOBJデータ

64×64×3の配列データに変換して、3Dグラフにプロットしてると以下のようになります。解像度64だとディテールまでは表現できないものの、大雑把な輪郭や特徴的な額のアンテナは再現できそうです。

f:id:ichidaya:20201231210543j:plain

極座標形式に変換してから離散化

学習用のデータを集めるのがたいへんそうだしそもそもニューラルネットの構成をまだ決めていないのですが、来年(2021年)はこの方向の試行も進めていきたいと思っています。

ロボット骨格にボディアーマーを装着する -次郎丸編-

1か月以上かかってしまいましたが、PETGフィラメントで出力したロボット骨格(前回投稿後に改良)にボディアーマーを装着しました。Fusion360上で大きさや位置の合わせをしながら設計していった(下図)のですが、骨格の動きとアーマーが干渉したり、出力してみると強度がたりなかったりで、ずいぶんと試作と廃棄を繰り返すことになりました。

f:id:ichidaya:20201129163322j:plain

骨格とアーマー

下の写真で試作機がポーズをとった足元に転がっていいるのは完成までに犠牲になったパーツの亡骸(の一部)です。実機だったら開発中止になってますね。

f:id:ichidaya:20201129163631j:plain

完成した試作機と廃棄されたパーツ

 

アーマーは骨格にねじ止めしているので、脱着可能です。前と後ろはこんな感じ。現状、関節の裏側はどうしてもむき出しになってしまうのですが、ガンプラなんかではどう処理しているんだろう。

f:id:ichidaya:20201129164411j:plain

アーマー装着時(前と後ろ)

肩から上腕部分は、1軸(胸の内部に埋込み)、2軸、1軸の3つのジョイントで構成しています。両端のジョイントにアーマー部品をねじ止めしています。青いのはボールジョイントを挟みこんだときの緩衝材として塗ったリキッドゴムです。前回はシリコンゴムのチューブを切って貼り付けていたのを今回は違うやり方を試してみたのですが、結果は関節をぐりぐり動かしているうちにゴムがはがれてきてしまいいまいちでした。TPUフィラメントを試してみたいけど、Adventrer3ではヒートヘッドの温度がちょっと足りないかな、と考えあぐねているところです。

f:id:ichidaya:20201129181054j:plain

肩から上腕部分のジョイントとアーマー

アーマーをつけたことによって関節の可動域が制限されてしまった部分(特に腰のあたり)もありますが、いちおうフルアーマー付きでポーズをとる段階になったので試作機に名前を付つけることにしました。

f:id:ichidaya:20201129204117j:plain

アーマー付きでポーズをとる

前回試作機PLR-18-01につけた名前をつけたのは「太郎丸」でした。

ichidaya.hatenablog.jp

今 回の試作機PLR-23-01は「次郎丸」と命名しました。

ロボット骨格の関節可動範囲を改良

前回のBlogで紹介したロボット骨格を改良を続けています。今回は肩と脚のつけ根の関節の自由度を1つ増やしました。

f:id:ichidaya:20201007221213j:plain

肩と脚のつけ根にジョイントを追加

ロボット骨格の関節はPETG製のパーツとバーツ同士を繋げるボルト/ナット、緩衝材として用いるシリコンゴムのチューブから成り立っています。構成は以下の3種類。

①肘や膝の関節に用いる1軸のジョイント

f:id:ichidaya:20201007222154j:plain

1自由度の関節

②腰の部分に用いる1軸のジョイント

 

f:id:ichidaya:20201007222555j:plain

1自由度の関節(腰)

③肩や脚の根本に用いる2軸のジョイント

f:id:ichidaya:20201007222907j:plain

2自由度の関節

③が今回骨格に追加した関節部品です。ボール型のジョイントをシリコンゴムの緩衝材で挟みボルト/ナットで締め付けています。ボール型ジョイントを使うことで2つの自由度を実現しています。以前に試したボールをスナップインではめ込む方法ではどうしてもポーズの保持力に不満が残るのでボルト/ナットを使うことにしました。

f:id:ichidaya:20201008164010j:plain

前バージョンではできなかったポーズをとれる

左の仮面ライダー1号の変身ポーズでは肩の関節が大きく曲がるようになったので手を顔の前までもってくることができるようになっています。ちなみに前バージョンで同じポーズをとろうとしても下の写真のようになってしまいます。

f:id:ichidaya:20201008164327j:plain

前バージョンではこれくらいが限界

 

ロボット骨格 新バージョン

連休の間にロボット骨格の新バージョンを制作しました。関節の保持力を高めるために新素材(金属)を採用しています。関節の回転軸に8mm~10mmの長さのボルトを使い、ナットでしっかりとめてPETGで出力したパーツを押さえつけています。

f:id:ichidaya:20200926210519j:plain

ロボット骨格タイプA

いったん決めたポーズがくずれてしまうことはないし、金属部分がアクセントになって見た目もいい感じです(と思っています)。

ただ、上の骨格だとアーマー(胸から背中にかけて)を取り付けたとき肩関節の動きが大きすぎて干渉しそうなので下の写真のようなタイプBを制作しました。

f:id:ichidaya:20200926212131j:plain

ロボット骨格タイプB

タイプA/B両方を使っていろいろポーズを試しています。

f:id:ichidaya:20200926213643j:plain

いろんなポーズに挑戦

うーん、肩関節/上腕あたりの自由度をもう1つ増やしたいなという感じ。具体的には今は仮面ライダー1号の変身ポーズがとれない(改造人間じゃなくロボットだからという言い訳はしたくない)。

サーフェスモデリングの練習でロボット頭部を作ってみる

サーフェスモデリングの練習でロボット頭部のモデリングを行ってみました。

f:id:ichidaya:20200919214938j:plain

ロボット頭部のモデル

デザイン自体はネットにあった人間用ヘルメットのマネです。正面図と側面図をキャンバスに貼りつけてから「位置合わせ」で大きさを調整、あとはお手本をなぞるようなかたちでサーフェスを定義しつなげていきました。何回も「計算できません」とFusion 360に怒られながらAdventurer 3で出力するところまでたどりつきました。

f:id:ichidaya:20200919215746j:plain

これまでの頭部(左)と今回作成の頭部(右)

今はまだ、だめなときになぜだめなのかがわからないままにいろんなやりかたを試してみてうまくいく方法を探していくという感じです。