Skip to content

Commit c89abce

Browse files
committed
Update example, change stride behaviour if scale is not 1.0
1 parent c9bab5e commit c89abce

File tree

5 files changed

+180
-51
lines changed

5 files changed

+180
-51
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ report/
2323
__pycache__/
2424
*.py[cod]
2525
*$py.class
26+
.pytest_cache
2627

2728
# C extensions
2829
*.so

examples/example_const_stride_tiling.ipynb

Lines changed: 115 additions & 14 deletions
Large diffs are not rendered by default.

tests/test_const_stride.py

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
import numpy as np
55

66

7-
from tiling import ConstStrideTiles
7+
from tiling import ConstStrideTiles, ceil_int
8+
9+
10+
DEBUG_MODE = False
811

912

1013
class TestConstStrideTiles(unittest.TestCase):
@@ -38,6 +41,12 @@ def test_wrong_args(self):
3841
with self.assertRaises(AssertionError):
3942
ConstStrideTiles((100, 120), (10, 10), stride=(10, -10))
4043

44+
def test_wrong_index(self):
45+
46+
with self.assertRaises(IndexError):
47+
tiles = ConstStrideTiles((100, 120), (10, 10), stride=(5, 5))
48+
tiles[10000]
49+
4150
def test_with_nodata(self):
4251

4352
def _test(im_size, ts, scale, stride, origin):
@@ -54,7 +63,7 @@ def _test(im_size, ts, scale, stride, origin):
5463

5564
debug_msg += "n={}\n".format(len(tiles))
5665
self.assertGreater(len(tiles), 0, debug_msg)
57-
self.assertLess(np.sqrt(len(tiles)), 1 + (im_size - origin) * 1.0 / stride, debug_msg)
66+
self.assertLess(np.sqrt(len(tiles)), 1 + (im_size - origin) * 1.0 / tiles.stride[0], debug_msg)
5867

5968
extent0, out_size0 = tiles[0]
6069
# Start at origin
@@ -71,9 +80,9 @@ def _test(im_size, ts, scale, stride, origin):
7180
self.assertEqual(d, (extent[2], extent[3]), debug_msg)
7281
# Check if constant stride
7382
if extent[0] - prev_extent[0] > 0:
74-
self.assertEqual(stride, extent[0] - prev_extent[0], debug_msg)
83+
self.assertEqual(tiles.stride[0], extent[0] - prev_extent[0], debug_msg)
7584
if extent[1] - prev_extent[1] > 0:
76-
self.assertEqual(stride, extent[1] - prev_extent[1], debug_msg)
85+
self.assertEqual(tiles.stride[1], extent[1] - prev_extent[1], debug_msg)
7786
else:
7887
self.assertEqual(0, extent[1] - prev_extent[1], debug_msg)
7988

