Giter Club home page Giter Club logo

tiler's Introduction

tiler_baby_logo tiler

Tiler teaser image

CI Code style: black Coverage status PyPI version

Github repository | Github issues | Documentation


⚠️ Please note: work in progress, things will change and/or break! ⚠️


This python package provides consistent and user-friendly functions for tiling/patching and subsequent merging of NumPy arrays.

Such tiling is often required for various heavy image-processing tasks such as semantic segmentation in deep learning, especially in domains where images do not fit into GPU memory (e.g., hyperspectral satellite images, whole slide images, videos, tomography data).

Please see Quick start section.
If you want to use tiler interactively, I highly recommend napari and napari-tiler plugin.

Features

  • N-dimensional
  • Optional in-place tiling
  • Optional channel dimension (dimension that is not tiled)
  • Optional tile batching
  • Tile overlapping
  • Access individual tiles with an iterator or a getter
  • Tile merging, with optional window functions/tapering

Quick start

You can find more examples in examples.
For more Tiler and Merger functionality, please check documentation.

import numpy as np
from tiler import Tiler, Merger

image = np.random.random((3, 1920, 1080))

# Setup tiling parameters
tiler = Tiler(data_shape=image.shape,
              tile_shape=(3, 250, 250),
              channel_dimension=0)

## Access tiles:
# 1. with an iterator
for tile_id, tile in tiler.iterate(image):
   print(f'Tile {tile_id} out of {len(tiler)} tiles.')
# 1b. the iterator can also be accessed through __call__
for tile_id, tile in tiler(image):
   print(f'Tile {tile_id} out of {len(tiler)} tiles.')
# 2. individually
tile_3 = tiler.get_tile(image, 3)
# 3. in batches
tiles_in_batches = [batch for _, batch in tiler(image, batch_size=10)]

# Setup merging parameters
merger = Merger(tiler)

## Merge tiles:
# 1. one by one
for tile_id, tile in tiler(image):
   merger.add(tile_id, some_processing_fn(tile))
# 2. in batches
merger.reset()
for batch_id, batch in tiler(image, batch_size=10):
   merger.add_batch(batch_id, 10, batch)

# Final merging: applies tapering and optional unpadding
final_image = merger.merge(unpad=True)  # (3, 1920, 1080)

Installation

The latest release is available through pip:

pip install tiler

Alternatively, you can clone the repository and install it manually:

git clone [email protected]:the-lay/tiler.git
cd tiler
pip install

If you are planning to contribute, please take a look at the contribution instructions.

Motivation & other packages

I work on semantic segmentation of patched 3D data and I often found myself reusing tiling functions that I wrote for the previous projects. No existing libraries listed below fit my use case, so that's why I wrote this library.

However, other libraries/examples might fit you better:

Moreover, some related approaches have been described in the literature:

Frequently asked questions

This section is a work in progress.

How do I create tiles with less dimensions than the data array?

Tiler expects tile_shape to have less than or the same number of elements as data_shape. If tile_shape has less elements than data_shape, tile_shape will be prepended with ones to match the size of data_shape.
For example, if you want to get 2d tiles out from 3d array you can initialize Tiler like this: Tiler(data_shape=(128,128,128), tile_shape=(128, 128)) and it will be equivalent to Tiler(data_shape=(128,128,128), tile_shape=(1, 128, 128)).

tiler's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

tiler's Issues

[IDEA] Tiling PyTorch tensors

Is your feature request related to a problem? Please describe.
Pytorch's API is very numpy-like, but has differences in underlying memory model. It might be interesting to take a look what's happening there and whether it is possible to tile pytorch tensors too.

[IDEA] Automatically calculated tile shape for specified mosaic shape

Is your feature request related to a problem? Please describe.
It would be cool to be able to create Tiler object that automatically calculates tile shape to obtain specific mosaic (collection of tiles) shape.

Describe the solution you'd like
I imagine it as a class method for Tiler class, that accepts all standard 'init' arguments, except tile_shape.

Describe alternatives you've considered
Currently something similar is already calculated in the script that generates teaser image, in misc/teaser. Once this feature is done, change the teaser script accordingly.

[IDEA] Return all tiles

Something like tiler.get_all(axis=0) that will join all tiles along a new axis.
That would support all tiling modes except 'irregular'.

[IDEA] Add more examples

Is your feature request related to a problem? Please describe.
There should be more practical examples on how to use Tiler.

[IDEA] PyTorch Dataset Tiler

Is your feature request related to a problem? Please describe.
As a pytorch user, it would be great to have a convenience TiledDataset class that subclasses standard pytorch Dataset.

Describe alternatives you've considered
It's already possible, but you have to write a lot of boilerplate.

[IDEA] Calculate Tiler overhead and create benchmarking scripts

Is your feature request related to a problem? Please describe.
It is unclear how big is Tiler/Merger overhead, both in performance and memory usage. We should also create benchmarking scripts to compare how Tiler stands with other tiling/merging tools mentioned in the readme.

P.S. Baseline should probably be numpy's sliding window trick, numpy.lib.stride_tricks.sliding_window_view. It's returning just views

window function normalization

Hiho,
thank you for this awesome project. I played a bit around with it and tried all tiling and windowing options, but it seems to me that in the stitched image the windowing functions do not sum up to 1 (=100%), but to 0. I tested it with the following code:

