Skip to content

Commit 8d0cc4a

Browse files
committed
[WIP] Add constant stride tiles
0 parents  commit 8d0cc4a

15 files changed

+1159
-0
lines changed

.gitignore

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Created by https://www.gitignore.io/api/python, and modified...
2+
3+
## Linux backup files
4+
*~
5+
6+
## Arhives
7+
*.zip
8+
9+
### Mac OS X stuff ###
10+
Desktop DF
11+
Desktop DB
12+
.Spotlight-V100
13+
.DS_Store
14+
.Trashes
15+
.com.apple.timemachine.supported
16+
.fseventsd
17+
.syncinfo
18+
.TemporaryItems
19+
report/
20+
21+
### Python ###
22+
# Byte-compiled / optimized / DLL files
23+
__pycache__/
24+
*.py[cod]
25+
*$py.class
26+
27+
# C extensions
28+
*.so
29+
30+
# Distribution / packaging
31+
.Python
32+
env/
33+
build/
34+
develop-eggs/
35+
dist/
36+
downloads/
37+
eggs/
38+
.eggs/
39+
lib/
40+
lib64/
41+
parts/
42+
sdist/
43+
var/
44+
*.egg-info/
45+
.installed.cfg
46+
*.egg
47+
48+
# PyInstaller
49+
# Usually these files are written by a python script from a template
50+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
51+
*.manifest
52+
MANIFEST
53+
*.spec
54+
55+
# Installer logs
56+
pip-log.txt
57+
pip-delete-this-directory.txt
58+
59+
# Unit test / coverage reports
60+
htmlcov/
61+
.tox/
62+
.coverage
63+
.coverage.*
64+
.cache
65+
nosetests.xml
66+
coverage.xml
67+
*,cover
68+
.hypothesis/
69+
70+
# Translations
71+
*.mo
72+
*.pot
73+
74+
# Sphinx documentation
75+
docs/_build/
76+
77+
# PyBuilder
78+
target/
79+
80+
# IPython Notebook
81+
.ipynb_checkpoints
82+
83+
# pyenv
84+
.python-version
85+
86+
# Idea
87+
.idea
88+
*.iml

.travis.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
sudo: required
2+
language: python
3+
matrix:
4+
include:
5+
- python: 3.5
6+
- python: 2.7
7+
8+
install:
9+
- pip install numpy
10+
- python setup.py install
11+
- pip install flake8 coveralls pytest-cov
12+
13+
# command to run tests
14+
script:
15+
- py.test --cov tiling --cov-report term-missing
16+
- flake8
17+
18+
after_success:
19+
- coveralls

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2017 vfdev
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Image Tiling Utils
2+
3+
Minimalistic set of image reader angostic tools to easily iterate over large images
4+
5+
**Example 1**
6+
7+
Let's iterate over a large image with overlapping and extracting always the
8+
same size tiles (in pixels). Let's assume the data access is provided with an example function
9+
```python
10+
def read_data(x, y, width, height, out_width=None, out_height=None):
11+
out_width = width if out_width is None else out_width
12+
out_height = height if out_height is None else out_height
13+
img.read(x, y, width, height, out_width, out_height)
14+
```
15+
Thus, overlapping tiles can be extracted as
16+
```python
17+
from tiling import ConstStrideTiles
18+
19+
20+
tiles = ConstStrideTiles(image_size=(500, 500), tile_size=(256, 256),
21+
stride=(100, 100))
22+
23+
print("Number of tiles: %i" % len(tiles))
24+
for extent, out_size in tiles:
25+
x, y, width, height = extent
26+
data = read_data(x, y, width, height,
27+
out_width=out_size[0],
28+
out_height=out_size[1])
29+
print("data.shape: {}".format(data.shape))
30+
31+
# Access a tile:
32+
i = len(tiles) // 2
33+
extent, out_size = tiles[i]
34+
```
35+
36+
![example_tiles](examples/example_tiles.png)
37+
38+
39+
## Installation:
40+
41+
Package installation is very simple
42+
```bash
43+
pip install git+https://github.com/vfdev-5/ImageTilingUtils.git
44+
```
45+
46+
## Examples
47+
48+
For more practical examples, see this [notebook](examples/example_const_stride_tiling.ipynb)

examples/example_const_stride_tiling.ipynb

Lines changed: 247 additions & 0 deletions
Large diffs are not rendered by default.

examples/example_tiles.png

337 KB
Loading

examples/test_image.jpg

237 KB
Loading

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
numpy

setup.cfg

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[pep8]
2+
max-line-length = 120
3+
4+
[flake8]
5+
max-line-length = 120
6+
ignore = F401,E402,F403
7+
exclude = venv

setup.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from codecs import open as codecs_open
2+
from setuptools import setup, find_packages
3+
from tiling import __version__
4+
5+
6+
# Get the long description from the relevant file
7+
with codecs_open('README.md', encoding='utf-8') as f:
8+
long_description = f.read()
9+
10+
11+
setup(
12+
name="tiling",
13+
version=__version__,
14+
description=u"Minimalistic set of image reader angostic tools to easily iterate over large images",
15+
long_description=long_description,
16+
author="vfdev-5",
17+
author_email="vfdev dot 5 at gmail dot com",
18+
packages=find_packages(exclude=['tests', 'examples']),
19+
install_requires=[
20+
'numpy',
21+
],
22+
license='MIT',
23+
test_suite="tests",
24+
extras_require={
25+
'tests': [
26+
'pytest',
27+
'pytest-cov'
28+
]
29+
}
30+
)

