HoloLensで部屋の3Dスキャン試してみた
tango 凄い!しかし HoloLens だって…。
- 先日、twitterで以下の話が出てました。
Tango持って家の中をぐるぐる歩いてMatterport Scenesアプリに自宅をスキャンさせてみた。完全に俺の家だ… pic.twitter.com/iCIZpDHeEZ
— ようてん (@youten_redo) 2017年4月23日
- tangoは低レベルでPoint Cloudデータ(点群データ)取れるらしく、こういうアプリがあるそうです。
- なのでHoloLensで同じ事できないか?と思いテストしてみました。
(もし、既にHoloLensでこういったアプリがあったら教えてくださいっ!)
Special Mapping をそのまま利用する?
HoloLensの Special Mapping データ(点群)を取り出す(Natural Software)
- 最初に上記ブログを見たのですが、HoloLensの空間認識は単色ポリゴンで行ってるようで、
グレイスケールで思ってたのと違いました。
(すいません)
Locatable camera を使う?
Locatable camera in Unity(Microsoft Windows Dev Center)
- twitterで色々聞いたりして、このサイトにたどり着きました。
こちらによると、フォトキャプチャで3つの事ができるようです。
- ファイルに写真を取り込む
- テクスチャ2Dに写真を取り込む
- 写真を撮影し、生のバイトデータを取得する
- 1番はjpegファイルが作成できますが今回の目的とは違います。
- 2番は表示ができるようになります、以下のような表現もできるようです。
Holographic Photo Blending with PhotoCapture(forum.unity3d)
ですが、このような記述を見て心おれました。
- 3番は色情報をそのまま取れるようで、2番がダメでもこっちなら都合良くできそうです。ですよね~。>空間マッピングされたメッシュに独自のUVを追加することはできますが、それはやりたいことによっては少し複雑かもしれません。https://t.co/a6jYrl5g9V
— saco (@sacokoala) 2017年4月26日
Point Cloud データの表示
Point Cloud Free Viewer(unity asset store)
- このassetをそのまま使おうかと思ったら、事前処理?が必要そうでうまくいきませんでした。
- assetからは頂点カラー表示のshaderだけお借りして、以下のサイトを参考にRawDataからmeshを作成しました。
UnityでPoint Cloudを表示する方法(NegativeMindException)
写真を撮影した方向にPoint Cloud データ表示
-
先程作成したMeshデータを表示する際、カメラの向きに応じた座標変換が必要になります。
-
理論的な事はここに書いてあるようです。
Locatable camera(Microsoft Windows Dev Center) -
理論はとにかく、実際の座標変換コードはさっき提示したここに載っています。
Holographic Photo Blending with PhotoCapture(forum.unity3d) -
めっちゃ簡単に言うと、 photoCaptureからTryGetCameraToWorldMatrixでカメラの方向とってそれを反映するだけです。
※画像はunity上のイメージで、実際の部屋とは関係ありません。
Point Cloud データをSpatial Mapping の表面に張り付ける。
- これは皆さんお馴染みの、RaycastでカメラからPoint Cloud方向へ地形判定して、当たったらSpatialMappingと判定して座標移動、外れたらPoint Cloud捨ててるだけです。
- こんなカンジで地形に沿うようになりました。
※画像はunity上のイメージで、実際の部屋とは関係ありません。
座標系を合わせる(5/9追記)
- そういえば、出力したPoint Cloudが何故か左右逆だった時がありました。
- 理由もわからずとりあえず左右逆転しておいたのですが、つい先日理由が判明しました。
皆さん大好きな地獄の座標系のお話
— あるしおうね (@AmadeusSVX) 2017年5月8日
HoloLens: X右 Y上 Z後
Unity: X右 Y上 Z前
OpenCV: X右 Y下 Z前
全部共通なのはX右だけという…。HoloLensのPhotoCaptureは上記座標系で値を返すので注意が必要です
PointColorList.Add(String.Format(" {0} {1} {2} {3} {4} {5} {6}\n",
-PointAll[i].x, PointAll[i].y, PointAll[i].z,
ColorAll[i].r, ColorAll[i].g, ColorAll[i].b, ColorAll[i].a));
- なので、上の謎のマイナス記号は察してください(多分off形式の座標系が違う。)
Point Cloud データをファイルセーブする。
HoloLensでのアプリからのファイル書き込み(Natural Software)
- 上記ブログを参考に、MeshにせずListに残しておいたPoint Cloudデータにヘッダつけて、*.off形式のファイルとしてセーブしています。
- いつソフトが落ちても大丈夫なように、途中経過毎回全部セーブしてます、無駄ですみません…。
MeshLab で Point Cloud データを表示する。
- *.offファイルはMeshLabで簡単に表示できます。
- こんなカンジで、HoloLens単体で3Dスキャンした物体をカラーで表示一応できました。
#HoloLens で点群データ、小さいぬいぐるみじゃなくて大きなぬいぐるみなら行けるはずだ!という思いで上野駅でチャレンジしてみたが、ガラスケースに入っていて、赤外線は透過、可視光線は反射という罠にはまり、パンダの顔に盛大に反射した白いラインが…。 pic.twitter.com/3E7h7KJXPb
— saco (@sacokoala) 2017年5月6日
ソースコード
-
以下に置きました。
HoloPointCloud(GitHub) -
まだ試した方いないので、ファイル不足していたら追加します。
実行ファイル
- 以下に置きました、手っ取り早く試してみたい方は是非どうぞ。
HoloPointCloud_1.0.1.0_Test.zip(GoogleDrive)
今後の課題
- 移動しながら撮影していると、どこかの誤差から少しづつ座標がずれてる気がする。(要検証)
- カメラの露出で色が不安定になるので露出固定して撮影したい(今はライティングでカバー)
- 適当にmesh作成してるだけで落ちるので、もっとunityの状況(描画やメモリ)を調べてエラーで落ちないようにする。
- point cloud データが重なって無駄な部分を削除する。(MeshLab上でできますが)
- 点群データの座標の倍率、実は見た目で合わせたマジックナンバー入ってます(200)これを、カメラからの距離(正規化されたfrontなので多分1m)と画角と解像度から、正しく計算した値に直す。
- Point Cloud の密度がカメラ全体でmeshが落ちない65000以下で最大と適当なので、例えば撮影範囲の中心だけ使って高密度とか、もっと速度重視の低密度とか、色々試してみたい。(数値65000に修正しました)
- ファイルセーブが手抜きすぎるのでDocumentにoffファイル関連付けてロードもできるように改造すべき。
GW終わってしまったので、課題手を付ける予定は未定です(すみません)