23
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MBTiles でタイル地図のオフライン利用

Last updated at Posted at 2019-01-03

タイル地図


国土地理院の地理院タイルをはじめとするタイル地図の登場で、背景図を簡易に、かつ快適に利用することができるようになりました。また、すべてのタイル地図に当てはまるわけではありませんが、空中写真も含め無償で利用できるものも多く、助かります。

QGIS 2.x では TileLayer Plugin を利用するケースが多かったですが、 QGIS 3.x (正確には 2.18 も対応)からは標準で XYZ Tiles が追加できるようになりました。このように便利なタイル地図ですが、基本的に HTTP(S) 上にある画像データであるため、利用するときは(内部で)画像をダウンロードする必要があります。しかし、 GIS で個人情報等も一緒に扱うなどの理由でインターネットに接続しない環境で GIS を使いたいという要望も耳にします。

タイル地図をオフラインで使うことができるか。という問題ですが、基本的に一定のルールにしたがって配置された画像の集まりなので、ローカルに保存したタイル画像でも仕組み上は問題なさそうです(実際 TileLayer Plugin はローカルパスに対応)。しかし、 QGIS 標準の XYZ Tiles は現時点でローカルのパスには対応していないようです。 QGIS 3.4 ではローカルパスに対応したようです。1

またタイル地図は 256px 四方の画像の集まりなので非常にファイル数が多くなります。このため一旦タイル地図をダウンロードできても、バックアップや他 PC へファイルのコピーを行う場合には非常に時間がかかります。

そもそもダウンロードしていいの?

っと、その前に地理院タイルをローカルにダウンロードして利用してよいのでしょうか。

地理院タイルには大きくわけて基本測量成果を使用したタイルと、基本測量成果には当たらないタイルがあります。地理院タイル一覧にわかりやすく分類されていますが、空中写真や衛星写真は基本測量の成果には当たりません。また基本測量の成果に当たるものは原則測量法29条30条に従い国土地理院の長の承認を得る必要がありますが、条件を満たせば出典明示などで利用することができます。たとえば社内のイントラネットで利用する場合は30台を上限に複製できるとされています(よくある質問と回答)。ただし印刷し配布といった使用を行う場合は別問題なので注意が必要です。

また、基本測量成果に当たらない空中写真等は国土地理院コンテンツ利用規約に従い自由に複製することができます。

ただし、困ったら申請を行っておくほうが安心して利用できるかと思います。

ダウンロードに関しては国土地理院から qdltc というツール(スクリプト)が公開されています。 qdltc は目録ファイルをもとに全タイルを並列ダウンロードするツールです。全ファイルのダウンロードは1週間くらいかかるそうです。ただし、2回目以降の更新分ダウンロードは MD5 ダイジェストを確認することにより短時間ですむようになっているそうです。

たとえば std の目録ファイルは以下の場所にあります。 std の場合、目録ファイルだけで1.1 GB ほどあります。

  • https://cyberjapandata.gsi.go.jp/xyz/std/mokuroku.csv.gz

目録ファイルはパス、最終更新時刻、ファイルサイズ、 MD5 ダイジェストをまとめた CSV ファイルを gzip で圧縮したものです。

$ gzip -dc mokuroku.csv.gz | head
0/0/0.png,1457603626,77992,7186204bdc21218bf6d9dd0a39b17ef8
1/0/0.png,1457603627,75099,8abde99545d93135816895dd90871856
1/0/1.png,1457607266,49114,b1c45de27b2532a2c11710ad22851675
1/1/0.png,1457607264,76255,0d99409cff6edaad7a722a262a133180
1/1/1.png,1457603624,46597,15ca0df415ce6a3274edf96f65ac65f5
10/861/365.png,1450706972,222,738667a1b2ac6a61a03addc227320bb8
10/861/366.png,1450706950,222,edd701bef084ea879f7845e5cf140266
10/861/367.png,1450706951,222,c43784cad649d3664a2aaf68f035b6fa
10/861/368.png,1450706949,222,beca812cd632578f01f066cda486c8e6
10/861/369.png,1450706970,222,8ea3c54f6da6e594e5f90a2b3e81bdbb

私は、(たとえば)東京23区はズームレベル18まで、横浜大宮千葉あたりまではズームレベル16まで、関東周辺はズームレベル13まで、その他地域はズームレベル9までみたいなことを、手作業で地域指定してダウンロード範囲を決めるスクリプトを使っています。

もちろん、夜間に、適度な待ち時間をはさみながら。サーバ資源大事大事。

国土地理院の目録の活用は地理院タイル目録を用いた地理院タイルの効率的な同期方法も参考になります。

MBTiles

