LoginSignup
2

posted at

Organization

指定した領域のラスタータイルをダウンロードしたりGeoTIFFに変換してくれるPythonパッケージをPyPIで公開しました!

これは MIERUNE AdventCalendar 2022 22日目の記事です。
昨日は @asahina820 さんによる Cesium for Unityを使って3D Tiles形式のPLATEAUデータを表示する でした。

初めに

ラスタータイル、というデータ形式をご存知でしょうか?

WebGISではとてもよく利用される概念ですが、以下のように背景となる地図(画像)をズームレベルという概念に沿って倍率を変え、ズームレベルが上がるごとに地図の詳細度が上がっていきます。

image.png
地理院タイルについてより)

表示区画があらかじめ決まっているため、地図画像を事前に作成しておくことが可能で、軽量かつ高速に全世界分の背景地図をブラウザで表示することができます。

こんなラスタータイルですが、通常はhttps://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.pngのように{ズームレベル}/{X座標}/{Y座標}.png(.jpg)のようなZXYのタイル座標を指定する形式で配信され、ブラウザなどから利用することを想定しています。

ただ、国土地理院が配信する標高タイルのようにピクセルの値そのものに意味があるラスタータイルも存在していたり、航空写真などであればブラウザ以外でも一部の箇所だけ取得し、単なる背景画像以外の用途で利用したいなぁと思う場面はちょこちょこあります。

ラスタータイル自体は、それ自体に地理的な意味を全く持たないただの画像データなんで、そんな時にいちいち緯度経度からズームレベルごとのタイル座標を計算し、ダウンロードして、地理情報を埋め込んで〜みたいなことはしたくないわけです。

こういう悩みを持つ人は多そうなんで、みなさんが利用できるようにPythonでパッケージを作成して、PyPIに公開しました!

使い方

今回作ったのは、tile-operatorというツールです。

PyPIでも公開しているので、Python実行環境があれば「pip」などを利用して誰でも簡単に利用することができます。
https://pypi.org/project/tile-operator/0.0.6/

pip install tile-operator

CLIツールとしても利用できますが、多少めんどくさい設定が必要になります

CLIとして利用するための準備

CLIとして利用する場合にはこちらからSource code(zip)をクリックしてコード一式をダウンロードしてください。

image.png

その後、zipを解凍し、ターミナルなどを利用してtile-operatorディレクトリの中に入ってください。

$ cd ~/Downloads/tile-operator-0.0.6
$ ls -al
total 224
drwxrwxr-x@ 10 satoru  staff    320 12 17 16:11 ./
drwx------@  9 satoru  staff    288 12 17 21:44 ../
-rw-rw-r--@  1 satoru  staff   3277 12 17 16:11 .gitignore
-rw-rw-r--@  1 satoru  staff   1069 12 17 16:11 LICENSE
-rw-rw-r--@  1 satoru  staff   1904 12 17 16:11 README.md
-rw-rw-r--@  1 satoru  staff  91048 12 17 16:11 poetry.lock
-rw-rw-r--@  1 satoru  staff   1023 12 17 16:11 pyproject.toml
drwxrwxr-x@  5 satoru  staff    160 12 17 16:11 tests/
drwxrwxr-x@  4 satoru  staff    128 12 17 16:11 tile_operator/
-rw-rw-r--@  1 satoru  staff   1338 12 17 16:11 to.py

次に、poetryをインストールします。

curl -sSL https://install.python-poetry.org | python -
echo 'export PATH="/Users/satoru/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
poetry --version

バージョンが表示されれば、正常にインストールできています。できていない場合はググってください!!!

Pythonの仮想空間の管理をしやすくさせるために、ディレクトリ内に仮想環境を作成されるよう変更しておきましょう。

poetry config virtualenvs.in-project true

ここまで終了したら、以下のコマンドを入力して、tile-operatorの依存パッケージをインストールします。

poetry install
poetry shell

ここまでの準備が終わったら、ようやく指定範囲のラスタータイルをダウンロードしていきます。

初めに画像を取得したい範囲の矩形を示すGeoJSONを作成しましょう。

geojson.ioなんかを利用すると以下のように手軽に作成できます。

範囲が広すぎるとデータ数も増えてしまうので、札幌駅周辺のみを取得することとしましょう。

