ドローンによる空撮画像を最大活用！WebODM のすゝめ

:::note info
これは [MIERUNE Advent Calendar 2024](https://qiita.com/advent-calendar/2024/mierune) の18日目の記事です。
昨日は @kntoshiya さんによる [PythonでGoogleアナリティクスのデータを解析してみる](https://qiita.com/kntoshiya/items/2bfe910c2f665c9ab12d) でした。
:::

## はじめに
**OpenDroneMap** とは、主にドローンなどで撮影された空撮画像からオルソモザイク、点群、DEM（数値標高モデル）、3Dモデルなどを生成することができるオープンソースの写真測量ソフトウェアです。また、OpenDroneMap プロジェクトの一部である **WebODM** とは、OpenDroneMap の機能を Web ベースで利用することができるアプリケーションです。写真測量のワークフローを GUI で操作することができます。

https://opendronemap.org

https://opendronemap.org/webodm

[Cesium](https://cesium.com/) によるX（旧Twitter）の投稿で、WebODMのダッシュボードから3D Tilesを直接追加することができるようになったとの情報を目にしました。
**Cesium**：
　3D地理空間情報を可視化するためのオープンプラットフォーム

https://x.com/CesiumJS/status/1846251958132174951

この記事では、WebODM を利用した空撮画像の処理方法と、新機能を利用して Cesium に処理したデータを追加する方法をご紹介します。

## WebODM のインストール
WebODM は、以下の方法でインストールすることができます。
- Docker を使ってインストール
- WebODM Installer を使ってインストール

WebODM Installer を使う場合は利用料を支払う必要があるため、今回は Docker を使ったインストール方法をご紹介します。

環境は、以下が最小要件として推奨されています。
- Linux > Windows, macOS
- 100GB の空きディスク容量
- 16GB のメモリ

Windows の方は、[Docker Desktop](https://docs.docker.com/desktop/setup/install/windows-install) のインストールも必要です。

それでは、WebODM をインストールしましょう。
Docker によるインストールは、以下のように入力するだけでOKです。
```
git clone https://github.com/OpenDroneMap/WebODM --config core.autocrlf=input --depth 1
cd WebODM
./webodm.sh start
```
## アカウント作成・ログイン
WebODM が起動したら、```http://localhost:8000``` に接続します。

![スクリーンショット 2024-12-18 1.13.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/c924312d-aba7-9c39-bf56-5b5e9f771583.png)

ログイン画面に遷移したら、ログインもしくはアカウントを作成します。
もし、パスワードを忘れてしまったら、以下のコマンドを実行して新しいパスワードに変更しましょう。

```
./webodm.sh start && ./webodm.sh resetadminpassword newpass
```

## WebODM を使ってみよう！
ここからは、WebODM を使って空撮画像を処理していきます。
### データの準備
OpenDroneMap コミュニティでは、様々なサンプルデータセットを公開しています。特に、「Name」が太字のものは優れたデータセットのようなので、この記事では [helenenschacht](https://github.com/OpenDroneMap/odm_data_helenenschacht/tree/main) を使用することにしました。

https://opendronemap.org/odm/datasets

自身でデータを用意する場合には、以下のポイントに気をつけましょう。
- 少なくとも5枚の画像を用意すること（一般的には少なくとも16~32枚）
- 画像は65%以上オーバーラップしていること（70~72%が目標）
- より高精度の3Dモデルを作成したい場合は83%オーバーラップした画像を使用すること
- ジオリファレンスの精度を向上させたい場合はGCPファイルを用意すること

**オーバーラップ**：
　撮影した連続する画像の重なり度合い
**ジオリファレンス**：
　地理空間情報や画像を実際の座標系に関連付けること
**GCP**（Ground Control Point）：
　地上にある正確な位置がわかっている点のこと

### プロジェクトの作成
```プロジェクトを追加``` をクリックすると、「新規プロジェクト」ウィンドウが立ち上がります。プロジェクトの名称や説明を適宜入力して、```プロジェクトの作成``` をクリックしましょう。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/8074bf56-3066-960a-ae2a-3ebf5d8da357.png)

### GCP インターフェース
```GCP インターフェース``` タブを開きます。
GCPファイルと画像を追加します。

![123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/61f2eed5-7cdd-0f57-0d15-ee55f8f546d1.png)

左側の画像をクリックして開き、右側の GCP と対応させていきます。
画像を開いた際のオレンジのターゲットマークは Delete し、「+」マークから新たに追加します。対応関係が定義されたら、ターゲットマークがグリーンになります。

![スクリーンショット 2024-12-18 4.37.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/da65352f-7270-571d-e260-a3a8b7018c07.png)

すべての画像の設定が完了したら、```EXPORT FILE``` をクリックして GCP ファイルを保存します。

![えxp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/800124fe-99b4-4227-3894-0e6d6275d59a.png)

### 画像と GCP を選択
プロジェクトが選択できたら、画像と GCP を選択します。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/cd859016-e77f-d404-cb8f-8e9a4320d3ca.png)

画像と GCP を追加したら、```画像のサイズを変更``` は ```いいえ``` に設定します。
また、```設定``` の ```編集``` ボタンをクリックして、メニューを開きます。

![qwqw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/b9919b69-d672-2d65-e58c-6bd0a82d5aeb.png)

### タスクオプションの編集
設定を詳細に見てみましょう。
WebODM の設定画面ではアルファベット順に並んでいますが、機能ごとにカテゴライズして整理してみました。
#### 3D モデル
- **3d-tiles**：3D Tiles形式（OGC標準）の3D モデルを生成
- **mesh-octree-depth**：メッシュの詳細度（1-14） 値が大きいほど高詳細
- **mesh-size**：3D メッシュの最大頂点数を指定
- **texturing-keep-unseen-faces**：カメラで見えない面を保持
- **texturing-single-material**：単一テクスチャとマテリアルで出力
- **texturing-skip-global-seam-leveling**：テクスチャの色の正規化をスキップ
- **tiles**：オルソモザイクや DEM 向けのタイルを生成
- **use-3dmesh**：3D メッシュを使ってオルソモザイクを生成

#### ジオリファレンス・GCP
- **auto-boundary**：カメラ位置を基に自動で範囲を設定
- **auto-boundary-distance**：自動境界設定時の外縁距離を指定
- **boundary**：GeoJSON で手動範囲設定
- **cameras**：他のデータセットのカメラパラメータを再利用
- **force-gps**：GPS 情報を強制的に使用（GCPがあっても優先）
- **gps-accuracy**：GPS の精度（m）を設定
- **ignore-gsd**：GSD 制限を無視し最大品質で処理
- **use-exif**：GCP ではなく EXIF の位置情報を使用
- **use-fixed-camera-params**：カメラパラメータの最適化を無効化

#### DEM・DSM
- **dem-decimation**：DEM 生成前に点群を間引く
- **dem-euclidean-map**：DEM の各ピクセルに最近の NODATA セルまでの距離を計算
- **dem-gapfill-steps**：DEM のギャップ埋めステップ数を指定
- **dem-resolution**：DEMの解像度（cm/ピクセル）を設定
- **dsm**：DSM（地表面+構造物）を生成
- **dtm**：DTM（地形のみ）を生成

#### オルソモザイク
- **fast-orthophoto**：簡易的にオルソモザイクのみ生成
- **orthophoto-cutline**：オルソモザイクの外縁をポリゴンで切り抜き
- **orthophoto-resolution**：オルソモザイクの解像度（cm/ピクセル）を指定

#### 処理最適化
- **no-gpu**：GPU を使用せずに処理
- **optimize-disk-space**：ディスクスペースを節約
- **max-concurrency**：並列処理数を設定
- **split**：画像をサブモデルに分割
- **split-overlap**：サブモデル間のオーバーラップ半径を指定
- **use-hybrid-bundle-adjustment**：大規模データの再構築速度を向上

#### 背景除去・AI 処理
- **bg-removal**：AI で画像背景を自動除去
- **sky-removal**：空を自動で除去

#### 処理ステージ・再実行
- **end-with**：指定ステージで処理を終了
- **rerun-from**：処理パイプラインの途中から再実行
- **skip-3dmodel**/**skip-orthophoto**/**skip-report**/**skip-band-alignment**：特定の処理をスキップ

#### カメラ設定
- **camera-lens**：カメラレンズの種類を指定
- **rolling-shutter**/**rolling-shutter-readout**：ローリングシャッターの影響を補正

#### アルゴリズム選択
- **feature-quality**/**feature-type**：特徴点の品質や抽出アルゴリズムを設定
- **matcher-type**/**matcher-neighbors**/**matcher-order**：画像マッチングの方法や順序を設定
- **sfm-algorithm**/**sfm-no-partial**：Structure-from-Motion のアルゴリズム設定

### 処理開始
設定が完了したら、```レビュー``` → ```処理開始``` の順に進み、処理が終わるのを待ちます。
処理速度は、マシンスペックや追加したデータ量に依存します。

![スクリーンショット 2024-12-18 5.32.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/2623b7f9-87dd-10c1-6477-572248c5dfa1.png)

### 各種表示
処理が完了したら、```マップを表示``` や ```3Dモデルを表示``` をクリックするとビューアが立ち上がり、地図上で 3D Tiles を確認したり3D モデルを様々なツールを使って見ることができます。

![スクリーンショット 2024-12-18 6.44.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/6d35c53c-dda8-eecf-54f6-45f819de4440.png)

![スクリーンショット 2024-12-18 6.44.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/b98e51c3-af3d-7e3b-5e07-9612d3269703.png)
 
## 3D Tiles を Cesium に追加してみよう！
ここからは、作成した 3D Tiles を Cesium に追加する手順をご紹介します。
### 準備
[Cesium ion](https://ion.cesium.com) にログインもしくはアカウントを作成する。

![スクリーンショット 2024-12-18 6.02.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/070f4bb6-c8dc-6931-fe97-0b85fc02cfff.png)

ログインしたら、```Access Tokens``` → ```Create Token``` の順に進み、トークンの名称やスコープの設定を済ませて ```Create``` をクリックしてトークンを作成します。
トークンが作成されたら、作成したトークンをコピーして WebODM のダッシュボードに戻ります。

![QWERTY.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/10a10a93-21e1-ff67-8a26-0cc15d602f73.png)

ダッシュボードに戻ったら、```管理``` → ```プラグイン``` から ```cesiumion``` を有効化します。

![スクリーンショット 2024-12-18 6.49.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/c61c8f9d-416d-3e49-9a7b-85cb78e5b721.png)

```Cesium ion``` タブに移動し、トークを貼り付けて ```Set Token``` をクリックします。
以上で準備は完了です。

### 使ってみよう！
WebODM で新しいプロジェクトを作成し、これまでの手順で処理をします。
このとき、タスクオプションの編集を開き、**texturing-single-material** が有効になっていることを確認しましょう。

![スクリーンショット 2024-12-18 6.51.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762063/00ba23a4-de6f-9c6f-51c5-ae61daafbb70.png)

::: note warn
本来であれば、処理が終わると ```Tile in Cesium ion``` というドロップダウンリストが表示されるはずですが、どうやらソフトウェアにバグがあるようです。
この続きは、問題の解決方法が見つかったら追記したいと思います。
:::

https://github.com/OpenDroneMap/WebODM/issues/1567

## まとめ
ドローンの機体は家電量販店などでも手に入るようになりましたが、空撮画像を処理するためのソフトウェアは依然として高額なライセンス料が必要になる場合が多いと思います。
ぜひ、WebODMを活用してみてください。

:::note info
明日は @Guarneri001 さんの記事です。お楽しみに！
:::

#### 参考

https://sk-lb.net/webodm-install/#google_vignette

https://qiita.com/T-ubu/items/727f50b978031861ea02

https://qiita.com/nokonoko_1203/items/97ee058dc6df4e399d02

https://cesium.com/learn/ion/integrations-learn/integrations-webodm/