MBTiles は SQLite を利用したラスタ形式のひとつで、タイル地図をひとつのファイルにまとめることができます。 MBTiles に対応しているツールはいくつかありますが、今回は Mapbox 社からでている mb-util を使うことにします。

mb-util は easy_install などでインストールしてもよいのですが、リポジトリをクローンすれば Python スクリプトとしてそのまま使えます。

たとえば ort にダウンロードしたタイルが z/x/y の形式のパスで格納されているとします。

$ tree ort | head -n 20
ort
|-- 10
|   |-- 900
|   |   |-- 396.jpg
|   |   |-- 397.jpg
|   |   |-- 398.jpg
|   |   |-- 399.jpg
|   |   |-- 400.jpg
|   |   |-- 401.jpg
|   |   |-- 402.jpg
|   |   |-- 403.jpg
|   |   |-- 404.jpg
|   |   |-- 405.jpg
|   |   |-- 406.jpg
|   |   `-- 407.jpg
|   |-- 901
|   |   |-- 396.jpg
|   |   |-- 397.jpg
|   |   |-- 398.jpg
|   |   |-- 399.jpg

$ du -hs ort
1.3G	ort

手元にあったものは 1.3 GB くらいのデータですね。これを mb-util で変換します。

$ mb-util --silent --image_format=jpg ort ort.mbtiles
53200 tiles inserted (2020 tiles/sec)

$ ls -lh ort.mbtiles 
-rw-r--r--. 1 tohka tohka 1.2G 2018-12-31 16:31 ort.mbtiles

今回のデータだと、変換は1分程度で終わりました。 gdalinfo でラスタ情報を確認してみます。

$ gdalinfo ort.mbtiles 
Driver: MBTiles/MBTiles
Files: ort.mbtiles
Size is 131072, 131072
Coordinate System is:
PROJCS["WGS 84 / Pseudo-Mercator",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.0174532925199433,
            AUTHORITY["EPSG","9122"]],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Mercator_1SP"],
    PARAMETER["central_meridian",0],
    PARAMETER["scale_factor",1],
    PARAMETER["false_easting",0],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AXIS["X",EAST],
    AXIS["Y",NORTH],
    EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs"],
    AUTHORITY["EPSG","3857"]]
Origin = (15497753.906250000000000,4383203.125000000000000)
Pixel Size = (1.194328069686890,-1.194328069686890)
Image Structure Metadata:
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (15497753.906, 4383203.125) (139d13' 7.29"E, 36d35'52.35"N)
Lower Left  (15497753.906, 4226660.156) (139d13' 7.29"E, 35d27'38.37"N)
Upper Right (15654296.875, 4383203.125) (140d37'29.79"E, 36d35'52.35"N)
Lower Right (15654296.875, 4226660.156) (140d37'29.79"E, 35d27'38.37"N)
Center      (15576025.391, 4304931.641) (139d55'18.54"E, 36d 1'52.75"N)
Band 1 Block=256x256 Type=Byte, ColorInterp=Red
  Overviews: 65536x65536, 32768x32768, 16384x16384, 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512, 256x256
Band 2 Block=256x256 Type=Byte, ColorInterp=Green
  Overviews: 65536x65536, 32768x32768, 16384x16384, 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512, 256x256
Band 3 Block=256x256 Type=Byte, ColorInterp=Blue
  Overviews: 65536x65536, 32768x32768, 16384x16384, 8192x8192, 4096x4096, 2048x2048, 1024x1024, 512x512, 256x256

うまく表示されない?

このファイルを QGIS で追加すると表示はされます。しかしズームレベルが小さなタイルほど広域に取得したにも関わらず、表示されるのは最大ズームレベルで取得した限られた範囲のみになります。

どうも( QGIS 内でラスタの読み込みに使われる) GDAL では範囲情報が存在しない場合、最大ズームレベルの範囲をもって、ラスタ全体の範囲と計算しているようで、その結果、範囲外の部分に関しては表示してくれないようです。

スクリーンショット 出典:国土地理院オルソ画像、 Landsat8 画像(GSI, TSIC, GEO Grid/AIST)、 Landsat8 画像(courtesy of the U.S. Geological Survey)、 海底地形(GEBCO)

範囲情報を付加した MBTiles と、付加していないため部分的にしか表示されていない MBTiles 。

そこで範囲等の情報を追加した MBTiles を作成します。 mb-util の場合範囲等のメタ情報は metadata.json という名称でファイルを(今回のディレクトリ配置だと) ort に追加します。( mb-util 以外のツールだとオプションなど別の方法が用意されている場合があります。また最悪、作成した MBTiles ファイルに対し SQLite として metadata テーブルにレコードを追加するという方法もあります。)

$ vim ort/metadata.json

$ tree ort | head -n 10
ort
|-- 10
|   |-- 900
|   |   |-- 396.jpg
|   |   |-- 397.jpg
|   |   |-- 398.jpg
|   |   |-- 399.jpg
|   |   |-- 400.jpg
|   |   |-- 401.jpg
|   |   |-- 402.jpg

$ tree ort | tail -n 10
|   `-- 457
|       |-- 198.jpg
|       |-- 199.jpg
|       |-- 200.jpg
|       |-- 201.jpg
|       |-- 202.jpg
|       `-- 203.jpg
`-- metadata.json

