visit
Have you ever seen a photo on Google Street View and thought"Damn, this would make for a nice wallpaper"? Well, I have. So I started a project to get Street View photos at random and turning them into wallpapers.
First problem is that Street View photos are cluttered with interface controls. I soon found out it's a problem that had been already tackled by another kind of people that need clean Street view pictures: journalists. Karl Hodge listed all the that should be hidden to get a clean picture. Andy Dickinson went one step further and created a Chrome to hide all those elements at once with a single click.Now, if I only wanted a couple of pictures from Street View, that extension would have sufficed. But I get tired of my wallpapers very quickly. My perfect day starts with a good wallpaper that I have never seen before. I needed a solution that could automatically generate many photos to save me from boredom.The good news for anyone who wants to automate Google Maps stuff is that there are APIs for that. They aren't free of charge, but Google gives free monthly credit to developers. That was more than enough for my small project.In my case, the perfect API seemed to be the . It has a function to return a photo from a given location. The call is as simple as . Problem is that the maximum size allowed is 640x640. Not ideal for a wallpaper.
After some research, I found another API called . It has a that allows web developers to include Street View panoramas on their sites. Google even provides a that was almost exactly what I was looking for.<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Clean Street View</title>
<style>
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
function initPano() {
// Note: constructed panorama objects have visible: true
// set by default.
const urlParams = new URLSearchParams(window.location.search);
const latitude = parseFloat(urlParams.get('lat'));
const longitude = parseFloat(urlParams.get('lng'));
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('map'), {
position: { lat: latitude, lng: longitude },
addressControl: false,
linksControl: false,
panControl: false,
fullscreenControl: false,
zoomControl: false,
enableCloseButton: false,
showRoadLabels: false
});
}
</script>
<script async defer src="//maps.googleapis.com/maps/api/js?key=ADD_YOUR_KEY_HERE&callback=initPano"></script>
</body>
</html>
The page gets the query string parameters
lat
and lng
and displays a full screen clean Street View panorama of the location. This page alone can be used as an alternative to the Clean Street View extension, with the advantage of having the street names removed, but the drawback of needing a Google API key (which, by the way, demands a credit card).At this point, I needed to somehow save that picture so I could use it later. And here is the part I apologize to all JavaScript developers out there. Although I could create the page (basically because almost all the code was in the Google's demo), I couldn't do the screenshot part. To be fair, I even tried. I resorted to Python.In Python, one way to render a page that runs some JavaScript is using . It's a library that allows for task automation on browsers. Originally created for web application testing, Selenium can be used for a variety of tasks, including web scraping, boring stuff automation and taking screenshots from pages :-)
I won't get into the details of how Selenium work. But If you have never used it, it will open a browser and do whatever your code says. In my case, all I needed to do was to open my custom page with some values in the parameters in a fullscreen browser, take a screenshot and save the image file somewhere. Here is a sample code.import time
from selenium import webdriver
# Fenway Park's coordinates
lat = 42.345573
lng = -71.098326
# Webdriver setup
options = webdriver.chrome.options.Options()
options.add_argument("--log-level=3") # minimal logging
options.add_argument("--headless") # hide browser's GUI
options.add_argument("--window-size=1920,1080")
driver = webdriver.Chrome("chromedriver.exe", options=options)
# Get and save image
driver.get(page_path)
time.sleep(1) # wait for image to load
driver.save_screenshot(str(lat) + "_" + str(lng) + ".png")
import sys
import glob
import time
import csv
import requests
import matplotlib.path as mplt_path
from selenium import webdriver
from os import path
from random import uniform
# fmt: off
API_URL = "//maps.googleapis.com/maps/api/streetview/metadata" # Not billed
API_KEY = "ADD_YOUR_KEY_HERE" # get a key at //developers.google.com/maps/documentation/streetview/get-api-key
WIDTH = 1920
HEIGHT = 1080
# fmt: on
if getattr(sys, "frozen", False):
script_path = path.dirname(sys.executable)
else:
script_path = path.dirname(path.abspath(__file__))
# Setup on land polygons
paths = []
for poly_file in glob.glob("polygons\*.csv"):
with open(poly_file, newline="") as f:
data = list(csv.reader(f))
paths.append(mplt_path.Path(data, closed=True))
# Get a valid Street View coordinate
status = False
while status != "OK":
onland = False
# Pick a random point that is on land
while not onland:
lat, lng = uniform(-180, 180), uniform(-90, 90)
for p in paths:
if p.contains_point((lat, lng)):
onland = True
break
# Check if random point has a Street View panorama
locstring = str(lat) + "," + str(lng)
r = requests.get(API_URL + "?key=" + API_KEY + "&location=" + locstring)
status = r.json()["status"]
# Webdriver setup
options = webdriver.chrome.options.Options()
options.add_argument("--log-level=3") # minimal logging
options.add_argument("--window-size=" + str(WIDTH) + "," + str(HEIGHT))
options.add_argument("--headless")
driver = webdriver.Chrome("chromedriver.exe", options=options)
page_path = path.join(
script_path, "clean_street_view.html?lat=" + str(lat) + "&lng=" + str(lng)
)
driver.get(page_path)
time.sleep(1) # wait for image to load
driver.save_screenshot("images\\" + str(lat) + "_" + str(lng) + ".png")