Skip to content

Commit 50e7083

Browse files
committed
nit updates
1 parent 83aebf1 commit 50e7083

File tree

4 files changed

+46
-66
lines changed

4 files changed

+46
-66
lines changed

labelbox/data/annotation_types/data/tiled_image.py

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import requests
99
import numpy as np
1010

11-
from retry import retry
11+
from google.api_core import retry
1212
from PIL import Image
1313
from pyproj import Transformer
1414
from pygeotile.point import Point as PygeoPoint
@@ -27,8 +27,6 @@
2727
logging.basicConfig(level=logging.INFO)
2828
logger = logging.getLogger(__name__)
2929

30-
#TODO: need to add pyproj, pygeotile, retry to dependencies
31-
3230

3331
class EPSG(Enum):
3432
""" Provides the EPSG for tiled image assets that are currently supported.
@@ -147,14 +145,10 @@ def as_raster_data(self,
147145
if self.tile_bounds.epsg == EPSG.SIMPLEPIXEL:
148146
xstart, ystart, xend, yend = self._get_simple_image_params(zoom)
149147

150-
# Currently our editor doesn't support anything other than 3857.
151-
# Since the user provided projection is ignored by the editor
152-
# we will ignore it here and assume that the projection is 3857.
153148
elif self.tile_bounds.epsg == EPSG.EPSG3857:
154149
xstart, ystart, xend, yend = self._get_3857_image_params(zoom)
155150
else:
156-
raise ValueError(
157-
f"Unsupported epsg found...{self.tile_bounds.epsg}")
151+
raise ValueError(f"Unsupported epsg found: {self.tile_bounds.epsg}")
158152

159153
self._validate_num_tiles(xstart, ystart, xend, yend, max_tiles)
160154

@@ -244,47 +238,33 @@ def _fetch_image_for_bounds(self,
244238
245239
If a tile cannot be fetched, a padding of expected tile size is instead added.
246240
"""
247-
tiles = {}
241+
248242
if multithread:
243+
tiles = {}
249244
with ThreadPoolExecutor(
250245
max_workers=TILE_DOWNLOAD_CONCURRENCY) as exc:
251246
for x in range(x_tile_start, x_tile_end + 1):
252247
for y in range(y_tile_start, y_tile_end + 1):
253248
tiles[(x, y)] = exc.submit(self._fetch_tile, x, y, zoom)
254249

255-
rows = []
256-
for y in range(y_tile_start, y_tile_end + 1):
257-
row = []
258-
for x in range(x_tile_start, x_tile_end + 1):
259-
try:
260-
row.append(tiles[(x, y)].result())
261-
except:
262-
row.append(
263-
np.zeros(shape=(self.tile_size, self.tile_size, 3),
264-
dtype=np.uint8))
265-
rows.append(np.hstack(row))
266-
#no multithreading
267-
else:
250+
rows = []
251+
for y in range(y_tile_start, y_tile_end + 1):
252+
row = []
268253
for x in range(x_tile_start, x_tile_end + 1):
269-
for y in range(y_tile_start, y_tile_end + 1):
270-
try:
271-
tiles[(x, y)] = self._fetch_tile(x, y, zoom)
272-
except:
273-
tiles[(x, y)] = np.zeros(shape=(self.tile_size,
274-
self.tile_size, 3),
275-
dtype=np.uint8)
276-
277-
rows = []
278-
for y in range(y_tile_start, y_tile_end + 1):
279-
rows.append(
280-
np.hstack([
281-
tiles[(x, y)]
282-
for x in range(x_tile_start, x_tile_end + 1)
283-
]))
254+
try:
255+
if multithread:
256+
row.append(tiles[(x, y)].result())
257+
else:
258+
row.append(self._fetch_tile(x, y, zoom))
259+
except:
260+
row.append(
261+
np.zeros(shape=(self.tile_size, self.tile_size, 3),
262+
dtype=np.uint8))
263+
rows.append(np.hstack(row))
284264

285265
return np.vstack(rows)
286266

