-
-
Save sebastianleonte/617628973f88792cd097941220110233 to your computer and use it in GitHub Desktop.
A python script to download high resolution Google map images given a longitude, latitude and zoom level. (Works with Python 3)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# GoogleMapDownloader.py | |
# Created by Hayden Eskriett [http://eskriett.com] | |
# | |
# A script which when given a longitude, latitude and zoom level downloads a | |
# high resolution google map | |
# Find the associated blog post at: http://blog.eskriett.com/2013/07/19/downloading-google-maps/ | |
import urllib.request | |
from PIL import Image | |
import os | |
import math | |
class GoogleMapsLayers: | |
ROADMAP = "v" | |
TERRAIN = "p" | |
ALTERED_ROADMAP = "r" | |
SATELLITE = "s" | |
TERRAIN_ONLY = "t" | |
HYBRID = "y" | |
class GoogleMapDownloader: | |
""" | |
A class which generates high resolution google maps images given | |
a longitude, latitude and zoom level | |
""" | |
def __init__(self, lat, lng, zoom=12, layer=GoogleMapsLayers.ROADMAP): | |
""" | |
GoogleMapDownloader Constructor | |
Args: | |
lat: The latitude of the location required | |
lng: The longitude of the location required | |
zoom: The zoom level of the location required, ranges from 0 - 23 | |
defaults to 12 | |
""" | |
self._lat = lat | |
self._lng = lng | |
self._zoom = zoom | |
self._layer = layer | |
def getXY(self): | |
""" | |
Generates an X,Y tile coordinate based on the latitude, longitude | |
and zoom level | |
Returns: An X,Y tile coordinate | |
""" | |
tile_size = 256 | |
# Use a left shift to get the power of 2 | |
# i.e. a zoom level of 2 will have 2^2 = 4 tiles | |
numTiles = 1 << self._zoom | |
# Find the x_point given the longitude | |
point_x = (tile_size / 2 + self._lng * tile_size / 360.0) * numTiles // tile_size | |
# Convert the latitude to radians and take the sine | |
sin_y = math.sin(self._lat * (math.pi / 180.0)) | |
# Calulate the y coorindate | |
point_y = ((tile_size / 2) + 0.5 * math.log((1 + sin_y) / (1 - sin_y)) * -( | |
tile_size / (2 * math.pi))) * numTiles // tile_size | |
return int(point_x), int(point_y) | |
def generateImage(self, **kwargs): | |
""" | |
Generates an image by stitching a number of google map tiles together. | |
Args: | |
start_x: The top-left x-tile coordinate | |
start_y: The top-left y-tile coordinate | |
tile_width: The number of tiles wide the image should be - | |
defaults to 5 | |
tile_height: The number of tiles high the image should be - | |
defaults to 5 | |
Returns: | |
A high-resolution Goole Map image. | |
""" | |
start_x = kwargs.get('start_x', None) | |
start_y = kwargs.get('start_y', None) | |
tile_width = kwargs.get('tile_width', 5) | |
tile_height = kwargs.get('tile_height', 5) | |
# Check that we have x and y tile coordinates | |
if start_x == None or start_y == None: | |
start_x, start_y = self.getXY() | |
# Determine the size of the image | |
width, height = 256 * tile_width, 256 * tile_height | |
# Create a new image of the size require | |
map_img = Image.new('RGB', (width, height)) | |
for x in range(0, tile_width): | |
for y in range(0, tile_height): | |
url = f'https://mt0.google.com/vt?lyrs={self._layer}&x=' + str(start_x + x) + '&y=' + str(start_y + y) + '&z=' + str( | |
self._zoom) | |
current_tile = str(x) + '-' + str(y) | |
urllib.request.urlretrieve(url, current_tile) | |
im = Image.open(current_tile) | |
map_img.paste(im, (x * 256, y * 256)) | |
os.remove(current_tile) | |
return map_img | |
def main(): | |
# Create a new instance of GoogleMap Downloader | |
gmd = GoogleMapDownloader(51.5171, 0.1062, 13, GoogleMapsLayers.SATELLITE) | |
print("The tile coorindates are {}".format(gmd.getXY())) | |
try: | |
# Get the high resolution image | |
img = gmd.generateImage() | |
except IOError: | |
print("Could not generate the image - try adjusting the zoom level and checking your coordinates") | |
else: | |
# Save the image to disk | |
img.save("high_resolution_image.png") | |
print("The map has successfully been created") | |
if __name__ == '__main__': main() |
As a way of thank you for your help guys I want to share this version that works perfectly fine. Enjoy!
https://gist.github.com/Militoarg/e33a843ed4caed3a60561edb69d75f3d
Is there a way to get this to collect all the images at a given zoom level for an entire area?
Why does it always show for me - "Could not generate the image - try adjusting the zoom level and checking your coordinates"?
Hi there. @jackhirsh @Anjali1808
I've made an edited gist to download the image with the center of the given lat and long.
And also, the way of sending download request has changed. So images can be downloaded at any zoom and any size without a single problem in 2022.
https://gist.github.com/farhadinima75/c3e73f8d7d9f8d2e452063e611fb9a8c
Have fun :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi @acrete, I have added a new parameter for the class.
So you can simply do:
gmd = GoogleMapDownloader(51.5171, 0.1062, 13, GoogleMapsLayers.SATELLITE)
Or the layer you want!