Skip to content

Commit c8bcf5c

Browse files
committed
updates to new classes
1 parent 6a829c7 commit c8bcf5c

File tree

1 file changed

+84
-24
lines changed

1 file changed

+84
-24
lines changed

labelbox/data/annotation_types/data/tiled_image.py

Lines changed: 84 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
from enum import Enum
2-
from typing import Optional, List
2+
from typing import Optional, List, Any, Dict
33

44
from pydantic import BaseModel, validator
5+
import numpy as np
6+
from pyproj import Transformer, transform
57

68
from ..geometry import Point
79
from .base_data import BaseData
10+
from .raster import RasterData
811

912

1013
class EPSG(Enum):
@@ -15,9 +18,9 @@ class EPSG(Enum):
1518
>>> epsg = EPSG()
1619
"""
1720
SIMPLEPIXEL = 1
18-
EPSG4326 = 2
19-
EPSG3857 = 3
20-
EPSG3395 = 4
21+
EPSG4326 = 4326
22+
EPSG3857 = 3857
23+
EPSG3395 = 3395
2124

2225

2326
class TiledBounds(BaseModel):
@@ -71,38 +74,95 @@ class TiledImageData(BaseData):
7174
""" Represents tiled imagery
7275
7376
If specified version is 2, converts bounds from [lng,lat] to [lat,lng]
77+
78+
Requires the following args:
79+
tile_layer: TileLayer
80+
tile_bounds: TiledBounds
81+
zoom_levels: List[int]
82+
Optional args:
83+
max_native_zoom: int = None
84+
tile_size: Optional[int]
85+
version: int = 2
86+
alternative_layers: List[TileLayer]
7487
"""
7588
tile_layer: TileLayer
76-
alternative_layers: List[TileLayer]
7789
tile_bounds: TiledBounds
90+
alternative_layers: List[TileLayer] = None
7891
zoom_levels: List[int]
79-
max_native_zoom: int = zoom_levels[1]
92+
max_native_zoom: int = None
8093
tile_size: Optional[int]
8194
version: int = 2
8295

83-
# @property #TODO
84-
# def value(self):
85-
# Return self._as_raster(self.min_zoom).value()
86-
87-
# def _as_raster(zoom): #TODO
88-
# stitched together tiles as a RasterData object
89-
# Return result
90-
91-
@property
92-
def tile_layer_url(self):
93-
return self.tile_layer.url
94-
95-
@property
96-
def bounds(self):
97-
return self.tile_bounds.bounds
98-
96+
def __post_init__(self):
97+
if self.max_native_zoom is None:
98+
self.max_native_zoom = zoom_levels[1]
99+
100+
#TODO: look further into Matt's code and how to reference the monorepo ?
101+
def _as_raster(zoom):
102+
# stitched together tiles as a RasterData object
103+
# TileData.get_image(target_hw) ← we will be using this from Matt's precomputed embeddings
104+
# more info found here: https://github.com/Labelbox/python-monorepo/blob/baac09cb89e083209644c9bdf1bc3d7cb218f147/services/precomputed_embeddings/precomputed_embeddings/tiled.py
105+
image_as_np = None
106+
return RasterData(arr=image_as_np)
107+
108+
@property #TODO
109+
def value(self) -> np.ndarray:
110+
return self._as_raster(self.min_zoom).value()
111+
112+
#TODO: maybe not necessary, can remove
113+
# @property
114+
# def tile_layer_url(self) -> str:
115+
# return self.tile_layer.url
116+
117+
#TODO: maybe not necessary, can remove
118+
# @property
119+
# def bounds(self) -> List[Point]:
120+
# return self.tile_bounds.bounds
121+
122+
#TODO: wondering to keep this or not since epsg may be something of interest
123+
# and they dont want to go through TiledImageData.tile_bounds.epsg?
124+
# then can call TiledimageData.epsg
99125
@property
100-
def epsg(self):
126+
def epsg(self) -> EPSG:
101127
return self.tile_bounds.epsg
102128

103129
@validator('zoom_levels')
104130
def validate_zooms(cls, zoom_levels):
105131
if len(zoom_levels) != 2:
106132
raise AssertionError(
107-
f"zoom_levels should only contain min and max, found {len(zoom_levels)}"
133+
f"zoom_levels should contain 2 values [min,max], found {len(zoom_levels)}"
134+
)
135+
136+
137+
#TODO: we will need to update the [data] package to also require pyproj
138+
class EPSGTransformer(BaseModel):
139+
"""Transformer class between different EPSG's. Useful when wanting to project
140+
in different formats.
141+
142+
Requires as input a Point object.
143+
"""
144+
class Config:
145+
arbitrary_types_allowed = True
146+
147+
transform_function: Transformer = None
148+
149+
def is_simple(self, epsg: EPSG) -> bool:
150+
return epsg == EPSG.SIMPLEPIXEL
151+
152+
def geo_and_geo(self, src_epsg: EPSG, tgt_epsg: EPSG) -> None:
153+
if self.is_simple(src_epsg) or self.is_simple(tgt_epsg):
154+
raise Exception(
155+
f"Cannot be used for Simple transformations. Found {src_epsg} and {tgt_epsg}"
108156
)
157+
self.transform_function = Transformer.from_crs(src_epsg.value,
158+
tgt_epsg.value)
159+
160+
def geo_and_pixel(self, src_epsg, geojson):
161+
pass
162+
163+
def __call__(self, point: Point):
164+
if self.transform_function is not None:
165+
res = self.transform_function.transform(point.x, point.y)
166+
return Point(x=res[0], y=res[1])
167+
else:
168+
raise Exception("No transformation has been set.")

0 commit comments

Comments
 (0)