Deep Learning を使って衛星画像から建物を検出する

# TL;DR

![ダウンロード (2).png](https://qiita-image-store.s3.amazonaws.com/0/156561/da27cd37-0b78-e812-6220-723b0f684be3.png)
<div style="text-align: center;">

* SpaceNetと呼ばれるデータセットを用いて、衛星画像から建物を検出する畳み込みニューラルネットワークを学習した
* 学習したニューラルネットワークにより、IoU=0.602 の精度で建物領域を抽出できることを確認した
* 衛星画像と既存のGISデータに対して機械学習を適用することにより、広域の衛星画像からの情報抽出を大幅に効率化できる可能性を示した
* [Source on GitHub](https://github.com/motokimura/spacenet_building_detection)

#1 機械学習による衛星写真の自動解析

近年、AIブームの影響もあり、衛星画像の自動解析に注目が集まりつつあります。
衛星画像や航空写真は、地図作成や変化抽出などによく使われていますが、撮影範囲が広く含まれる情報もリッチなため、手動で情報を抽出するのには非常に手間がかかります(例えば、GoogleMapsの衛星画像から一つ一つの建物の輪郭をなぞる、二時期の衛星画像を見比べて変化している場所をくまなく探す、などの作業を想像してみてください…)。

その一方で、既存の地図データなど、機械学習の教師ラベルとして扱えるデータもそれなりに存在しており、これらと機械学習を組み合わせることで、衛星画像の自動解析を効率的に実現できる可能性があります。

既存の地図データを使って機械学習のモデルを効率的に学習し、衛星画像から情報を自動で抽出することができれば、より広域からより高頻度に情報を抽出できるようになり、地図の精度向上や、都市域における微細な変化の自動検出など、様々な応用が生まれると考えられます。

今回はその一例として、SpaceNetと呼ばれるデータを使って、衛星画像から建物領域を抽出する畳み込みニューラルネットワーク(CNN)を学習・評価してみます。今回学習したCNNを使うことで、下図のように衛星画像中の建物領域(建物に対応するピクセル)を自動で検出することができます。~~なお、今回使用するソースコードは、近日GitHubで公開する予定です。~~
> 公開しました → [GitHub](https://github.com/motokimura/spacenet_building_detection)

![ダウンロード (1).png](https://qiita-image-store.s3.amazonaws.com/0/156561/9c8ba808-34ee-82a7-fb84-c4f326adb2f4.png)
![ダウンロード.png](https://qiita-image-store.s3.amazonaws.com/0/156561/aacedba6-ef8a-39a6-cd8a-e42da123dbb4.png)

#2 SpaceNetデータセット

SpaceNetは、アメリカのDigitalGlobe社が保有している複数の人工衛星が撮影した画像と、建物や道路といった特定の地物のラベルがセットになったデータセットです。現在はリオデジャネイロ、ラスベガス、パリ、上海、ハルツームの5つの都市のデータが公開されており、AWS S3からダウンロードすることができます。

画像においては、1ピクセルがおよそ30〜50センチメートルほどで、自動車が視認できる程度の解像度を持っています。
一方、ラベルにおいては、地物の一つ一つがポリゴンとして定義されており、各ポリゴンの頂点座標（緯度・経度）がGeoJSON形式とよばれるJSON準拠の地理データフォーマットで記述されています。現在、建物と道路という2種類の地物のみラベルが公開されています。

今回は、リオデジャネイロの衛星画像と建物のラベルを用いて、衛星画像から建物を自動で検出できるCNNを学習・評価することにします。


#3 建物検出CNNとその学習

##3.1 データセット（画像と教師ラベル）の準備

まずデータセットをCNNに与えられるように変換しておきます。衛星画像は縦横それぞれ数千ピクセルの巨大な画像として提供されることが多く、機械学習で扱うにはサイズが大きすぎます。SpaceNetでは、オリジナルの大きな衛星画像をおよそ400×400ピクセルのパッチに分割したものが公開されていますので、今回はこのパッチ画像を使って学習することにします。

一方、建物ラベルも、GeoJSONファイルとしてパッチごとに用意されています。学習に扱いやすいように、それぞれのGeoJSONファイルから建物領域をマスクしたラベル画像を生成します。

このようにして、下図のようなパッチ画像とラベル画像のペアを用意します。画像の枚数は都市によって異なりますが、リオデジャネイロの場合、学習用と評価用の合計で6,937ペア用意できます。

![img_lbl.png](https://qiita-image-store.s3.amazonaws.com/0/156561/11427403-05ec-6a54-f970-38cc499557c3.png)

こうして作成したデータセットを、train/validation/tesの3セットに分割します。今回は、train:validation:test=7:1:2 の割合にランダムに分割しました。

なお、建物ラベルの位置精度はあまりよくありません。下の画像では、ラベルに記述されている建物の輪郭線を赤線で示していますが、よく見ると実際の建物の位置とずれています（特に画像左側）。おそらく、ラベルのもととなる地図データのようなものがあり、その位置精度がそこまで高くないからだと思われます。

![err.png](https://qiita-image-store.s3.amazonaws.com/0/156561/3708240f-c119-56b3-28ad-42d05f66f59f.png)


##3.2 建物検出に使用するCNN (U-Net)

U-Netと呼ばれるCNNを用いて画像から建物領域を検出します。U-Netはもともと医療画像のセグメンテーション向けに考案されたネットワークですが、衛星画像や航空写真にもいくつか適用例があります。

今回はU-Netを使ったセマンティックセグメンテーションを行うことにより、衛星画像から建物領域を抽出します。セマンティックセグメンテーションとは、画像の各ピクセルが、あらかじめ定められた特定のクラス群の中でどのクラスにあたるのかを分類するタスクのことをいいます。今回は、衛星画像の各ピクセルが建物/非建物のどちらにあたるのかを分類することになります。

U-Netは下図に示すようなencoder-decoder型のネットワークで、入力側のレイヤーから出力側のレイヤーに複数のスキップ結合を持ちます。スキップ構造を持つネットワークは他にもありますが、U-Netの場合はencoder側のpoolingレイヤーによって特徴マップの解像度が変わる前後で、decoder側の同じ解像度を持つレイヤにスキップ結合が伸びています。

![unet.png](https://qiita-image-store.s3.amazonaws.com/0/156561/39b95f51-d0d1-3c7a-d990-815bb8ad6607.png)

一般にCNNでは、畳み込みを繰り返すほどにセマンティクス（今回の例では建物/非建物の分類）に関する情報が増えますが、反対に位置に関する情報が失われてしまいます（位置情報が失われてしまうと、クラスの境界付近での分類精度が低下するなどの問題があります）。U-Netでは、encoder側の特徴マップをdecoder側の特徴マップと結合させることによって、decoder側が抽出したセマンティクスに重要な特徴に加えて、encoder側の特徴マップが持つ位置情報を保持したままセグメンテーションを行うことを可能にしています。

##3.3 CNNの学習

いよいよ学習です。今回はOptimizerとしてAdamを使用し、バッチサイズは16に設定しました。また、過学習を防止するため畳み込み層の後にbatch-normalizationを行っています。実装にはChainerを使用しました。
![lcurve.png](https://qiita-image-store.s3.amazonaws.com/0/156561/786c1771-c429-a831-13c5-09b5825dc11b.png)

TensorBoardに出力した学習曲線を上に示します。validationセットでのpixel accuracyがピークに達した49エポックで学習を止めました。なお、学習はAWSのp2.xlargeインスタンス（K80搭載）を使用しましたが、49エポック学習を回すのに17時間ほどかかりました。

#4 結果

##4.1 定性評価

testデータに対する検出結果を下に示しました。左から、入力画像、建物クラスに対する分類スコア、検出結果を入力画像に重ねたもの、正解ラベルを入力画像に重ねたもの、となっています。

![unet_result_tiles.png](https://qiita-image-store.s3.amazonaws.com/0/156561/30aabf64-108f-909f-fd80-9c860eae69d2.png)

上下の例を見てみると、割と小さい建物でも検出できていることがわかります。一方で、木に囲まれた小さな空き地などを建物として誤検出しやすい傾向も見られます。真ん中の例を見てみると、屋根の色が大きく変わっているところが建物として検出できていませんが、それ以外の領域では比較的大きな建物でも欠けなく検出ができていることがわかります。

分類スコアを見てみると、建物の輪郭近くよりも中心部に近い領域でスコアが高くなっています。クラスの境界付近でスコアが下がる（=スコアのクラス間分散が大きくなる）のは一般画像のセマンティックセグメンテーションでもよく見られますが、今回のケースでは建物ラベルの位置精度があまりよくないことも一因として考えられそうです。

##4.2 定量評価

testデータを使って学習したネットワークの評価を行います。まずはtestデータの各ピクセルに与えられたラベルと、ネットワークによる分類結果から、precision, recall, IoU(Intersection over Union)の評価指標を計算してみると以下のようになります。

|precision|recall|IoU|
|:--:|:--:|:--:|
|0.754|0.748|0.602|

そこそこよい結果なのではないでしょうか。都市の建ぺい率を調べる、時系列の衛星画像から建設が盛んに行われている場所を抽出する、災害による被害が大きい場所をおおよそ把握する、などの用途であれば使える可能性がありそうです。

#5 まとめと課題

SpaceNetデータを使って衛星画像から建物領域を抽出するCNNを学習しました。学習したCNNを使用することによって IoU=0.602 の精度で建物領域を抽出できることを確認しました。

今回学習・評価したネットワークでは、建物が密集している領域では隣接する建物が1つの塊として抽出される傾向が強く、建物が密集している都市部では個々の建物を検出することが難しいと思われます。このことから、都市内全域の建物面積を計算するなどの用途では使えそうですが、建物の個数を正確にカウントする、個々の建物の面積を正確に集計する、などの用途で使うには手法の改善が必要になりそうです。今後は、Mask-RCNNなどのインスタンスセグメンテーションの手法を衛星画像に適用することで、個々の建物とその面積を正確に抽出できないか検討したいと考えています。
また、今回は学習・評価ともにリオデジャネイロのデータで行なっているため、他の地域でのネットワークの汎化性能についても検証する必要があります。

# References

* [SpaceNet on AWS](https://spacenetchallenge.github.io/)
* [Getting Started With SpaceNet Data](https://medium.com/the-downlinq/getting-started-with-spacenet-data-827fd2ec9f53)
* [U-Net: Convolutional Networks for Biomedical Image Segmentation](https://arxiv.org/abs/1505.04597)