PDALを用いた3次元点群データの着色方法

## はじめに
:::note info
この記事は、[FOSS4G Advent Calendar 2024](https://qiita.com/advent-calendar/2024/foss4g)の19日目の記事です。  
:::

昨今、色々な自治体の3次元点群データがオープンデータとして公開され始めています。公開された3次元点群データで遊んでいると、RGBのカラー情報が含まれてないものもあり、オルソ画像を用いて着色できないかなと思ったので、試してみました。  
この記事では、3次元点群データを変換・処理するライブラリである[PDAL](https://pdal.io/en/2.8.2/index.html)を用いて、着色を行っていきます。    

**2025/01/01 追記**  
この記事で行っている内容を、Google Colaboratoryにて試せるようにしました。  
[こちら](https://github.com/raokiey/colorization-of-point-cloud-data-using-pdal)のGitHub上にあるノートブックから試すことが可能です。  

## 使用するデータ 

- 点群データ [「神奈川県 横浜北部、川崎3次元点群データ」](https://www.geospatial.jp/ckan/dataset/kanagawa-2022-pointcloud)  
（カラー情報は含まれていないため、Intensityの情報をもとに可視化しています。）

![元の点群データ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/7fd9fbff-400d-fc05-ae41-805ae69f7c7b.png)


- オルソ画像
上の点群データと一緒に公開されていたオルソ画像を使用しました。

![オルソ画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/1284c033-982d-d959-3724-0ad911aaa2f3.png)



## 着色方法
基本的には、[PDALのExercisesページ](https://pdal.io/en/2.4.3/workshop/exercises/analysis/colorization/colorization.html)の通り行えば問題ありません。  

### 1. パイプラインの定義
PDALでは、複雑な操作を行うときにJSON形式でパイプラインを定義し、実行できます。ここでは、着色処理を行うパイプラインを定義していきます。  

実際に使用したパイプラインは以下の通りです。
```JSON
{
    "pipeline": [
        "./data/point_cloud/09MD0512_epsg6677.las",
        {
            "type": "filters.colorization",
            "raster": "./data/ortho/09MD0512_ortho_segment_building.tif"
        },
        {
            "type": "writers.las",
            "minor_version": "2",
            "dataformat_id": "3",
            "filename":"./data/point_cloud/09MD0512_epsg6677_segment_building.las"
        }
    ]
}
```
#### パイプラインの解説  
3行目: 
```JSON
"./data/point_cloud/09MD0512_epsg6677.las"
```  
着色したい3次元点群データのパスを指定しています。   

4行目～7行目:
```JSON
        {
            "type": "filters.colorization",
            "raster": "../data/ortho/09MD0512_ortho.tif"
        },
```
この部分では、点群データへの着色を行う処理を記載しています。  
`tpye`: 実施する処理を指定するところです。今回は点群データの着色を行うために`filters.colorization`を指定しています。  
`raster`: 着色処理に使用する画像のパスを指定するところです。  

8行目～13行目:
```JSON
        {
            "type": "writers.las",
            "minor_version": "2",
            "dataformat_id": "3",
            "filename":"../data/point_cloud/09MD0512_epsg6677_color_test.las"
        }
```
この部分では、着色した点群データを出力する処理を記載しています。  
`type`: 処理した点群データをLAS形式などにて出力する`writers.las`を指定しています。  
`minor_version`: LASのバージョンを指定するところです。今回は多くのソフトウェアで使用できる1.2にしました。
`dataformat_id`: Point Data Format IDを指定するところです。今回は時間と色情報の両方をサポートしている3にしました。
`filename`: 出力先のパスを指定するところです。

### 2. パイプラインの実行
先ほど定義したパイプラインを`colorize_pipeline.json`として保存しています。  
以下のコマンドを実行することで、パイプラインで定義した処理を実行できます。
```shell
$ pdal pipeline ./colorize_pipeline.json
```
実行した結果、以下の画像のようになりました。オルソ画像の色を用いて3次元点群データが着色されていることが分かります。  
**今回は、QGISやCloudCompare上での可視化なのでRGB 8bitの画像を用いましたが、lasの仕様上RGB 16bitの方が良いと思われます。**

![カラー化した点群データ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/22fe87e2-9549-c49c-5848-468e9348f326.png)


## 応用編
ここまではオルソ画像を用いて着色していましたが、当然他の画像を用いて着色もできます。  
オルソ画像をセグメンテーション（領域分割）した結果を用いて着色することで、簡易的に3次元点群データをセグメンテーションすることができるかなと思いました。    
そこで、オルソ画像から[Grounding DINO](https://github.com/IDEA-Research/GroundingDINO)と[SAM 2.1（Segment Anything Model 2.1）](https://github.com/facebookresearch/sam2)という2つのAIモデルを用いて、建物を抽出してみました。具体的には、[segment-geospatial](https://samgeo.gishub.org/)というライブラリを用いて行っています。このライブラリ自体の説明に関しては、[公式ドキュメント](https://samgeo.gishub.org/)や[FOSS4G 2023 Japan@FUKUIで発表した資料](https://github.com/raokiey/foss4g_2023_japan_at_fukui_general_presentation_8)、[こちらの記事](https://zenn.dev/syu_tan/articles/0b2d6a3e325d46)などをご覧ください。
text promptに`each building`と指定してセグメンテーションを行った結果、以下の画像のようになりました。  

![セグメンテーション結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/da586d2c-1841-4ae6-6839-1468b5a9139f.png)


先ほど紹介した着色処理を行うと以下のようになり、建物部分が赤色に着色され簡易的ではありますが、3次元点群データに対してセグメンテーションを行ったようになります。  

![セグメンテーション結果でカラー化した点群データ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246958/b512d390-737d-66f0-bb1f-51ea3a81cde7.png)


## おわりに
PDALを用いた3次元点群データの着色方法について紹介しました。PDALを用いると、3次元点群データについて様々な処理が行えるなと改めて実感しました。まだまだ知らない処理があるので、これからも遊んでいきたいと思います。