他人のGPUで"大規模"フォトグラメトリしたい！！

# 概要

少し前に、[他人のGPUでフォトグラメトリしたい！！](https://qiita.com/kotauchisunsun/items/9e3444faec734ddedcb5)という記事を書きました。これはGoogle Colaboratory上の無料のGPUでフォトグラメトリをする方法について紹介しました。
意外にも反響があり，実際にフォトグラメトリしていただいた方もいらっしゃいます．

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">小物をとってみたけど、小物ではなくてその周りがオブジェクトになった。うーんなんでだろう。<a href="https://twitter.com/hashtag/photogrammetry?src=hash&amp;ref_src=twsrc%5Etfw">#photogrammetry</a> の写真のとり方を知りたい。<br>画像24枚使って約30分弱で完成。 <a href="https://t.co/5j2hOEgjXm">pic.twitter.com/5j2hOEgjXm</a></p>&mdash; すぎどん (@sgidon) <a href="https://twitter.com/sgidon/status/1173498783809687552?ref_src=twsrc%5Etfw">September 16, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">すたみとにてこたうちさん( <a href="https://twitter.com/kotauchisunsun?ref_src=twsrc%5Etfw">@kotauchisunsun</a> )がお話してた他人のGPUでフォトグラメトリ！早速（遅い）やってみたんですが、私でも簡単にできました！すごい！<br>撮影場所:相模原伊勢丹8F KIHACHI前<br>記事はこちら！↓<a href="https://t.co/xHssCRDoSs">https://t.co/xHssCRDoSs</a> <a href="https://twitter.com/hashtag/Qiita?src=hash&amp;ref_src=twsrc%5Etfw">#Qiita</a> <a href="https://twitter.com/hashtag/%E3%81%99%E3%81%9F%E3%81%BF%E3%81%A8?src=hash&amp;ref_src=twsrc%5Etfw">#すたみと</a> <a href="https://t.co/oCy9kFeVv7">pic.twitter.com/oCy9kFeVv7</a></p>&mdash; 彩|スマブラV (@aya_ssbgc) <a href="https://twitter.com/aya_ssbgc/status/1179471233575862272?ref_src=twsrc%5Etfw">October 2, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


しかし、これには何点か課題があり、

- 12時間以上かかるフォトグラメトリができない。
- セッションが切れるとデータが消える。

という問題点がありました。今回、これを改善しました。それにより、GoogleColab上で，長時間のフォトグラメトリが可能になりました．実際に，**画像数2,700枚超え、総稼働時間100時間超のフォトグラメトリに成功しました。**
今回は、そのスクリプトをご紹介します。

# "大規模"とは

特に、公式の定義はありません。私が勝手に言っているだけです。

| 規模 | 画像の枚数 |
|-----:|---------:|
|小規模| < 100     |
|中規模| < 1,000   |
|大規模| > 1,000   |

ぐらいじゃないかな。と思っています。

龍 lilea(@lileaLab)さんの資料で、以下のようなものがあります。
https://onedrive.live.com/view.aspx?resid=B21F9927B008AC46!2788789&ithint=file%2cpptx&authkey=!ABzF3ZARTTdtw8w

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/d3e04c8c-8f0a-aa1d-dc73-685d808b87e4.png)

これを見ると、部屋のような規模のフォトグラメトリをしようとすると大体、1,000枚ぐらいの画像が必要になるのかな。と思いました。
そこで、目標として、GoogleColaboratory上で1,000枚を超えるフォトグラメトリをする。ということを目標にしました。


# GoogleColaboratoryでフォトグラメトリする
## 1. GoogleDriveにフォルダを作成する．

[GoogleDrive](https://drive.google.com/drive)にアクセスして，"images"というフォルダを作成します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/228d228b-5bf8-bd56-4170-024f499708d6.png)

## 2. 画像をアップロードする

今回のサンプルは 岩山幸洋(https://twitter.com/HappyOcean) さんの最近公開されたデータセットの画像をアップロードします．

https://github.com/HappyOcean/Full_Body_Photogrammetry

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/5b0b6f6a-7bf5-3a3b-144b-83f1629f9a56.png)

## 3. GoogleColaboratoryの準備をする．

GoogleColaboratoryにアクセスし，左上のメニューから「Python3の新しいノートブック」をクリックします．
https://colab.research.google.com/notebooks/welcome.ipynb

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/b751f6c8-1b18-b7b0-4ee4-7466f33c5710.png)

