Structure From Motion (SfM)を試す 〜 OpenMVG編 (Ubuntu 16.04) 〜

[前回](https://qiita.com/fujin/items/d7ec313a33f9195bd2e0)に続き、Structure From Motion (SfM) についての内容となります。

今回は、OpenMVG + OpenMVS を使い、複数枚の撮影画像から三次元モデルを作成してみました。
三次元モデルの表示には、MeshLab を使用しています。

※サンプルデータ実行→オリジナルデータ実行の順に記載しています。

# OpenMVG

## OpenMVG とは
Structure From Motion の手法を用いたライブラリになります。

## 実行環境
・Ubuntu 16.04 LTS

## 入力画像
・サンプルデータ
城の画像 11枚
https://github.com/openMVG/ImageDataset_SceauxCastle/tree/master/images

## 導入手順

- 要求パッケージをインストール

```
sudo apt-get install libpng-dev libjpeg-dev libtiff-dev libxxf86vm1 libxxf86vm-dev libxi-dev libxrandr-dev
```

- Githubからソースコードをクローン＆サブモジュールのアップデート

```
git clone --recursive https://github.com/openMVG/openMVG.git
```

- ビルドディレクトリ作成

```
cd openMVG
cd ..
mkdir openMVG_Build
cd openMVG_Build
```

- ビルド

```
cmake -DCMAKE_BUILD_TYPE=RELEASE . ../openMVG/src/
make 
もしくは(Nはコア数)
make -jN
```

参考）
https://github.com/openMVG/openMVG/blob/master/BUILD.md

## 実行

- チュートリアル実行
以下の Python ファイルを修正する。<br>
openMVG/src/software/SfM/tutorial_demo.py.in の
"@OPENMVG_SOFTWARE_SFM_BUILD_DIR@" 部分を<br>
 /openMVG/src/build/Linux-x86_64-Release へのパスへ置き換えます。

```
# Indicate the openMVG binary directory
OPENMVG_SFM_BIN = "@OPENMVG_SOFTWARE_SFM_BUILD_DIR@"

# Indicate the openMVG camera sensor width directory
CAMERA_SENSOR_WIDTH_DIRECTORY = "@OPENMVG_SOFTWARE_SFM_SRC_DIR@" + "/../../openMVG/exif/sensor_width_database"
```

- Python実行

```
python tutorial_demo.py.in
```

実行後 /tutorial_out フォルダが生成され、点群情報のファイルが作成されます。


次に、生成されたファイルを確認します。

# MeshLab

MeshLab を使い、生成した点群データを読み込みます。

## MeshLab とは
MeshLab は、三角形メッシュの処理と編集を行うオープンソースシステムです。
メッシュの編集、クリーニング、修復、検査、レンダリング、テクスチャリング、
および変換のための一連のツールを提供します。

参考）
http://www.meshlab.net/
https://qiita.com/yuzsh/items/ab2869345f5e9e499199

## 導入手順
```
sudo apt-get install meshlab
```

## 実行
MeshLab を起動します。

```
meshlab
```

#### 点群データの読み込み
先ほど生成した以下のファイルを読み込む事で、カラー情報を含んだ点群データを表示出来ます。
[Path to OpenMVG]/src/software/SfM/tutorial_out/reconstruction_sequential内の colorized.ply

![MVG_S1.png](https://qiita-image-store.s3.amazonaws.com/0/134550/69f73065-ffa4-9fd9-3652-a072bd8e31cc.png)

# OpenMVS
OpenMVS を使い、密な点群を再構築します。

## OpenMVS とは
点群データを使って、より密な点群を求めるの Multi-View Stereo という手法を使ったライブラリになります。

参考）
https://blog.negativemind.com/2016/08/31/openmvs-sample/

## 導入手順

#### ビルド
以下のページ内の手順通りにビルドを実行します。
https://github.com/cdcseacave/openMVS/wiki/Building#linux-compilation

## 実行

#### OpenMVGからOpenMVSのプロジェクトファイルへ変換する
OpenMVG の openMVG_main_openMVG2openMVS を使用し、
先ほど出力した sfm_data.bin を scene.mvs ファイルへ変換します。

```
cd <path to openMVG>/src/build/Linux-x86_64-Release
./openMVG_main_openMVG2openMVS -i ../../software/SfM/tutorial_out/reconstruction_sequential/sfm_data.bin -o ../../software/SfM/tutorial_out/reconstruction_sequential/scene.mvs
```

#### 密な点群データ作成

- 以下のフォルダに入力画像をあらかじめ OpenMVG で使用した画像を入れておきます。

[path to openMVS]/openMVS_build/bin/undistorted_images/

- 実行

```
cd <openMVS>/openMVS_build/bin/
./DensifyPointCloud <openMVG>/src/software/SfM/tutorial_out/reconstruction_sequential/scene.mvs
```

> ※エラー対応メモ
> ・scene.mvs を生成場所から移動して実行していまうと「入力画像がありません」エラーが発生する
> [App     ] error: failed loading image header
> [App     ] error: failed reloading image '〜/undistorted_images/100_7100.JPG'
> [App     ] error: invalid project

##### MeshLab で表示
- scene_dense.ply が生成されるので MeshLab で読み込みます。

![MVG_S2.png](https://qiita-image-store.s3.amazonaws.com/0/134550/c5ed43ef-ba3f-1ba6-5534-8c0d11a5331a.png)

密な点群データが表示されています。

#### テクスチャー適応

- ラフなメッシュの再構築

```
cd <path to openMVS>/openMVS_build/bin/ && ./ReconstructMesh <path to openMVG>/src/software/SfM/tutorial_out/reconstruction_sequential/scene_dense.mvs
```

- テクスチャーを貼る

```
cd <path to openMVS>/openMVS_build/bin/ && ./TextureMesh <path to openMVG>/src/software/SfM/tutorial_out/reconstruction_sequential/scene_dense_mesh.mvs
```

##### MeshLab で表示
- scene_dense_mesh_texture.ply が生成されるので MeshLab で読み込みます。

![MVG_S3.png](https://qiita-image-store.s3.amazonaws.com/0/134550/0bbbb089-9d46-a663-67d8-16b66f855b25.png)

綺麗な三次元データが表示されています。

# オリジナルデータ

次にオリジナルデータで試してみました。

## 入力画像
・オリジナルデータ
スマートフォンで自ら撮影した箱の画像 14枚（全方向から撮影しています）

![MVG_S4.png](https://qiita-image-store.s3.amazonaws.com/0/134550/716b1925-cd7f-3944-3be6-88f0dd7f28be.png)

## カメラデーターベース登録
撮影したスマートフォンカメラの物理的なセンサーサイズの横幅を 
sensor_width_camera_database.txt に登録する必要があります。
※使用するカメラが既に登録済みであれば必要はありません。
※登録方法は以下のサイトを参考にしました。
http://blog.goo.ne.jp/yoossh/e/cb24d1dbe945bea3b572e15faba9a64c

・登録先ファイル名
openMVG/src/openMVG/exif/sensor_width_database/sensor_width_camera_database.txt

## 実行

サンプルデータと同様に実行しました。

![sfm_mvs.gif](https://qiita-image-store.s3.amazonaws.com/0/134550/274611b0-43ac-f2fb-d16a-30d72d213220.gif)

綺麗な箱の三次元データが表示されました。

以上、今回は OpenMVG + OpenMVS を使い、複数枚の撮影画像から三次元モデルを作成してみました。