File size: 3,667 Bytes
b39a019
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# A set of functions to automatically annotate images for training a classification model of crosswalks. Requires a paid API key for the images but tile locations are free to access.
import overpy
from geopy.geocoders import Nominatim
import requests

MAPBOX_API_KEY = None  
crosswalk_images_folder = "crosswalk_images"

# Returns a list of crosswalk locations based on a given location geo-code, such as "Bloomsbury, London, UK"
# Geo-codes for a location may differ from the common name for a location, so check before putting in a location
def get_cross_walk_location(location_geo_code, bounds=0.001):
    over_api = overpy.Overpass()
    geo_locator = Nominatim(user_agent="crosswalk_locator")
    location = geo_locator.geocode(location_geo_code)

    if not location:
        raise ValueError("This location could not be geocoded - try an alternative name?.")

    geo_bounding_box = (location.latitude - bounds, location.longitude - bounds,
                        location.latitude + bounds, location.longitude + bounds)  # South, West, North, East

    query = f"""
    [out:json][timeout:25];
    (
      node["highway"="crossing"]({geo_bounding_box[0]},{geo_bounding_box[1]},{geo_bounding_box[2]},{geo_bounding_box[3]});
    );
    out body;
    """  # Should return all crosswalks within {bounds} longitude/ latitude points, in a square shape

    result = over_api.query(query)

    crosswalks = []
    for node in result.nodes:
        crosswalks.append((node.lat, node.lon))
    # Now we have a list of all the (latitude, longitude) pairs in that area,
    # and can use it access the images of those areas for annotation

    return crosswalks


# Gets the aerial image associated with a particular longitude and latitude.
# Uses the mapbox api, which is cheaper alternative to google maps static tiles API, but has lower res. images.
def get_mapbox_aerial_image(location, output_file_name, zoom=18, size="256x256", style="satellite-v9",
                            api_key=MAPBOX_API_KEY):
    longitude, latitude = location  # We split here, so it's easier to map this function onto a set of (lon, lat) coords
    base_url = f"https://api.mapbox.com/styles/v1/mapbox/{style}/static"

    coords = f"{latitude},{longitude},{zoom}"
    url = f"{base_url}/{coords}/{size}?access_token={api_key}"

    response = requests.get(url)

    if response.status_code == 200:
        with open(output_file_name, "wb") as file:
            file.write(response.content)
        print(f"Retrieved aerial image and saved it as {output_file_name}")

    else:
        print("Error, Error, Error!", response.status_code, response.text)


# Saves a list of crosswalk locations for the given geo-code to a folder, and returns the names of the saved files
# This function executes the setup required for training a classification model requiring 256x256 images as ours did
# If you want to change the model you are training, adjsut the get_mapbox_aerial_image function
def get_crosswalk_images(geo_code, folder=crosswalk_images_folder, file_extension="png"):
    crosswalk_image_files = []
    crosswalk_set = get_cross_walk_location(geo_code, bounds=0.1)
    for crosswalk in crosswalk_set:
        formatted_crosswalk = list(map(float, crosswalk))
        stored_file_name = str(formatted_crosswalk)
        try:
            get_mapbox_aerial_image(formatted_crosswalk,
                                    f"{folder}/{formatted_crosswalk}.{file_extension}")
            crosswalk_image_files.append(stored_file_name)
        except Exception as e:
            print(e)

    return crosswalk_image_files


#print(len(get_cross_walk_location("Bloomsbury, London, UK")))