import numpy as np
from tiler import Tiler, Merger
import matplotlib.pyplot as plt
imsize = 64
im = np.reshape(np.arange(imsize*imsize),[imsize,imsize])
batch_size = 10
overlap = 5
tiler_mode = 'wrap'
windows_supported = ['boxcar', 'triang', 'blackman', 'hamming', 'hann', 'bartlett', 'flattop', 'parzen', 'bohman', 'blackmanharris', 'nuttall', 'barthann', 'overlap-tile']
tiler = Tiler(data_shape=im.shape,
                tile_shape=(16,16),
                channel_dimension=None,overlap=overlap,mode=tiler_mode,constant_value=1.0)
#Tiler.TILING_MODES == ['constant', 'drop', 'irregular', 'reflect', 'edge', 'wrap']
tiles_in_batches = [batch for _, batch in tiler(im, batch_size=batch_size)]
merged_images = []

for mwin in windows_supported:
    merger = Merger(tiler,window=mwin)
    #Merger.SUPPORTED_WINDOWS == ['boxcar', 'triang', 'blackman', 'hamming', 'hann', 'bartlett', 'flattop', 'parzen', 'bohman', 'blackmanharris', 'nuttall', 'barthann', 'overlap-tile']
    
    for batch_id, batch in enumerate(tiles_in_batches):
        merger.add_batch(batch_id, batch_size, batch)

    imf = merger.merge(unpad=True,argmax=False)
    merged_images.append(imf)
merged_images = np.array(merged_images)
fig,ax = plt.subplots(nrows=4,ncols=4,figsize=[14,14])
axm = ax.flatten()
for m,mim in enumerate(merged_images): 
    ima = axm[m].imshow(mim)
axm[m+1].imshow(im)
plt.show() 

which results in

tiling_test

where the last image is the original (to-be-tiled and merged) image and the others are the different merges from all possible merging options.

What am I doing wrong here?

Link to napari-tiler

Hey Ilja @the-lay

Hope everything is going well!

Would you like to include a link in the README to the napari-tiler repo?

[IDEA] Figuring out how to use this library with TensorFlow multi-class and binary classification

Is your feature request related to a problem? Please describe.

I have been trying to use this library for the inference of TensorFlow binary and multiclass segmentation models. I am able to use the tiler object to perform the predictions. I have not been able to figure out how to leverage the merger for the following cases.

data_shape = 5000 x 3000 x 4
tile_shape = (256, 256, 4)
channel_dimension = 0

The output of the model can be either a batch of (N x 256 x 256 x 1) or (N x 256 x 256 x 6); where 6 is the number of classes.

ValueError: Passed data shape ([256 256   1]) does not fit expected tile shape ((256, 256, 4)).

Describe the solution you'd like
Would be great to have additional examples regarding similar use cases performing TensorFlow or PyTorch predictions.

Here is an example of what I have been trying:

model = tf.keras.models.load_model(model.hdf5)

image = rxr.open_rasterio(filename)
image = image.transpose("y", "x", "band")
print(image.shape)

tiler = Tiler(
            data_shape=image.shape,
            tile_shape=(256, 256, 4),
            channel_dimension=2,
            #overlap=0.50
        )

# Calculate and apply extra padding, as well as adjust tiling parameters
#new_shape, padding = tiler.calculate_padding()
#tiler.recalculate(data_shape=new_shape)
#padded_image = np.pad(image, padding, mode="reflect")

merger = Merger(tiler=tiler)#, window="overlap-tile")
print(tiler)

for batch_id, batch in tiler(image, batch_size=512):
    batch = model.predict(batch)
    merger.add_batch(batch_id, 512, batch)

I am probably missing something, but would be nice to have it documented. Also, argmax option seems to be hardcoded for channel first images, which adds additional computational requirements when using channels last images. Any help would be appreciated.

[Q] Possible to merge overlapping tiles of a multi-class discrete model output using max strategy?

Hi 👋

I just found your library as I was browsing for a tiler/ merger solution to replace my crappy custom code that cannot handle overlap.

I'm looking for a library that lets me split a source images (3-channel, 2048x2048px) into overlapping 3-channel tiles with size 256x256px (overlap width=32px in x and y direction).

I'm feeding my segmentation model batches of those tiles. The results are 1-channel images of size 256x256 (values are multi-class integer results: currently classes 0,1,2).

So the flow is:

  1. Source: 2048x2048 RGB image
  2. Convert to batches of 256x256 RGB tiles (that overlap by 32px): 9x9 tiles in total (with Tiler()?), non-overlapping it is 8x8 tiles
  3. Run my model with those tiles
  4. The model returns 81x 256x256 data tiles
  5. Use merger to reconstruct a 2048x2048 monochrom image (with discrete class ids: 0, 1, 2) - in the overlap regions I would need to use the max value (no average or blending)

If I understand the library correctly, overlapping tiles are merged and the values are averaged? In my case, I'd have to take the max value in an overlap area. Is this supported? Could I adapt the code to take the max instead of the mean? And if so: are there any examples how to do this?

Cheers and thanks for any hints

`mode='drop'` produces wrong tiling with integer overlap

Encountered this problem when running this code:

tiler = Tiler(data_shape=(2, 180, 512, 512), tile_shape=(1, 64, 64, 64), overlap=32, mode='drop')
print(tiler.n_tiles) # 0

It should have raised an exception since overlap is bigger than data_shape on the first dimension.

[BUG] Incompatible Python and NumPy Versioning

Heads up that numpy >=1.20.0 doesn't support Python 3.6. numpy.typing in merger.py was introduced in numpy 1.20.0. Tiler has been failing on any Python 3.6 work I try doing.

The two solutions I see are to remove numpy.typing to allow Python 3.6 to work or update tiler to work 3.7 =<.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.