Using Data Sources¶
Streetscapes can work with images from multiple sources. Currently included are: Mapillary, Kartaview, and Amsterdam Open Panorama.
It is also possible to use Global Streetscapes as a data source. However, as it is a fundamentally different type of dataset, a separate tutorial can be found here
NOTE: Make sure you have the appropriate API keys stored in your .env file.
First let's load the libraries and a workspace:
import warnings
warnings.filterwarnings("ignore")
import geopandas as gpd
import contextily
from PIL import Image
import numpy as np
from matplotlib import pyplot as plt
from streetscapes.sources import Mapillary, KartaView, AmsterdamPanorama
from streetscapes.streetview import SVWorkspace
ws = SVWorkspace("./Amsterdam", create=True)
mp = Mapillary(ws.env)
mp
Mapillary(root_dir='~/.cache/huggingface/assets/streetscapes/images/mapillary')
To test that the connection to our data sources work, we can get the image URL for an image:
mp_img_url = mp.get_image_url("4911230068985425")
mp_img_url
'https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/An--rrF4WlM05JH5SMiWxbdSXVWL0mFEymquJWW0EmSjaBemmKBcF8DRGqIe8akNayRiH0VTYunIfeHZlt2zAGA0sYkEkeWIUtnfp27cgiCen37fra1_v0gwTJFgNL5wTiUGkS7F56f_yLBZF1HqZg?stp=s2048x1536&edm=ALXxkZ8EAAAA&_nc_gid=tRbdW7qYYq0X5shRFZKzqQ&_nc_oc=Adkq7sMroKF2dZYGjwd90Vy8lKypHmU9SUEHP5gqwLGIVCHE_qxvwlQePNnu-8C4UOIzdVfTHVpZYuM7NdLV1_YK&ccb=10-5&oh=00_AfIS3HNjILFUkNkGg0xxkyr0hbenPw-1Q-YFarbRfKXC-Q&oe=68668C7C&_nc_sid=201bca'
Then we can fetch all of the image ids within a certain bounding box (bbox). You can define the bbox you want here.
bbox = [4.879990,52.368023,4.892499,52.374656]
df = mp.fetch_image_ids(bbox=bbox)
We can then take these ids and turn them to a geopandas dataframe and visualise them:
pdf = df.to_pandas()
gdf = gpd.GeoDataFrame(pdf, geometry=gpd.points_from_xy(pdf.lon, pdf.lat))
gdf.set_crs("EPSG:4326", allow_override=True, inplace=True)
gdf.head(5)
| id | altitude | atomic_scale | camera_type | captured_at | compass_angle | computed_altitude | computed_compass_angle | computed_geometry | computed_rotation | ... | make | model | thumb_256_url | thumb_1024_url | thumb_2048_url | thumb_original_url | sequence | width | lon | lat | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1917152201975344 | 50.157000 | 0.966447 | fisheye | 1683058662000 | 233.678855 | 2.200463 | 234.444802 | {'coordinates': [4.8890121741514, 52.368506077... | [0.80341789785712, 1.5825194278947, -1.6909058... | ... | GoPro | HERO7 Black | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | hEqPyRUmOBlvVJkbpzMg3d | 4000 | 4.889012 | 52.368506 |
| 1 | 2123857951153524 | 59.137000 | 0.958617 | fisheye | 1683058745000 | 302.127134 | 1.332355 | 300.733279 | {'coordinates': [4.8881621068794, 52.368739030... | [1.3840344032714, 0.87375049055148, -0.7304818... | ... | GoPro | HERO7 Black | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | hEqPyRUmOBlvVJkbpzMg3d | 4000 | 4.888162 | 52.368739 |
| 2 | 1905249926497728 | 84.565000 | 1.025931 | fisheye | 1683222429000 | 194.520986 | 1.624200 | 169.813657 | {'coordinates': [4.890530623151, 52.3729970104... | [0.30890820372818, -2.1646534079862, 2.1842481... | ... | GoPro | HERO7 Black | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | NhvZLRndBupJwiQCjV8D75 | 4000 | 4.890531 | 52.372997 |
| 3 | 3894119180663616 | 46.585438 | 1.001886 | equirectangular | 1471422392024 | 0.000000 | 2.186527 | 0.095146 | {'coordinates': [4.8821141861186, 52.370025099... | [1.5755633925048, 0.00038934569121215, 0.00299... | ... | Trimble | Trimble TMX | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | cjXHBMe3gjtnO1JxY0itMg | 8000 | 4.882114 | 52.370025 |
| 4 | 4026155874166112 | 50.994701 | 0.999110 | equirectangular | 1471238655950 | 0.000000 | 2.074441 | 1.326067 | {'coordinates': [4.8914778199576, 52.370309523... | [1.5715531011154, -0.0045901262039534, 0.03175... | ... | Trimble | Trimble TMX | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | https://scontent-ams4-1.xx.fbcdn.net/m1/v/t6/A... | a9oQejn_GKWe73KqIZrcSQ | 8000 | 4.891478 | 52.370310 |
5 rows × 24 columns
ax = gdf.plot(column='uuid', color='red', markersize=3, figsize=(6, 6), alpha=0.5)
contextily.add_basemap(ax, crs=gdf.crs, source=contextily.providers.nlmaps.standaard)
Finally, we can download an image:
image = gdf.iloc[0]
filename = mp.download_image(image.id, image.thumb_1024_url, overwrite=True)
Image.open(filename)
For multiple images, the process is similar:
df_sample = gdf[:5] # First 5 images
image_ids = df_sample.id # Column in the dataframe with id
urls = df_sample.thumb_1024_url # Specify the type of url
paths = mp.download_images(image_ids, urls)
paths
Downloading images | mapillary | Done: 100%|██████████| 5/5 [00:02<00:00, 2.00it/s]
[PosixPath('/Users/clairedonnelly/.cache/huggingface/assets/streetscapes/images/mapillary/1917152201975344.jpeg'),
PosixPath('/Users/clairedonnelly/.cache/huggingface/assets/streetscapes/images/mapillary/2123857951153524.jpeg'),
PosixPath('/Users/clairedonnelly/.cache/huggingface/assets/streetscapes/images/mapillary/1905249926497728.jpeg'),
PosixPath('/Users/clairedonnelly/.cache/huggingface/assets/streetscapes/images/mapillary/3894119180663616.jpeg'),
PosixPath('/Users/clairedonnelly/.cache/huggingface/assets/streetscapes/images/mapillary/4026155874166112.jpeg')]
KartaView¶
KartaView, formerly OpenStreetView and OpenStreetCam is a project to crowdsource street-level photographs to improve OpenStreetMap. It works quite similarly to Mapillary but unlike Mapillary, it also provides some open source code of its web and mobile applications. The coverage of KartaView is a little bit more restricted with fewer images depending on the region.
Let's load the data source into the workspace environment:
kv = KartaView(ws.env)
kv
KartaView(root_dir='~/.cache/huggingface/assets/streetscapes/images/kartaview')
To test that the connection to our data sources work, we can get the image URL for an image:
kv_img_url = kv.get_image_url("1208524")
kv_img_url
Unlike Mapillary, KartaView downloads images within a certain radius of a co-ordinate. Here we have chosen a 500 m radius:
df = kv.fetch_image_ids(52.3723032, 4.8877233, 500)
We can then take these ids and turn them to a geopandas dataframe and visualise them:
pdf = df.to_pandas()
gdf = gpd.GeoDataFrame(pdf, geometry=gpd.points_from_xy(pdf.lng, pdf.lat))
gdf.set_crs("EPSG:4326", allow_override=True, inplace=True)
gdf.head(5)
| id | sequence_id | sequence_index | orgCode | lat | lng | field_of_view | name | lth_name | th_name | ... | match_lat | match_lng | way_id | shot_date | heading | headers | gps_accuracy | projection | username | geometry | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1605307145 | 6072841 | 5218 | CMNT | 52.369301 | 4.892199 | None | storage13/files/photo/2022/9/10/proc/6072841_5... | storage13/files/photo/2022/9/10/lth/6072841_58... | storage13/files/photo/2022/9/10/th/6072841_58a... | ... | None | None | None | 2022-08-20 09:29:56.000 | 15.18 | None | None | PLANE | madflex | POINT (4.8922 52.3693) |
| 1 | 1605307401 | 6072841 | 5233 | CMNT | 52.370079 | 4.892559 | None | storage13/files/photo/2022/9/10/proc/6072841_6... | storage13/files/photo/2022/9/10/lth/6072841_6b... | storage13/files/photo/2022/9/10/th/6072841_6b4... | ... | 52.370079040527344 | 4.892553806304932 | 7371712 | 2022-08-20 09:30:12.000 | 190.80 | None | None | PLANE | madflex | POINT (4.89256 52.37008) |
| 2 | 1605307657 | 6072841 | 5247 | CMNT | 52.370702 | 4.892724 | None | storage13/files/photo/2022/9/10/proc/6072841_6... | storage13/files/photo/2022/9/10/lth/6072841_64... | storage13/files/photo/2022/9/10/th/6072841_64d... | ... | 52.370700836181640 | 4.892742156982422 | 7371712 | 2022-08-20 09:30:26.000 | 13.72 | None | None | PLANE | madflex | POINT (4.89272 52.3707) |
| 3 | 1605307913 | 6072841 | 5265 | CMNT | 52.371511 | 4.892822 | None | storage13/files/photo/2022/9/10/proc/6072841_b... | storage13/files/photo/2022/9/10/lth/6072841_bc... | storage13/files/photo/2022/9/10/th/6072841_bc3... | ... | 52.371509552001950 | 4.892897129058838 | 7371712 | 2022-08-20 09:30:44.000 | 5.43 | None | None | PLANE | madflex | POINT (4.89282 52.37151) |
| 4 | 1605308169 | 6072841 | 5280 | CMNT | 52.372230 | 4.892816 | None | storage13/files/photo/2022/9/10/proc/6072841_d... | storage13/files/photo/2022/9/10/lth/6072841_d3... | storage13/files/photo/2022/9/10/th/6072841_d32... | ... | 52.372226715087890 | 4.892929077148438 | 7371712 | 2022-08-20 09:30:59.000 | 3.38 | None | None | PLANE | madflex | POINT (4.89282 52.37223) |
5 rows × 23 columns
ax = gdf.plot(column='uuid', color='red', markersize=3, figsize=(6, 6), alpha=0.5)
contextily.add_basemap(ax, crs=gdf.crs, source=contextily.providers.nlmaps.standaard)
Finally, we can download an image:
image = gdf.iloc[0]
url = kv.get_image_url(image)
filename = kv.download_image(image.id, url, overwrite=True)
Image.open(filename)