287-
@retry(delay=1, tries=5, backoff=2, max_delay=8)
267+
@retry.Retry(initial=1, maximum=16, multiplier=2)
288268
def _fetch_tile(self, x: int, y: int, z: int) -> np.ndarray:
289269
"""
290270
Fetches the image and returns an np array.
@@ -293,9 +273,7 @@ def _fetch_tile(self, x: int, y: int, z: int) -> np.ndarray:
293273
data.raise_for_status()
294274
decoded = np.array(Image.open(BytesIO(data.content)))[..., :3]
295275
if decoded.shape[:2] != (self.tile_size, self.tile_size):
296-
logger.warning(
297-
f"Unexpected tile size {decoded.shape}. Results aren't guarenteed to be correct."
298-
)
276+
logger.warning(f"Unexpected tile size {decoded.shape}.")
299277
return decoded
300278

301279
def _crop_to_bounds(

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ PILLOW
1212
opencv-python
1313
typeguard
1414
imagesize
15+
pyproj
16+
pygeotile

setup.py

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,14 @@
2222
install_requires=[
2323
"backoff==1.10.0",
2424
"backports-datetime-fromisoformat==1.0.0; python_version < '3.7.0'",
25-
"dataclasses==0.7; python_version < '3.7.0'",
26-
"ndjson==0.3.1",
27-
"requests>=2.22.0",
28-
"google-api-core>=1.22.1",
29-
"pydantic>=1.8,<2.0",
30-
"tqdm",
25+
"dataclasses==0.7; python_version < '3.7.0'", "ndjson==0.3.1",
26+
"requests>=2.22.0", "google-api-core>=1.22.1", "pydantic>=1.8,<2.0",
27+
"tqdm"
3128
],
3229
extras_require={
3330
'data': [
3431
"shapely", "geojson", "numpy", "rasterio", "PILLOW",
35-
"opencv-python", "typeguard", "imagesize"
32+
"opencv-python", "typeguard", "imagesize", "pyproj", "pygeotile"
3633
],
3734
},
3835
classifiers=[
Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import pytest
2-
from labelbox.data.annotation_types.data import tiled_image
32
from labelbox.data.annotation_types.geometry.point import Point
43
from labelbox.data.annotation_types.data.tiled_image import (EPSG, TiledBounds,
54
TileLayer,
65
TiledImageData)
76
from pydantic import ValidationError
8-
from retry import retry
97

108

119
@pytest.mark.parametrize("epsg", list(EPSG))
@@ -16,7 +14,7 @@ def test_epsg(epsg):
1614
@pytest.mark.parametrize("epsg", list(EPSG))
1715
def test_tiled_bounds(epsg):
1816
top_left = Point(x=0, y=0)
19-
bottom_right = Point(x=100, y=100)
17+
bottom_right = Point(x=50, y=50)
2018

2119
tiled_bounds = TiledBounds(epsg=epsg, bounds=[top_left, bottom_right])
2220
assert isinstance(tiled_bounds, TiledBounds)
@@ -31,18 +29,23 @@ def test_tiled_bounds_same(epsg):
3129
bounds=[single_bound, single_bound])
3230

3331

34-
# def test_create_tiled_image_data():
35-
# bounds_points = [Point(x=0, y=0), Point(x=5, y=5)]
36-
# url = "https://labelbox.s3-us-west-2.amazonaws.com/pathology/{z}/{x}/{y}.png"
37-
# zoom_levels = [1, 10]
38-
39-
# tile_layer = TileLayer(url=url, name="slippy map tile")
40-
# tile_bounds = TiledBounds(epsg=EPSG.EPSG4326, bounds=bounds_points)
41-
# tiled_image_data = TiledImageData(tile_layer=tile_layer,
42-
# tile_bounds=tile_bounds,
43-
# zoom_levels=zoom_levels,
44-
# version=2)
45-
# assert isinstance(tiled_image_data, TiledImageData)
46-
# assert tiled_image_data.tile_bounds == bounds_points
47-
# assert tiled_image_data.tile_layer.url == url
48-
# assert tiled_image_data.zoom_levels == zoom_levels
32+
def test_create_tiled_image_data():
33+
bounds_points = [Point(x=0, y=0), Point(x=5, y=5)]
34+
url = "https://labelbox.s3-us-west-2.amazonaws.com/pathology/{z}/{x}/{y}.png"
35+
zoom_levels = (1, 10)
36+
37+
tile_layer = TileLayer(url=url, name="slippy map tile")
38+
tile_bounds = TiledBounds(epsg=EPSG.EPSG4326, bounds=bounds_points)
39+
tiled_image_data = TiledImageData(tile_layer=tile_layer,
40+
tile_bounds=tile_bounds,
41+
zoom_levels=zoom_levels,
42+
version=2)
43+
assert isinstance(tiled_image_data, TiledImageData)
44+
assert tiled_image_data.tile_bounds.bounds == bounds_points
45+
assert tiled_image_data.tile_layer.url == url
46+
assert tiled_image_data.zoom_levels == zoom_levels
47+
48+
49+
#TODO: create a test from 4326->SIMPLE->3857->4326
50+
def test_epsg_projections():
51+
pass

0 commit comments

Comments
 (0)