tests/test_const_size.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#
2+
# import unittest
3+
#
4+
# import numpy as np
5+
#
6+
#
7+
# from tiling import ConstSizeTiles
8+
#
9+
#
10+
# class TestConstSizeTiles(unittest.TestCase):
11+
#
12+
# def test__compute_number_of_tiles(self):
13+
# res = ConstSizeTiles._compute_number_of_tiles(32, 100, 0)
14+
# self.assertEqual(res, 4)
15+
# res = ConstSizeTiles._compute_number_of_tiles(32, 100, 7)
16+
# self.assertEqual(res, 4)
17+
# scale = 2.0
18+
# res = ConstSizeTiles._compute_number_of_tiles(3.0/scale, 10, 0)
19+
# self.assertEqual(res, 7)
20+
# res = ConstSizeTiles._compute_number_of_tiles(6.0/scale, 20, 1)
21+
# self.assertEqual(res, 10)
22+
#
23+
# def test__compute_float_overlapping(self):
24+
# res = ConstSizeTiles._compute_float_overlapping(32, 100, 4)
25+
# self.assertEqual(res, 28.0 / 3.0)
26+
#
27+
# def test__compute_tile_params(self):
28+
#
29+
# def _test(width, size, overlapping, scale):
30+
#
31+
# offset, = ConstSizeTiles._compute_tile_params()
32+
#
33+
#
34+
# for scale in [0.7, 0.89, 0.99, 1.0, 1.78, 2.12]:
35+
# for im_size in range(50, 100, 3):
36+
# for ext in range(12, int(im_size * scale) - 1):
37+
# for min_ovr in range(0, int(ext / scale) - 1):
38+
# _test(im_size, ext, min_ovr, scale)
39+
#
40+
# def test_no_scale(self):
41+
#
42+
# def _test(image_size, tile_size, min_overlapping):
43+
#
44+
# tiles = ConstSizeTiles(image_size=image_size, tile_size=tile_size,
45+
# min_overlapping=min_overlapping, scale=1.0)
46+
#
47+
# true_image = np.random.rand(image_size[1], image_size[0], 3)
48+
# tiled_image = np.zeros_like(true_image)
49+
# count = 0
50+
# for i, (x, y, width, height) in enumerate(tiles):
51+
# count += 1
52+
# self.assertTrue(0 <= x <= image_size[0] - tile_size[0],
53+
# "{}: 0 <= {} <= {}".format(i, x, image_size[0] - tile_size[0]))
54+
# self.assertTrue(0 <= y <= image_size[1] - tile_size[1],
55+
# "{}: 0 <= {} <= {}".format(i, y, image_size[1] - tile_size[1]))
56+
# self.assertEqual(width, tiles.tile_size[0])
57+
# self.assertEqual(height, tiles.tile_size[1])
58+
# self.assertTrue(x + width <= image_size[0],
59+
# "{}: 0 <= {} <= {}".format(i, x + width, image_size[0]))
60+
# self.assertTrue(y + height <= image_size[1],
61+
# "{}: 0 <= {} <= {}".format(i, y + height, image_size[1]))
62+
# tiled_image[y:y + height, x:x + width, :] = true_image[y:y + height, x:x + width, :]
63+
#
64+
# self.assertEqual(len(tiles), count)
65+
# err = float(np.sum(np.abs(tiled_image - true_image)))
66+
# self.assertLess(err, 1e-10, "Err : %f" % err)
67+
#
68+
# for o in [0, 5, 10, 15]:
69+
# _test((123, 234), (23, 34), o)
70+
# _test((256, 256), (32, 32), o)
71+
# _test((512, 512), (128, 128), o)
72+
#
73+
# def test_with_scale(self):
74+
#
75+
# def _test(image_size, tile_size, min_overlapping, scale):
76+
# tiles = ConstSizeTiles(image_size=image_size, tile_size=tile_size,
77+
# min_overlapping=min_overlapping, scale=scale)
78+
# count = 0
79+
# for i, (x, y, width, height) in enumerate(tiles):
80+
# count += 1
81+
# self.assertTrue(0 <= x <= image_size[0]*scale - tile_size[0],
82+
# "{}: 0 <= {} <= {}".format(i, x, image_size[0]*scale - tile_size[0]))
83+
# self.assertTrue(0 <= y <= image_size[1]*scale - tile_size[1],
84+
# "{}: 0 <= {} <= {}".format(i, y, image_size[1]*scale - tile_size[1]))
85+
# # self.assertEqual(width, tiles.tile_size[0])
86+
# # self.assertEqual(height, tiles.tile_size[1])
87+
# # self.assertTrue(x + width <= image_size[0],
88+
# # "{}: 0 <= {} <= {}".format(i, x + width, image_size[0]))
89+
# # self.assertTrue(y + height <= image_size[1],
90+
# # "{}: 0 <= {} <= {}".format(i, y + height, image_size[1]))
91+
#
92+
# self.assertEqual(len(tiles), count)
93+
#
94+
# for s in [0.7, 0.88, 0.97, 1.0, 1.23, 1.89, 2.34]:
95+
# _test((123, 234), (23, 34), 15, s)
96+
# _test((256, 256), (32, 32), 15, s)
97+
# _test((512, 512), (128, 128), 15, s)
98+
#
99+
# if __name__ == "__main__":
100+
# unittest.main()

0 commit comments

Comments
 (0)