@@ -85,15 +94,25 @@ def _test(im_size, ts, scale, stride, origin):
8594
debug_msg += "extent={}, out_size={}\n".format(extent, _)
8695
self.assertLess(extent[0], im_size, debug_msg)
8796
self.assertLess(extent[1], im_size, debug_msg)
88-
self.assertGreaterEqual(extent[0] + max(extent[2], stride), im_size, debug_msg)
89-
self.assertGreaterEqual(extent[1] + max(extent[3], stride), im_size, debug_msg)
90-
91-
for scale in [0.7, 0.89, 0.99, 1.0, 1.78, 2.12]:
92-
for im_size in range(100, 120):
93-
for ext in range(32, int(im_size * scale) - 1, 3):
94-
for stride in range(ext // 2, ext + 10, 3):
95-
for origin in range(-5, 5):
96-
_test(im_size, ext, scale, stride, origin)
97+
self.assertGreaterEqual(extent[0] + max(extent[2], tiles.stride[0]), im_size, debug_msg)
98+
self.assertGreaterEqual(extent[1] + max(extent[3], tiles.stride[1]), im_size, debug_msg)
99+
100+
if not DEBUG_MODE:
101+
for scale in [0.7, 0.89, 0.99, 1.0, 1.78, 2.12]:
102+
for im_size in range(100, 120):
103+
for ext in range(32, int(im_size * scale) - 1, 3):
104+
for stride in range(int(ext * scale) // 2, int(ext * scale) + 10, 5):
105+
for origin in range(-5, 5):
106+
_test(im_size, ext, scale, stride, origin)
107+
108+
def test_as_iterator(self):
109+
tiles = ConstStrideTiles((100, 120), (10, 10), stride=(5, 5))
110+
counter = 0
111+
for extent, out_size in tiles:
112+
_extent, _out_size = tiles[counter]
113+
self.assertEqual(extent, _extent)
114+
self.assertEqual(out_size, _out_size)
115+
counter += 1
97116

98117
def test_without_nodata(self):
99118

@@ -111,7 +130,7 @@ def _test(im_size, ts, scale, stride, origin):
111130

112131
debug_msg += "n={}\n".format(len(tiles))
113132
self.assertGreater(len(tiles), 0, debug_msg)
114-
self.assertLess(np.sqrt(len(tiles)), 1 + (im_size - origin) * 1.0 / stride, debug_msg)
133+
self.assertLess(np.sqrt(len(tiles)), 1 + (im_size - origin) * 1.0 / tiles.stride[0], debug_msg)
115134

116135
extent0, out_size0 = tiles[0]
117136
# Start at origin but should be positive
@@ -145,7 +164,7 @@ def _test(im_size, ts, scale, stride, origin):
145164
if prev_extent[2] == tiles.tile_extent[0]:
146165
# Check if constant stride
147166
if extent[0] - prev_extent[0] > 0:
148-
self.assertEqual(stride, extent[0] - prev_extent[0],
167+
self.assertEqual(tiles.stride[0], extent[0] - prev_extent[0],
149168
debug_msg + var_debug_msg)
150169

151170
# Check if output size is the same
@@ -154,16 +173,16 @@ def _test(im_size, ts, scale, stride, origin):
154173
if extent[0] - prev_extent[0] > 0:
155174
if prev_extent[0] == 0 and extent[0] + extent[2] < im_size:
156175
# Check stride between the ends of tiles
157-
self.assertEqual(stride, extent[0] + extent[2] - prev_extent[0] - prev_extent[2],
176+
self.assertEqual(tiles.stride[1], extent[0] + extent[2] - prev_extent[0] - prev_extent[2],
158177
debug_msg + var_debug_msg)
159178
elif prev_extent[0] > 0 and extent[0] + extent[2] == im_size:
160179
# Check stride between the starts of tiles
161-
self.assertEqual(stride, extent[0] - prev_extent[0],
180+
self.assertEqual(tiles.stride[0], extent[0] - prev_extent[0],
162181
debug_msg + var_debug_msg)
163182

164183
if prev_extent[3] == tiles.tile_extent[1]:
165184
if extent[1] - prev_extent[1] > 0:
166-
self.assertEqual(stride, extent[1] - prev_extent[1],
185+
self.assertEqual(tiles.stride[1], extent[1] - prev_extent[1],
167186
debug_msg + var_debug_msg)
168187
else:
169188
self.assertEqual(0, extent[1] - prev_extent[1], debug_msg + var_debug_msg)
@@ -172,33 +191,37 @@ def _test(im_size, ts, scale, stride, origin):
172191
if extent[1] - prev_extent[1] > 0:
173192
if prev_extent[1] == 0 and extent[1] + extent[3] < im_size:
174193
# Check stride between the ends of tiles
175-
self.assertEqual(stride, extent[1] + extent[3] - prev_extent[1] - prev_extent[3],
194+
self.assertEqual(tiles.stride[1], extent[1] + extent[3] - prev_extent[1] - prev_extent[3],
176195
debug_msg + var_debug_msg)
177196
elif prev_extent[1] > 0 and extent[1] + extent[3] == im_size:
178-
self.assertEqual(stride, extent[1] - prev_extent[1],
197+
self.assertEqual(tiles.stride[1], extent[1] - prev_extent[1],
179198
debug_msg + var_debug_msg)
180199

181200
# Check the last tile ends at the boundary or out side and starts inside
182201
extent, _ = tiles[-1]
183202
debug_msg += "extent={}, out_size={}\n".format(extent, _)
184203
self.assertLess(extent[0], im_size, debug_msg)
185204
self.assertLess(extent[1], im_size, debug_msg)
186-
if stride < tiles.tile_extent[0]:
205+
if tiles.stride[0] < tiles.tile_extent[0]:
187206
self.assertEqual(extent[0] + extent[2], im_size, debug_msg)
188207
else:
189208
self.assertLessEqual(extent[0] + extent[2], im_size, debug_msg)
190209

191-
if stride < tiles.tile_extent[1]:
210+
if tiles.stride[1] < tiles.tile_extent[1]:
192211
self.assertEqual(extent[1] + extent[3], im_size, debug_msg)
193212
else:
194213
self.assertLessEqual(extent[1] + extent[3], im_size, debug_msg)
195214

196-
for scale in [0.7, 0.89, 0.99, 1.0, 1.78, 2.12]:
197-
for im_size in range(100, 120):
198-
for ext in range(32, int(im_size * scale) - 1, 3):
199-
for stride in range(ext // 2, ext + 10, 3):
200-
for origin in range(-5, 5):
201-
_test(im_size, ext, scale, stride, origin)
215+
if not DEBUG_MODE:
216+
for scale in [0.7, 0.89, 0.99, 1.0, 1.78, 2.12]:
217+
for im_size in range(100, 120):
218+
for ext in range(32, int(im_size * scale) - 1, 3):
219+
for stride in range(int(ext * scale) // 2, int(ext * scale) + 10, 5):
220+
for origin in range(-5, 5):
221+
_test(im_size, ext, scale, stride, origin)
222+
223+
def test_int_ceil(self):
224+
self.assertEqual(2, ceil_int(1.789))
202225

203226

204227
if __name__ == "__main__":

tiling/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from __future__ import absolute_import
22
from abc import ABCMeta, abstractmethod
33

4+
import numpy as np
5+
6+
47
__version__ = '0.1'
58

69

@@ -38,7 +41,10 @@ def __init__(self, image_size, tile_size=(128, 128), scale=1.0):
3841
self.image_size = image_size
3942
self.tile_size = tile_size
4043
self.scale = float(scale)
41-
self.tile_extent = [d / self.scale for d in self.tile_size]
44+
# Apply floor to tile extent (tile size / scale)
45+
# Output size is then ceil(extent * scale), extent is <= tile_extent
46+
# ceil(extent * scale) < ceil(tile_extent * scale) = ceil(floor(tile_extent / scale) * scale)<= tile_size
47+
self.tile_extent = [int(np.floor(d / self.scale)) for d in self.tile_size]
4248
self._index = 0
4349
self._max_index = 0
4450

tiling/const_stride.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ def __init__(self, image_size, tile_size, stride=(1, 1), scale=1.0, origin=(0, 0
7171
Initialize tiles
7272
:param image_size: (list or tuple of int) input image size in pixels (width, height)
7373
:param tile_size: (list or tuple of int) output tile size in pixels (width, height)
74-
:param stride: (list or tuple of int) horisontal and vertical strides in pixels.
75-
Values need to be positive larger than 1 pixel.
74+
:param stride: (list or tuple of int) horizontal and vertical strides in pixels.
75+
Values need to be positive larger than 1 pixel. Stride value is impacted with scale and corresponds to a
76+
sliding over scaled image.
7677
:param scale: (float) Scaling applied to the input image parameters before extracting tile's extent
7778
:param origin: (list or tuple of int) point in pixels in the original image from where to start the tiling.
7879
Values can be positive or negative
@@ -84,13 +85,10 @@ def __init__(self, image_size, tile_size, stride=(1, 1), scale=1.0, origin=(0, 0
8485
"Argument stride should be a tuple/list (sx, sy)"
8586
if isinstance(stride, int):
8687
stride = (stride, stride)
88+
# Apply scale on the stride
89+
stride = [int(np.floor(s / self.scale)) for s in stride]
8790
for v in stride:
88-
assert v > 0, "Stride values should be larger than 1 pixel"
89-
90-
# Apply floor to tile extent (tile size / scale)
91-
# Output size is then ceil(extent * scale), extent is <= tile_extent
92-
# ceil(extent * scale) < ceil(tile_extent * scale) = ceil(floor(tile_extent / scale) * scale)<= tile_size
93-
self.tile_extent = [int(np.floor(e)) for e in self.tile_extent]
91+
assert v > 0, "Scaled stride values `floor(stride / scale)` should be larger than 1 pixel"
9492

9593
self.stride = stride
9694
self.origin = origin

0 commit comments

Comments
 (0)