欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

[GIS 开发] 批量下载和拼接地图图块(Python)

最编程 2024-05-07 08:37:05
...
#***********************************************************************
# Purpose: python下载和拼接地图瓦片(高德和google地图)
# Author: 爱看书的小沐
# Date: 2022-03-04
# Languages: Python
# Platform: Python 3.9.7 win64
# ***********************************************************************
# -*-coding:utf-8 -*-

import os, sys
import math
import urllib.request
import PIL.Image as Image
from PIL import ImageDraw, ImageFont

import urllib
import time
import random
import datetime

def downloadImage(img_url, fname, mylog):
try:
urllib.request.urlretrieve(img_url,filename=fname)
except IOError as e:
print("--", fname, "->", e)
print(img_url, file=mylog)
except Exception as e:
print("--", fname, "->", e)
print(img_url, file=mylog)

def downloadImage2(img_url, fname, mylog):
user_agent = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1'
headers = { 'User-Agent' : user_agent }
try:
req = urllib.request.Request(img_url, headers=headers)
response = urllib.request.urlopen(req)
bytes = response.read()
except Exception as e:
print("--", fname, "->", e)
print(img_url, file=mylog)
sys.exit(1)

if bytes.startswith(b"<html>"):
print("-- forbidden", fname)
print(img_url, file=mylog)
sys.exit(1)

print("-- saving", fname)

f = open(fname,'wb')
f.write(bytes)
f.close()

time.sleep(1 + random.random())

def num2deg(xtile, ytile, zoom):
n = 2.0 ** zoom
lon_deg = xtile / n * 360.0 - 180.0
lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
lat_deg = math.degrees(lat_rad)
return (lat_deg, lon_deg)

def getImageUrl(x, y, zoom):
#高德瓦片,wprd03想必是和谷歌一样,有多个服务器提供服务。测试下来可以取到01 到 04。
img_url = 'https://wprd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&style=6'.format(x=x, y=y, z=zoom)
#img_url = 'https://wprd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=7<ype=0'.format(x=x, y=y, z=zoom)
return img_url

def getAndCheckImageFilePath(file_path, x, y, zoom):
path = file_path + "/" + str(zoom) + "/" + str(x)
if not os.path.exists(path):
os.makedirs(path)
return getImageFilePath(file_path, x, y, zoom)

def getImageFilePath(file_path, x, y, zoom):
return file_path + "/" + str(zoom) + "/" + str(x) + '/'+ str(y)+'.png'

#################################################################
# 图片拼接
#################################################################

def mergeAllImageToOne(file_path, zoom, params):
xmin = params[0]
ymin = params[1]
xmax = xmin + params[2]
ymax = ymin + params[3]
mw = 256
toImage = Image.new('RGB', (256*(xmax-xmin), 256*(ymax-ymin)) )

for x in range(xmin, xmax):
for y in range(ymin, ymax):

fname = getImageFilePath(file_path, x, y, zoom)
fromImage = Image.open(fname)
fromImage = fromImage.convert('RGB')
draw = ImageDraw.Draw(fromImage)

# 添加每个瓦片的文字信息
fontSize = 18
setFont = ImageFont.truetype('C:/windows/fonts/arial.ttf', fontSize)
fillColor = "#ffff00"
pos = num2deg(x, y, zoom)
text = 'Tile: ' + str(x)+ "," + str(y)+ "," + str(zoom)
text2 = 'Lat: %.6f'%pos[0]
text3 = 'Lon: %.6f'%pos[1]
draw.text((1,1), text,font=setFont,fill=fillColor)
draw.text((1,1+fontSize), text2,font=setFont,fill=fillColor)
draw.text((1,1+2*fontSize), text3,font=setFont,fill=fillColor)

# 添加每个瓦片的边框线条
draw.rectangle([0, 0, mw-1, mw-1], fill=None, outline='red', width=1)

# 将每个瓦片的小图绘制到大图里面。
toImage.paste(fromImage, ((x-xmin) * mw, (y-ymin) * mw))

toImage.save(file_path + '/' + str(zoom) +'/preview.png' )
toImage.close()

#################################################################
# 图片拼接
#################################################################

def downloadMapAllImage(file_path, zoom, params):
xmin = params[0]
ymin = params[1]
xmax = xmin + params[2]
ymax = ymin + params[3]

if not os.path.exists(file_path):
os.makedirs(file_path)
mylog = open(file_path + '/err.log', mode = 'a',encoding='utf-8')

for x in range(xmin, xmax):
for y in range(ymin, ymax):

img_url = getImageUrl(x, y, zoom)
print(img_url)

img_savepath = getAndCheckImageFilePath(file_path, x, y, zoom)
print(img_savepath)

if not os.path.exists(img_savepath):
downloadImage(img_url, img_savepath, mylog)
#downloadImage2(img_url, img_savepath, mylog)

mylog.close()

#################################################################

if __name__ == '__main__':
starttime = datetime.datetime.now()
file_path='d:/maps'

# (1) 全球地图
zoom = 4
params = [0, 0, pow(2, zoom), pow(2, zoom)]

# (2) 中国地图
# zoom = 9
# params = [354, 165, 106, 91]

# (3) 局部地图
# zoom = 18
# params = [215768, 99253, 4, 4]

downloadMapAllImage(file_path, zoom, params)
mergeAllImageToOne(file_path, zoom, params)

endtime = datetime.datetime.now()
print("ok", (endtime - starttime).seconds)