新しいノートブックが表示された後，「編集」「ノートブックの設定」をクリックします．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/96bea3f2-aca5-6928-8e4a-46dbca4e4e72.png)

ノートブックの設定で，「ハードウェアアクセラレータ」を「GPU」に設定し，「保存」します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/b6f9efd1-fd7e-accb-9a58-38bc7291518c.png)

## 4. GoogleColaboratoryでフォトグラメトリする．

以下のスクリプトをコピーし，GoogleColaboratoryにコピーします．

```py:large_meshroom.ipyb
from google.colab import drive
drive.mount('/content/drive')

!mkdir "drive/My Drive/cache"
!mkdir "drive/My Drive/result"
!mkdir "drive/My Drive/log"

!pwd
!wget https://github.com/alicevision/meshroom/releases/download/v2019.2.0/Meshroom-2019.2.0-linux.tar.gz
!tar xvf ./Meshroom-2019.2.0-linux.tar.gz

!./Meshroom-2019.2.0/meshroom_photogrammetry  \
    --input "/content/drive/My Drive/images" \
    --output "/content/drive/My Drive/result" \
    --cache "/content/drive/My Drive/cache" \
    --forceStatus \
    | tee "/content/drive/My Drive/log/"`date '+%Y%m%d%H%M%S'`".log"
!rm -rf "drive/My Drive/cache" 
```


そのあと，「ランタイム」から「すべてのセルを実行」をクリックします．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/f747fe41-c663-e90f-f08b-e8f85538de66.png)

次に，GoogleDriveとの連携を求められます．URLが以下のように表示されるので，クリックします．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/0e229adc-40c8-0aa9-eea5-32f3bf5de356.png)

そのあと，先ほど画像データをアップロードしたGoogleアカウントをクリックします．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/cb6d0066-4660-87b7-e2e0-5a17da22150d.png)

右下の許可をクリックします．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/a204fd63-003d-6773-ceff-7ee7c6c610e1.png)

トークンが発行されるので，右のアイコンをクリックし，トークンをコピーします．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/9e186d70-3b41-35ec-9c53-b10a65429002.png)

先ほどのトークンを「Enter verification code:」の横のテキストボックスに貼り付け，Enterを押下します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/40dd1e8c-d554-2f60-eafa-4afc71d34346.png)

あとは自動でMeshRoomがインストールされ，フォトグラメトリが実行されます．

## 5. 結果をダウンロードする．

フォトグラメトリが終了すると，GoogleDriveにresultというフォルダが作成されます．この中身が出力結果となっています．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/da8e28f2-bc9c-24e4-588f-3f69c82ef208.png)


これで完成です．このデータセットの場合，3.5hから4.0hぐらいかかりました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/81f3b4c5-77e6-c018-63fd-813144012ffc.png)

実際に見れるモデルを以下のリンクに置いておきます．
アップロードの制限で上がらなかったので，Blenderでポリゴン数を10%まで削っています．

https://gallery.styly.cc/kotauchisunsun/856b667b-f1bc-11e9-b34d-4783bb2170d0

# 6. 再実行の仕方

不運にも何らかの原因で接続が切れたり，12時間の計算時間の上限が来て，実行がとまることがあると思います．その場合，同じNotebookを開き，「ランタイム」から「すべてのセルを実行」を実行して，GoogleDriveとの連携の手順を踏んでください．**これだけで自動で途中から再開されます．**

# GoogleColaboratoryが落ちない工夫

[前の記事](https://qiita.com/kotauchisunsun/items/9e3444faec734ddedcb5)では@YougurutさんがAutoRefreshの使い方をコメント欄で教えていただきました．
この方法は，私も知っていたのですが，割と失敗するといった記事を見ていたので，ちょっと紹介するか迷っていました．
というわけで，古典的ではありますが，私はbatで解決してました．

```bat:cron.bat
echo off
set /P URL="Google ColabのURLを入力してください: "
:LOOP
    "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" %URL%
    timeout 3600
goto :LOOP
```

上記した内容をcron.batとして，保存して，ダブルクリックして下さい．
そうすると，`Google ColabのURLを入力してください`と表示されるので，実行しているGoogle ColabのURLを貼り付けてください．コンソール右クリックで貼り付けられます．
そうすると，1時間ごとにchromeが起動します．これで，大体回避することができます．


# 大規模フォトグラメトリの実験

上記した手順はあくまでサンプルで，大規模フォトグラメトリしたものは別のデータセットです．まず初めにその出力結果を見せます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/64bb24b8-3150-675f-3b6f-f87bae5e28a6.png)

