streetlevel.lookaround: Apple Look Around
Support for Apple Look Around.
Note that, unlike with the other providers, this library does not automatically stitch the panoramas since 1) Look Around does not serve one image broken up into tiles, but six faces which form a sort-of-but-not-really cubemap, and 2) its image format, HEIC, is somewhat inconvenient to work with. A function to create an equirectangular image out of the panorama faces is available, but not exactly fast, so it is recommended to display the faces unmodified.
Panoramas can be rendered by creating a spherical rectangle (meaning a rectangle on the surface of a sphere) for each face, centered on
phi=0, theta=0. fov_s is the phi size (width), fov_h is the theta size (height), and cy is an additional offset
which must be subtracted from phi. The resulting geometry for the face is then rotated by the specified Euler angles. (The API
returns several other parameters as well, but they do not appear to be in use.)
Finding panoramas
- get_coverage_tile(tile_x, tile_y, session=None)
Fetches Look Around panoramas on a specific map tile. Coordinates are in Slippy Map aka XYZ format at zoom level 17.
- Parameters:
tile_x (int) – X coordinate of the tile.
tile_y (int) – Y coordinate of the tile.
session (Session | None) – (optional) A requests session.
- Returns:
A CoverageTile object holding a list of panoramas and the last modification date of the tile.
- Return type:
Usage sample:
from streetlevel import lookaround tile = lookaround.get_coverage_tile(109775, 56716) first = tile.panos[0] print(f""" Got {len(tile.panos)} panoramas. Here's one of them: ID: {first.id}\t\tBuild ID: {first.build_id} Latitude: {first.lat}\tLongitude: {first.lon} Capture date: {first.date} """)
- async get_coverage_tile_async(tile_x, tile_y, session)
- Parameters:
tile_x (int)
tile_y (int)
session (ClientSession)
- Return type:
- get_coverage_tile_by_latlon(lat, lon, session=None)
Same as
get_coverage_tile, but for fetching the tile on which a point is located.
- Parameters:
lat (float) – Latitude of the point.
lon (float) – Longitude of the point.
session (Session | None) – (optional) A requests session.
- Returns:
A CoverageTile object holding a list of panoramas and the last modification date of the tile. Note that the list is not sorted - the panoramas are in the order in which they were returned by the API.
- Return type:
Usage sample:
from streetlevel import lookaround tile = lookaround.get_coverage_tile_by_latlon(23.53239040648735, 121.5068719584602) first = tile.panos[0] print(f""" Got {len(tile.panos)} panoramas. Here's one of them: ID: {first.id}\t\tBuild ID: {first.build_id} Latitude: {first.lat}\tLongitude: {first.lon} Capture date: {first.date} """)
- async get_coverage_tile_by_latlon_async(lat, lon, session)
- Parameters:
lat (float)
lon (float)
session (ClientSession)
- Return type:
Downloading panoramas
- get_panorama_face(pano, face, zoom, auth, session=None)
Fetches one face of a panorama.
Images are in HEIC format. Since HEIC is poorly supported across the board, decoding the image is left to the user of the library.
- Parameters:
pano (LookaroundPanorama | Tuple[int, int]) – The panorama, or its ID.
face (Face | int) – Index of the face.
zoom (int) – The zoom level. 0 is highest, 7 is lowest.
auth (Authenticator) – An Authenticator object.
session (Session | None) – (optional) A requests session.
- Returns:
The HEIC file containing the face, as
bytes.- Return type:
bytes
Usage sample:
from streetlevel import lookaround tile = lookaround.get_coverage_tile_by_latlon(46.52943, 10.45544) auth = lookaround.Authenticator() faces = [] zoom = 0 for face_idx in range(0, 6): face = lookaround.get_panorama_face(tile.panos[0], face_idx, zoom, auth) faces.append(face)
- download_panorama_face(pano, path, face, zoom, auth, session=None)
Downloads one face of a panorama to a file.
- Parameters:
pano (LookaroundPanorama | Tuple[int, int]) – The panorama, or its ID.
path (str) – Output path.
face (Face | int) – Index of the face.
zoom (int) – The zoom level. 0 is highest, 7 is lowest.
auth (Authenticator) – An Authenticator object.
session (Session | None) – (optional) A requests session.
- Return type:
None
Usage sample:
from streetlevel import lookaround tile = lookaround.get_coverage_tile_by_latlon(46.52943, 10.45544) auth = lookaround.Authenticator() zoom = 0 for face_idx in range(0, 6): lookaround.download_panorama_face(tile.panos[0], f"{tile.panos[0].id}_{face_idx}_{zoom}.heic", face_idx, zoom, auth)
Data classes and Enums
- class CameraMetadata(lens_projection: 'LensProjection', position: 'OrientedPosition')
- Parameters:
lens_projection (LensProjection)
position (OrientedPosition)
- lens_projection: LensProjection
- position: OrientedPosition
- class CoverageTile(x, y, panos, last_modified)
Represents a coverage tile.
- Parameters:
x (int)
y (int)
panos (List[LookaroundPanorama])
last_modified (datetime)
- x: int
The X coordinate of the tile at z=17.
- y: int
The Y coordinate of the tile at z=17.
- panos: List[LookaroundPanorama]
Panoramas on this tile.
- last_modified: datetime
The time the tile was last changed. This happens whenever footage is published or removed, new blurs are applied, or (I assume) PoIs are updated.
- class CoverageType(value)
Coverage type of a Look Around panorama.
- CAR = 2
The panorama was taken by a car.
- BACKPACK = 3
The panorama was taken by a backpack.
- class Face(value)
Face indices of a Look Around panorama.
- BACK = 0
- LEFT = 1
- FRONT = 2
- RIGHT = 3
- TOP = 4
- BOTTOM = 5
- class LookaroundPanorama(id, build_id, lat, lon, coverage_type=None, date=None, has_blurs=None, raw_orientation=None, raw_altitude=None, tile=None, camera_metadata=None, _heading=None, _pitch=None, _roll=None, _elevation=None, _altitude=None)
Metadata of a Look Around panorama.
- Parameters:
id (int)
build_id (int)
lat (float)
lon (float)
coverage_type (CoverageType)
date (datetime)
has_blurs (bool)
raw_orientation (Tuple[int, int, int])
raw_altitude (int)
tile (Tuple[int, int, int])
camera_metadata (List[CameraMetadata])
_heading (float)
_pitch (float)
_roll (float)
_elevation (float)
_altitude (float)
- build_id: int
An additional parameter required for requesting the imagery. Each time Apple publishes or updates a set of panoramas, they are assigned a build ID to act as a revision number.
- camera_metadata: List[CameraMetadata] = None
Properties needed for rendering the panorama faces.
- coverage_type: CoverageType = None
Whether the coverage was taken by car or by backpack.
- date: datetime = None
Capture date and time of the panorama (in UTC, not local time).
- property elevation: float
Elevation at the capture location in meters.
- has_blurs: bool = None
Whether something in this panorama, typically a building, has been blurred.
- property heading: float
Heading in radians, where 0° is north, 90° is west, 180° is south, 270° is east.
- id: int
The pano ID.
- lat: float
Latitude of the panorama’s location.
- lon: float
Longitude of the panorama’s location.
- permalink(heading=0.0, pitch=0.0, radians=False)
Creates a link which will open a panorama at this location in Apple Maps. Linking to a specific panorama by its ID does not appear to be possible.
On non-Apple devices, the link will redirect to Google Maps.
- Parameters:
heading (float) – (optional) Initial heading of the viewport. Defaults to 0°.
pitch (float) – (optional) Initial pitch of the viewport. Defaults to 0°.
radians (bool) – (optional) Whether angles are in radians. Defaults to False.
self (LookaroundPanorama)
- Returns:
An Apple Maps URL which will open the closest panorama to this location.
- Return type:
str
- property pitch: float
Pitch offset for upright correction of the panorama, in radians.
- raw_altitude: int = None
The raw altitude value returned by the API.
- raw_orientation: Tuple[int, int, int] = None
The raw yaw, pitch, and roll values returned by the API.
- property roll: float
Roll offset for upright correction of the panorama, in radians.
- tile: Tuple[int, int, int] = None
The tile this panorama is located on.
- class LensProjection(fov_s: 'float', fov_h: 'float', k2: 'float', k3: 'float', k4: 'float', cx: 'float', cy: 'float', lx: 'float', ly: 'float')
- Parameters:
fov_s (float)
fov_h (float)
k2 (float)
k3 (float)
k4 (float)
cx (float)
cy (float)
lx (float)
ly (float)
- fov_s: float
Phi size of the panorama face.
- fov_h: float
Theta size of the panorama face.
- k2: float
- k3: float
- k4: float
- cx: float
Theta offset.
- cy: float
Phi offset.
- lx: float
- ly: float
Reprojection
- to_equirectangular(faces, camera_metadata)
Reprojects the faces of a Look Around panorama to a single equirectangular image. The center of the returned image is the inverse direction of travel (meaning you’re looking backwards).
Note that this method is very slow. On my machine, a full resolution image (zoom 0, 16384×8192) takes about 50 seconds to convert.
PyTorch must be installed to call this function. Due to its size and differing CUDA versions, it is not installed automatically alongside the other dependencies of this library.
- Parameters:
faces (List[Image]) – The faces of the panorama as PIL images.
camera_metadata (List[CameraMetadata]) – The camera metadata of the faces.
- Returns:
The reprojected panorama as PIL image.
- Return type:
Image
Usage sample:
from streetlevel import lookaround panos = lookaround.get_coverage_tile_by_latlon(54.583244, 9.820249) pano = next(p for p in panos if p.id == 6651337760361848285) auth = lookaround.Authenticator() faces = [] zoom = 2 for face_idx in range(0, 6): face_heic = lookaround.get_panorama_face(pano, face_idx, zoom, auth) # Convert the HEIC file to a PIL image here. # This step is left to the user so that you can choose whichever # library performs best on your machine. faces.append(face) result = lookaround.to_equirectangular(faces, pano.camera_metadata) result.save(f"{pano.id}_{zoom}.jpg", options={"quality": 100})
Authentication
- class Authenticator
Various requests to internal Apple Maps endpoints, such as Look Around imagery, must be dynamically authenticated with a session ID and access key. This class provides this functionality.
- authenticate_url(url)
Appends authentication parameters to a URL.
- Parameters:
url (str) – An unauthenticated URL.
- Returns:
An authenticated URL.
- Return type:
str
Miscellaneous
- build_permalink(lat, lon, heading=0.0, pitch=0.0, radians=False)
Creates a link which will open a panorama at the given location in Apple Maps. Linking to a specific panorama by its ID does not appear to be possible.
On non-Apple devices, the link will redirect to Google Maps.
- Parameters:
lat (float) – Latitude of the panorama’s location.
lon (float) – Longitude of the panorama’s location.
heading (float) – (optional) Initial heading of the viewport. Defaults to 0°.
pitch (float) – (optional) Initial pitch of the viewport. Defaults to 0°.
radians (bool) – (optional) Whether angles are in radians. Defaults to False.
- Returns:
An Apple Maps URL which will open the closest panorama to the given location.
- Return type:
str