プログラム日記φ(..)

おもにPython関係のプログラムメモ

Python Basemapで利用できる無料地図タイル(背景地図)一覧

前回、Python Basemapの背景地図を緯度・経度を指定してOpenStreetMapで描画してみましたが、

 

memomemokun.hateblo.jp

 

 

実は、Python Basemapには以下のような形でArcGIS REST APIを呼び出すだけで、

 

    map = Basemap(epsg=3857, 
            lat_ts=center_Lat, resolution='h',
            llcrnrlon=minLon, llcrnrlat=minLat, 
            urcrnrlon=maxLon, urcrnrlat=maxLat)


    map.arcgisimage(service='Ocean_Basemap',verbose=True,dpi=96, xpixels=1200)

 

簡単にArcGISの背景地図を描画するためのAPIが用意されているのですが、

NatGeo_World_Map(ArcGIS

NatGeo_World_Map

World_Imagery(ArcGIS

World_Imagery

World_Physical_Map(ArcGIS

World_Physical_Map

World_Shaded_Relief(ArcGIS

f:id:memomemokun:20181220181850j:plain

World_Street_Map(ArcGIS

World_Street_Map

Ocean_Basemap(ArcGIS

Ocean_Basemap

 

 

今回は、OpenStreetMapをはじめ、Wikimedia Maps、国土地理院などの無料で利用できる地図タイルの一覧を集めてみました。なお、使用規定などは各タイルで異なりますので、実際の使用の際にはそれぞれのサービス先でご確認ください。

 

JA:タイル - OpenStreetMap Wiki

 

 

タイル名:OpenStreetMap's Standard tile layer

タイル利用規約 - OpenStreetMap

https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
https://b.tile.openstreetmap.org/{z}/{x}/{y}.png
https://c.tile.openstreetmap.org/{z}/{x}/{y}.png

f:id:memomemokun:20181220154228j:plain

タイル名:Wikimedia Maps
https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png

Wikimedia Maps

タイル名:OpenCycleMap
https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png

OpenCycleMap

タイル名:Transport 
https://tile.thunderforest.com/transport/{z}/{x}/{y}.png

f:id:memomemokun:20181220160659j:plain

タイル名:Landscape
https://tile.thunderforest.com/landscape/{z}/{x}/{y}.pnglandscape 

タイル名:Outdoors
https://tile.thunderforest.com/outdoors/{z}/{x}/{y}.png

Outdoors

タイル名:Transport Dark
https://tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png

Transport Dark 

タイル名:SpinalMap
https://tile.thunderforest.com/spinal-map/{z}/{x}/{y}.png

Spinal Map

タイル名:Pioneer
https://tile.thunderforest.com/pioneer/{z}/{x}/{y}.png

Pioneer

タイル名:Mobile Atlas
https://tile.thunderforest.com/mobile-atlas/{z}/{x}/{y}.png

Mobile Atlas

タイル名:Neighbourhood
https://tile.thunderforest.com/mobile-atlas/{z}/{x}/{y}.png

f:id:memomemokun:20181220163401j:plain

タイル名:Humanitarian map style
http://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png

Humanitarian map style

タイル名:Toner
http://a.tile.stamen.com/toner/{z}/{x}/{y}.png

toner

タイル名:Terrain
http://a.tile.stamen.com/terrain/{z}/{x}/{y}.jpg

Terrain

タイル名:Watercolor
http://a.tile.stamen.com/terrain/{z}/{x}/{y}.jpg

Watercolor

タイル名:Transport map
http://www.openptmap.org/tiles/{z}/{x}/{y}.png

Transport map

 

以下国土地理院

タイル名:電子国土基本図
https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png

電子国土基本図

タイル名:土地利用図
https://cyberjapandata.gsi.go.jp/xyz/lum200k/{z}/{x}/{y}.png

土地利用図

タイル名:全国最新写真(シームレス)
https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg

全国最新写真(シームレス)

タイル名:色別標高図
https://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png

色別標高図

タイル名:陰影起伏図
https://cyberjapandata.gsi.go.jp/xyz/hillshademap/{z}/{x}/{y}.png

陰影起伏図

タイル名:傾斜量図
https://cyberjapandata.gsi.go.jp/xyz/slopemap/{z}/{x}/{y}.png

傾斜量図

 

などなど、国土地理院には他にも様々な地図タイルが存在するほか

地理院地図|地理院タイル一覧

 

他にも探せばまだまだ色々ありそうですね。

 

 

上のサンプル地図を描いた際のソースは以下

import requests
from StringIO import StringIO
import string
import pandas as pd
import numpy as np
import hjson

import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib import cm

from scipy import misc

from mpl_toolkits.basemap import Basemap
from osgeo import gdal

from math import pi
from math import tanh
from math import sin
from math import asin
from math import exp
from numpy import arctanh

from pyproj import Geod


# 1タイルのピクセル数
pix = 256

# 描画に使用する縦横の最小タイル数
Tiles = 2

g = Geod(ellps='WGS84')


# ピクセル座標を経緯度に変換する
def fromPointToLatLng(pixelLat,pixelLon, z):
    L = 85.05112878
    lon = 180 * ((pixelLon / 2.0**(z+7) ) - 1)
    lat = 180/pi * (asin(tanh(-pi/2**(z+7)*pixelLat + arctanh(sin(pi/180*L)))))
    return lat, lon



# 経緯度をピクセル座標に変換する
def fromLatLngToPoint(lat,lon, z):
    L = 85.05112878
    pointX = int( (2**(z+7)) * ((lon/180) + 1) )
    pointY = int( (2**(z+7)/pi) * (-1 * arctanh(sin(lat * pi/180)) + arctanh(sin(L * pi/180))) )
    return pointX, pointY    


# 経緯度をタイル座標に変換する
def fromLatLngToTile(lat,lon, z):
    pointX, pointY = fromLatLngToPoint(lat,lon, z)
    return pointX/pix, pointY/pix    


# 指定経緯度範囲が異なるタイルにまたがる最小のズームレベルとそのタイル座標を返す
def getTile(Tiles, minLat, minLon, maxLat, maxLon):
    
    for z in range(0,20):
        tileX1, tileY1 = fromLatLngToTile(minLat, minLon, z)
        tileX2, tileY2 = fromLatLngToTile(maxLat, maxLon, z)
        
        if tileX2 - tileX1 >= Tiles - 1  and tileY1 - tileY2 >= Tiles - 1: break

    return z, tileX1, tileY1, tileX2, tileY2 



# 地図画像データを読み込み各ピクセルをRGB値に変換した配列を返す
def load_imgColors(urlFormat, z, x1, y1, x2, y2):

    for x in range(x1, x2+1):
        for y in range(y2, y1+1):

            #地図画像データを読み込む
            url = urlFormat.format(z=z,x=x,y=y)
            print url
            response = requests.get(url)
            if response.status_code == 404:

                 #地図画像データが無い区画は白塗りにする
                 colors=np.ones((256, 256, 3), dtype=object)

            else:

                 #画像READ
                 img = misc.imread(StringIO(response.content))
                 
            # 画像タイルを縦に連結
            if y == y2:
                 im_v = img
            else:
                 #im_v = cv2.vconcat([im_v, img])
                 #im_v = np.append(im_v,img,0)
                 im_v = np.concatenate((im_v, img), axis = 0) #縦
                
        # 画像タイルを横に連結
        if x == x1:
            im = im_v
        else:
            #im = cv2.hconcat([im, im_v])
            #im = np.append(im,im_v,1)
            im = np.concatenate((im,im_v), axis = 1) #横
            
    return im



def makeMap(tileServer, center_Lat, center_Lon, minLat, minLon, maxLat, maxLon):

    # 指定経緯度範囲の最適ズームとタイル座標範囲を求める
    z, x1, y1, x2, y2  = getTile(Tiles, minLat, minLon, maxLat, maxLon)
    
    # タイルURL
    f=open('tiles.hjson')
    tiles = hjson.load(f)
    f.close()


    # OpenStreetMapのタイル画像のURLフォーマット
    urlFormat = tiles['tiles'][tileServer]
    print urlFormat

    # OpenStreetMapのタイル画像を読み込み連結して1枚の画像として返す
    imgColors = load_imgColors(urlFormat, z, x1, y1, x2, y2) 



    # 指定経緯度のピクセル座標を求める
    pointX1, pointY1 = fromLatLngToPoint(minLat, minLon, z)
    pointX2, pointY2 = fromLatLngToPoint(maxLat, maxLon, z)


    # 経緯度範囲に地図タイルをカット
    imgColors = imgColors[pointY2-y2*pix:pointY2-y2*pix+pointY1-pointY2, pointX1-x1*pix:pointX1-x1*pix+pointX2-pointX1, :]


    # 地図を作成する
    # 3857 球面メルカトル
    # 3395 回転楕円体メルカトル
    fig = plt.figure(figsize=(4,4))
    #plt.subplots_adjust(left=0, right=1, bottom=0, top=1)
    map = Basemap(epsg=3857, 
            lat_ts=center_Lat, resolution='h',
            llcrnrlon=minLon, llcrnrlat=minLat, 
            urcrnrlon=maxLon, urcrnrlat=maxLat)



    # 背景地図画像を描画
    mx0, my0 = map(minLon, minLat)
    mx1, my1 = map(maxLon, maxLat)

    extent = (mx0, mx1, my0, my1)
    plt.imshow(imgColors, vmin = 0, vmax = 255, extent = extent)


    # 経緯度線を描画
    map.drawparallels(np.arange(int(minLat), int(maxLat)+1, coordinateLineStep[z]), labels = [1,0,0,0], fontsize=8)
    map.drawmeridians(np.arange(int(minLon), int(maxLon)+1, coordinateLineStep[z]), labels = [0,0,0,1], fontsize=8)


    plt.savefig('1.jpg', dpi=72)
    plt.show()


# ズームレベルに応じた経緯度線のステップ
coordinateLineStep = {
    5 : 5.0,
    6 : 5.0,
    7 : 2.5,
    8 : 1.0,
    9 : 0.5,
   10 : 0.25,
   11 : 0.2,
   12 : 0.1,
   13 : 0.05,
   14 : 0.02,
   15 : 0.01,
   16 : 0.005,
   17 : 0.0025,
   18 : 0.002,
   19 : 0.002
}


if __name__ == '__main__':

# 東京駅 center_Lat = 35.681111 center_Lon = 139.766667 gap = 0.01 minLat = center_Lat - gap minLon = center_Lon - gap * 1.2 maxLat = center_Lat + gap maxLon = center_Lon + gap * 1.2 print "北緯%f 東経%f - 北緯%f 東経%f" % (minLat, minLon, maxLat, maxLon) makeMap('Neighbourhood', center_Lat, center_Lon, minLat, minLon, maxLat, maxLon)

 

タイルサーバー一覧(tiles.hjson)

{
  "tiles": {
    // OpenStreetMap's Standard tile layer
    "OSMA"          : "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png",
    "OSMB"          : "https://b.tile.openstreetmap.org/{z}/{x}/{y}.png",
    "OSMC"          : "https://c.tile.openstreetmap.org/{z}/{x}/{y}.png",

    // Wikimedia Maps
    "WikiMaps"      : "https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png",

    // OpenCycleMap
    "OpenCycleMap"  : "https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Transport
    "Transport"     : "https://tile.thunderforest.com/transport/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Landscape
    "Landscape"     : "https://tile.thunderforest.com/landscape/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Outdoors
    "Outdoors"      : "https://tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Transport Dark
    "TransportDark" : "https://tile.thunderforest.com/transport-dark/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Spinal Map
    "SpinalMap"     : "https://tile.thunderforest.com/spinal-map/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Pioneer
    "Pioneer"       : "https://tile.thunderforest.com/pioneer/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Mobile Atlas
    "MobileAtlas"   : "https://tile.thunderforest.com/mobile-atlas/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Neighbourhood
    "Neighbourhood" : "https://tile.thunderforest.com/neighbourhood/{z}/{x}/{y}.png?apikey=取得したAPIキー",

    // Humanitarian map style
    "HumanitarianMapA" : "http://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png",

    // Hillshading
    "Hillshading"   : "http://c.tiles.wmflabs.org/hillshading/{z}/{x}/{y}.png",

    // Black & White map
    "toner"         : "http://a.tile.stamen.com/toner/{z}/{x}/{y}.png",

    // Terrain
    "Terrain"       : "http://a.tile.stamen.com/terrain/{z}/{x}/{y}.jpg",

    // Watercolor
    "Watercolor"    : "http://a.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg",

    // Transport map
    "Transportmap"  : "http://www.openptmap.org/tiles/{z}/{x}/{y}.png",



    // 国土地理院
    // 電子国土基本図
    "std"           : "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png",

    // 土地利用図
    "lum200k"       : "https://cyberjapandata.gsi.go.jp/xyz/lum200k/{z}/{x}/{y}.png",

    // 全国最新写真(シームレス)
    "seamlessphoto" : "https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg",

    // 色別標高図
    "relief"        : "https://cyberjapandata.gsi.go.jp/xyz/relief/{z}/{x}/{y}.png",

    // 陰影起伏図
    "hillshademap"  : "https://cyberjapandata.gsi.go.jp/xyz/hillshademap/{z}/{x}/{y}.png",

    // 傾斜量図
    "slopemap"      : "https://cyberjapandata.gsi.go.jp/xyz/slopemap/{z}/{x}/{y}.png",


    "toner" : "http://a.tile.stamen.com/toner/{z}/{x}/{y}.png",
  }
}