実際に見れるモデルはこちら
https://gallery.styly.cc/kotauchisunsun/48d4e551-f1ae-11e9-b34d-4783bb2170d0


クオリティ的に非常に雑ですね．それと，部屋のようなものがフォトグラメトリされています．なぜ，このようなことになったのか．その理由がこちらです．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/ec95a4ad-537e-7aad-892f-87a1e76929f5.png)

実は，大規模フォトグラメトリの大きな問題として，"データセットがない"という問題があります．ネットを探しても，1,000枚越えのデータセットはありません．そのため，手ごろな方法で，データを水増ししようと考えました．その結果，動画から画像出力する発想に至りました．
そこで，家に手近にあった，キズナアイのフィギュアをフォトグラメトリしてみよう．と思って，動画を撮りました．で，その動画のデータを全フレーム画像で書き出して，フォトグラメトリを行った結果，こうなりました．
フォトグラメトリしたかったのは，実は赤丸の部分だけだったのです．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/4d7e1bb2-72dd-6a32-b3a4-68014de95d92.png)

その結果，MeshRoomが余計なことをしてくれたせいで，部屋全体がフォトグラメトリされる結果となりました．
では，キズナアイのフィギュア自体はどうなったか？というとクリーチャー化しました．ルパンvs複製人間にでてくるミニサイズのマモーみたいなキズナアイになりました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139643/c2d48d3c-a3cb-eaa6-8fde-a2ce9c50a034.png)

さて，結果のモデルとしては割と残念な感じになってしまいましたが，得られた知見として，

**MeshRoomで画像2,700枚越えのフォトグラメトリをGoogleColabratoryで無料で可能である．**

ということです．MeshRoomは無料のOSSのソフトであるため，実際にどこまで耐えられるのか？という疑問がありました．しかし，この結果から，MeshRoomでも大規模なフォトグラメトリは可能のようです．
また，そのような大規模なフォトグラメトリには計算時間が必要になってきます．そんな中で，GoogleColabratoryの無料枠のみでできるスキームができるのか？というと，この実験の結果から，無料枠のみでフォトグラメトリ可能でした．
ただし，クオリティに関しては調整が必要そうである．という結果でした．


# 制限

これで，ほぼほぼ普通の用途においてはフォトグラメトリに関して制限がなくなりました．が，やはり制限はあります．

- 1タスクあたり12時間まで
- キャッシュの限界はGoogleDriveの空き容量の限界

という2点があります．前者は，MeshRoomの仕様によるものです．MeshRoomは1つのフォトグラメトリをするにあたり，「CameraInit」「FeatureExtract」「FeatureMatching」等のいくつかのタスクに分かれます．このタスク単位で実行が継続されます．そのため，1つのタスクに12時間以上かかると，途中でGoogleColabratoryにジョブを切られて，永遠に完成しません．しかし，これはあまり気にする必要がなく，先のキズナアイの大規模フォトグラメトリでも，最大のタスクが6時間程度だったので，まだまだ規模的には行けると思います．
問題なのは後者です．今回の仕様により，GoogleDriveにcacheというフォルダが作成されるようになりました．このcacheにより継続的な実行を実現しています．しかし，このフォルダが非常に肥大化しやすく，先の岩山さんの例だと7GBぐらいの中間ファイルができています．そのため，かなり容量を圧迫します．GoogleDriveの無料枠が15GBなので，そこが限界になってきます．これは割と引っ掛かります．


# 感想

正直な話，開発には時間がかかりませんでしたが，実行に時間がかかりました．これほど長時間PCを動かすジョブは久々だったので，かなり精神的にキツイものがあります．一度ミスると10日間のジョブが飛ぶので，最後の結果を見るまでは，なかなかしんどかったです．結果として，モデルのクオリティは高くありませんでしたが，そもそもMeshRoomに大規模フォトグラメトリの能力があることが分かっただけで満足です．大規模フォトグラメトリできるのはRealityCaptureだけではないようです．次のフォトグラメトリネタとして広域フォトグラメトリのネタを用意しているので，またちょっと暇を見てやろうと思います．