今回用意した metadata.json の中身はこんなかんじ。 bounds に範囲を指定します。わからない場合や、 0/0/0 などタイル地図で表現できる全域の場合は -180.0,-85.051129,180.0,85.051129 を指定すればよいでしょう。

{
    "name": "MBTiles demo",
    "type": "baselayer",
    "description": "demo",
    "version": "1",
    "format": "jpg",
    "bounds": "136.40625,34.307143856288036,142.03125,37.718590325588146",
    "minzoom": "8",
    "maxzoom": "17"
}

指定できる項目は MBTiles Specification に載っています。また、 mb-util のテストデータも参考になるかと思います。

この状態で(一旦古いファイルを消して)あらためて mb-util を実行すると metadata.json が自動的に読み込まれて範囲等の情報が設定されます。

$ rm ort.mbtils

$ mb-util --silent --image_format=jpg ort ort.mbtiles
53200 tiles inserted (1900 tiles/sec)

もういっかい gdalinfo にかけてみます。

$ gdalinfo ort.mbtiles 
Driver: MBTiles/MBTiles
Files: ort.mbtiles
Size is 524288, 393216
Coordinate System is:
PROJCS["WGS 84 / Pseudo-Mercator",
    GEOGCS["WGS 84",
        DATUM["WGS_1984",
            SPHEROID["WGS 84",6378137,298.257223563,
                AUTHORITY["EPSG","7030"]],
            AUTHORITY["EPSG","6326"]],
        PRIMEM["Greenwich",0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.0174532925199433,
            AUTHORITY["EPSG","9122"]],
        AUTHORITY["EPSG","4326"]],
    PROJECTION["Mercator_1SP"],
    PARAMETER["central_meridian",0],
    PARAMETER["scale_factor",1],
    PARAMETER["false_easting",0],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AXIS["X",EAST],
    AXIS["Y",NORTH],
    EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext  +no_defs"],
    AUTHORITY["EPSG","3857"]]
Origin = (15184667.968750000000000,4539746.093750000000000)
Pixel Size = (1.194328069686890,-1.194328069686890)
Metadata:
  name=MBTiles demo
  format=jpg
  bounds=136.40625,34.307143856288036,142.03125,37.718590325588146
  minzoom=8
  version=1
  maxzoom=17
  type=baselayer
  description=demo
Image Structure Metadata:
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (15184667.969, 4539746.094) (136d24'22.30"E, 37d43' 6.88"N)
Lower Left  (15184667.969, 4070117.188) (136d24'22.30"E, 34d18'25.67"N)
Upper Right (15810839.844, 4539746.094) (142d 1'52.29"E, 37d43' 6.88"N)
Lower Right (15810839.844, 4070117.188) (142d 1'52.29"E, 34d18'25.67"N)
Center      (15497753.906, 4304931.641) (139d13' 7.29"E, 36d 1'52.75"N)
Band 1 Block=256x256 Type=Byte, ColorInterp=Red
  Overviews: 262144x196608, 131072x98304, 65536x49152, 32768x24576, 16384x12288, 8192x6144, 4096x3072, 2048x1536, 1024x768
Band 2 Block=256x256 Type=Byte, ColorInterp=Green
  Overviews: 262144x196608, 131072x98304, 65536x49152, 32768x24576, 16384x12288, 8192x6144, 4096x3072, 2048x1536, 1024x768
Band 3 Block=256x256 Type=Byte, ColorInterp=Blue
  Overviews: 262144x196608, 131072x98304, 65536x49152, 32768x24576, 16384x12288, 8192x6144, 4096x3072, 2048x1536, 1024x768

また SQLite で metadata テーブルをみてみます。

$ sqlite3 ort.mbtiles 'SELECT * FROM metadata;'
name|MBTiles demo
format|jpg
bounds|136.40625,34.307143856288036,142.03125,37.718590325588146
minzoom|8
version|1
maxzoom|17
type|baselayer
description|demo
  1. [Qgis-user] QGIS Local XYZ Tiles / コミットログ fixes #16587

23
19
0

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
  3. You can use dark theme
What you can do with signing up
23
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?