image.png

右に表示されているGeoJSONをaoi.geojsonなど適当な名前をつけて作成し、書き込んでおきます。

image.png

次に、取得したいラスタータイルのURLを設定します。

今回はOpenStreetMapのデータを利用していきましょう。

URLは以下のようになります。
https://tile.openstreetmap.jp/{z}/{x}/{y}.png

最後に取得したいズームレベルを決めましょう。

今回は18を指定します。

ズームレベル18はとても詳細度の高いズームレベルですので、広い範囲で取得するときはお気をつけください。

東京都全域とか指定すると、10万ファイルは超えると思います

それではコマンドを実行してみましょう。

$ python to.py -v download https://tile.openstreetmap.jp/{z}/{x}/{y}.png aoi.geojson 17

Tile Download

 Options:
  tile_url=https://tile.openstreetmap.jp/{z}/{x}/{y}.png
  file_path=aoi.geojson
  zoom_level=17


100%|█████████████████████████████████████████████████████████████████████████████████████| 20/20 [00:10<00:00,  1.94it/s]

プログレスバーの表示から、20枚の画像がダウンロードされたことがわかりますね。

ダウンロードされた画像はこのようにoutputフォルダが生成され、そこに格納されます。

image.png

ね、簡単でしょ?

Pythonのパッケージとして利用する

こちらはPyPIからインストールすればすぐに使える上、CLIツールより高機能です。

まずは以下のようにクラスとユーティリティ関数をインポートします。

from tile_operator.operate import TileOperate, file_to_bounds

次に、インポートしたfile_to_boundsを利用して、先ほど作成したaoi.geojsonのバウンディングボックスを作成しましょう。

file_path = "./aoi.geojson"
bbox = file_to_bounds(file_path).bounds()
bbox
# (141.34524527865244, 43.06547110473289, 141.3568432889649, 43.07128825219701)

その後、作成したbboxとデータを取得したいズームレベルのみ指定してインスタンス化します。

to = TileOperate(
    bbox=bbox,
    zoom_level=17,
)

そしてset_tile_listメソッドを利用し、その後、geo_tile_listメソッドを呼び出してセットされたタイル座標の一覧を取得しましょう。

to.set_tile_list()
tile_list = to.get_tile_list()
print(len(tile_list))

ダウンロードされるタイルが、CLIを利用した時と同様に20個であることがわかりました。

20

さらに、タイル座標の一覧も取得できます。

to.get_tile_list()
[(116998, 48126),
 (116998, 48127),
 (116998, 48128),
 (116998, 48129),
 (116999, 48126),
 (116999, 48127),
 (116999, 48128),
 (116999, 48129),
 (117000, 48126),
 (117000, 48127),
 (117000, 48128),
 (117000, 48129),
 (117001, 48126),
 (117001, 48127),
 (117001, 48128),
 (117001, 48129),
 (117002, 48126),
 (117002, 48127),
 (117002, 48128),
 (117002, 48129)]

set_tile_listメソッドを呼び出して、タイル座標の一覧が生成された後であれば、download_all_tilesメソッドを呼び出し、タイルをダウンロードすることが可能です。

tile_url = "https://tile.openstreetmap.jp/{z}/{x}/{y}.png"
to.download_all_tiles(tile_url)
100%|██████████| 20/20 [00:05<00:00,  3.70it/s]

その他便利そうな機能

タイル座標に応じたグリッド(ポリゴン)を作成し、geopandasのGeoDataFrameで返すメソッドも用意されています。

to.create_tile_grid_from_bbox_list()

image.png

ディレクトリ構成が{z}/{x}/{y}.png(.jpg)になっている必要がありますが、タイル画像へのパスを与えて、GeoTIFFに変換するメソッドもあります。

tile_path = "./output/17/116998/48126.png"
to.tile_to_geotiff(tile_path)

指定ファイルと同じディレクトリに48126.tifというファイルが生成されるので、QGISで表示させてみましょう。

背景地図とぴったり重なります。

image.png

終わりに

ということで、ありそうでなかった(実はあるかも)手軽にタイルをローカルマシンにダウンロードしたり、色々できるツールを作ってみました!!

これからも機能を追加していこうと思いますんで、使ってみてください!

明日は@soramiさんです!お楽しみにー!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
2