-
-
Save cbeddow/28e5d043a46ba34ea91f7b66564307d4 to your computer and use it in GitHub Desktop.
| import mercantile, mapbox_vector_tile, requests, json | |
| from vt2geojson.tools import vt_bytes_to_geojson | |
| # define an empty geojson as output | |
| output= { "type": "FeatureCollection", "features": [] } | |
| # vector tile endpoints -- change this in the API request to reference the correct endpoint | |
| tile_points = 'mly_map_feature_point' | |
| tile_traffic_signs = 'mly_map_feature_traffic_sign' | |
| tile_coverage = 'mly1_public' | |
| # tile layer depends which vector tile endpoints: | |
| # 1. if map features or traffic signs, it will be "point" or "traffic_sign" respectively | |
| # 2. if looking for coverage, it will be "image" for points, "sequence" for lines, or "overview" for far zoom | |
| tile_layer = "point" | |
| # Mapillary access token -- user should provide their own | |
| access_token = 'MLY|XXX' | |
| # a bounding box in [west_lng,_south_lat,east_lng,north_lat] format | |
| west, south, east, north = [-80.13423442840576,25.77376933762778,-80.1264238357544,25.788608487732198] | |
| # list of values to filter for and keep -- update this if changing to traffic signs | |
| filter_values = ['object--support--utility-pole','object--street-light'] | |
| # get the list of tiles with x and y coordinates which intersect our bounding box | |
| # MUST be at zoom level 14 where the data is available, other zooms currently not supported | |
| tiles = list(mercantile.tiles(west, south, east, north, 14)) | |
| # loop through list of tiles to get tile z/x/y to plug in to Mapillary endpoints and make request | |
| for tile in tiles: | |
| tile_url = 'https://tiles.mapillary.com/maps/vtp/{}/2/{}/{}/{}?access_token={}'.format(tile_points,tile.z,tile.x,tile.y,access_token) | |
| response = requests.get(tile_url) | |
| data = vt_bytes_to_geojson(response.content, tile.x, tile.y, tile.z,layer=tile_layer) | |
| # filter for only features matching the values in filter list above | |
| filtered_data = [feature for feature in data['features'] if feature['properties']['value'] in filter_values] | |
| # check if features are inside bbox, and push to output geojson object if yes | |
| for feature in filtered_data: | |
| if (feature['geometry']['coordinates'][0] > east and feature['geometry']['coordinates'][0] < west)\ | |
| and (feature['geometry']['coordinates'][1] > south and feature['geometry']['coordinates'][1] < north): | |
| output['features'].append(feature) | |
| # save a local geojson with the filtered data | |
| with open('mydata.geojson', 'w') as f: | |
| json.dump(output, f) |
FYI I learned recently, that the number of image points in the vector tiles at https://tiles.mapillary.com are limited to about 2k per tile. Depending on the use case, it is not the right approach to fetch the data. The mapillary JSON api does have a 2k limit as well but there are plans to add pagination to those endpoints which will make it easier to fetch all data for a given reagion+filter.
@jyothir07 can you share the errors you get?
@tordans yes this may end up working better. I also have done it before where I split into like zoom 16 tiles, then get a tile bbox, and just continuous make a request to the JSON API with that bbox so it's always small but in theory it could still exceed 2000, though typically it's because of someone uploading 2000+ images with the same GPS point
@cbeddow the above code is not working. Can u please suggest