Skip to content

Instantly share code, notes, and snippets.

@esemwy
Created June 10, 2015 12:10
Show Gist options
  • Save esemwy/75b9ef7fd042d4947745 to your computer and use it in GitHub Desktop.
Save esemwy/75b9ef7fd042d4947745 to your computer and use it in GitHub Desktop.
Create 360 degree mosaic from Google Maps Street View data.
#!/usr/bin/env python
# Based on http://stackoverflow.com/questions/17555345/creating-a-montage-of-pictures-in-python
from sys import path
# needed for some package installs, harmless otherwise
path.append('/usr/local/lib/python2.7/site-packages')
import argparse
import os
import sys
from time import strftime
import requests
from io import BytesIO
PIL_INSTALLED = True
try:
from PIL import Image
from PIL import ImageDraw
except:
PIL_INSTALLED = False
from subprocess import call
import re
# parameters
row_size = 13
extension = '.png'
url = 'http://cbk0.google.com/cbk'
def generate_montage(files):
images = [ Image.open(file) for file in files ]
width = 0
height = 0
i = 0
sum_x = max_y = 0
width = max(image.size[1] for image in images)*row_size
height = max(image.size[0] for image in images)*len(images)/row_size
montage = Image.new(mode='RGBA', size=(width, height), color=(0,0,0,0))
draw = ImageDraw.Draw(montage)
offset_x = offset_y = 0
i = 0
max_y = 0
max_x = 0
offset_x = 0
for image in images:
montage.paste(image, (offset_x, offset_y))
max_x = max(max_x, offset_x+image.size[0])
if i % row_size == row_size-1:
offset_y += max_y
max_y = 0
offset_x = 0
else:
offset_x += image.size[0]
max_y = max(max_y, image.size[1])
i += 1
if i % row_size:
offset_y += max_y
filename = strftime("Montage %Y-%m-%d at %H.%M.%S"+extension)
# montage = montage.crop((0, 0, max_x, offset_y))
montage.save(filename)
def generate_montage_magick(files):
filenames = []
for i, file in enumerate(files):
name = '/tmp/cbk_{:02d}.jpg'.format(i)
open(name,'w').write(file.read())
filenames.append(name)
filename = strftime("Montage %Y-%m-%d at %H.%M.%S"+extension)
params = ['montage', '-geometry', '+0+0', '-tile', '13x7']+filenames+[filename]
print ' '.join(params)
call(params)
def extractPanoid( mapsLink ):
fields = mapsLink.split( "!" )
for f in fields:
if f.startswith('1s'):
return f[2:102]
return None
def downloadAll(mapsLink):
panoid = extractPanoid( mapsLink )
files = []
for y in xrange(0,7):
for x in xrange(0,13):
payload = {
'output' : 'tile',
'panoid' : panoid,
'zoom' : 4,
'x' : x,
'y' : y
}
r = requests.get(url, params=payload)
files.append(BytesIO(r.content))
try:
if len(files) > 1:
if PIL_INSTALLED:
generate_montage(files)
else:
generate_montage_magick(files)
except Exception as e:
print e
def readFile(html):
pat = re.compile(r'src="([^"]+)"')
with open(html,'r') as fd:
text = fd.read()
files = [open(os.path.join(os.path.dirname(html),m),'r') for m in re.findall(pat,text)]
try:
if len(files) > 1:
if PIL_INSTALLED:
generate_montage(files)
else:
generate_montage_magick(files)
except Exception as e:
print e
def main():
parser = argparse.ArgumentParser(description='Create Google Maps Mosaic.')
parser.add_argument('input', metavar='file-or-url', type=str,
help='File or URL')
parser.add_argument('--url', action='store_true', help='Use URL to download tiles')
args = parser.parse_args()
if args.url:
downloadAll(args.input)
else:
readFile(args.input)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment