예제 #1
0
    def test_init(self):
        tiler = Tiler(data_shape=self.data.shape, tile_shape=(10, ))

        # logits test
        with self.assertRaises(ValueError):
            Merger(tiler=tiler, logits=-1)
        with self.assertRaises(ValueError):
            Merger(tiler=tiler, logits='unsupported_type')

        merger = Merger(tiler=tiler)
        np.testing.assert_equal(merger.data.shape, self.data.shape)

        merger2 = Merger(tiler=tiler, logits=99)
        np.testing.assert_equal(merger2.data.shape, (99, ) + self.data.shape)
예제 #2
0
    def test_overlap_tile_window(self):

        # no overlap is given - the resulting window should be just zeros
        tiler = Tiler(data_shape=(100, ), tile_shape=(10, ), overlap=0)
        merger = Merger(tiler=tiler, window='overlap-tile')
        np.testing.assert_equal(merger.window, np.zeros((10, )))

        # odd overlap - discarding overlap // 2 elements from both sides
        tiler = Tiler(data_shape=(100, ), tile_shape=(10, ), overlap=5)
        merger = Merger(tiler=tiler, window='overlap-tile')
        np.testing.assert_equal(merger.window, [0, 0, 1, 1, 1, 1, 1, 1, 0, 0])

        # even overlap - discarding overlap // 2 elements from both sides
        tiler = Tiler(data_shape=(100, ), tile_shape=(10, ), overlap=(6, ))
        merger = Merger(tiler=tiler, window='overlap-tile')
        np.testing.assert_equal(merger.window, [0, 0, 0, 1, 1, 1, 1, 0, 0, 0])

        # channel dimension case
        tiler = Tiler(data_shape=(3, 100),
                      tile_shape=(3, 4),
                      channel_dimension=0,
                      overlap=2)
        merger = Merger(tiler=tiler, window='overlap-tile')
        np.testing.assert_equal(merger.window,
                                [[0, 1, 1, 0], [0, 1, 1, 0], [0, 1, 1, 0]])

        # 2D even case
        tiler = Tiler(data_shape=(100, 100), tile_shape=(4, 4), overlap=(2, 2))
        merger = Merger(tiler=tiler, window='overlap-tile')
        np.testing.assert_equal(
            merger.window,
            [[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]])

        # 2D odd case
        tiler = Tiler(data_shape=(100, 100), tile_shape=(4, 4), overlap=3)
        merger = Merger(tiler=tiler, window='overlap-tile')
        np.testing.assert_equal(
            merger.window,
            [[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]])

        # Channel + 2D even case
        tiler = Tiler(data_shape=(3, 100, 100),
                      tile_shape=(3, 4, 4),
                      channel_dimension=0,
                      overlap=2)
        merger = Merger(tiler=tiler, window='overlap-tile')
        np.testing.assert_equal(
            merger.window,
            [[[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]],
             [[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]],
             [[0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0]]])
예제 #3
0
    def test_generate_window(self):
        tiler = Tiler(data_shape=self.data.shape, tile_shape=(10, ))

        with self.assertRaises(ValueError):
            Merger(tiler=tiler, window='unsupported_window')

        with self.assertRaises(ValueError):
            Merger(tiler=tiler, window=np.zeros((10, 10)))

        with self.assertRaises(ValueError):
            Merger(tiler=tiler, window=10)

        window = np.zeros((10, ))
        window[1:10] = 1
        merger = Merger(tiler=tiler, window=window)
        for t_id, t in tiler(self.data):
            merger.add(t_id, t)
        np.testing.assert_equal(merger.merge(),
                                [i if i % 10 else 0 for i in range(100)])
예제 #4
0
padded_image = np.pad(image, ((32, 32), (32, 32), (0, 0)), mode='reflect')

# Specifying tiling parameters
# The overlap should be 0.5, 64 or explicitly (64, 64, 0)
tiler = Tiler(data_shape=padded_image.shape,
              tile_shape=(128, 128, 3),
              overlap=(64, 64, 0),
              channel_dimension=2)

# Specifying merging parameters
# You can define overlap-tile window explicitly, i.e.
# window = np.zeros((128, 128, 3))
# window[32:-32, 32:-32, :] = 1
# merger = Merger(tiler=tiler, window=window)
# or you can use overlap-tile window which will do that automatically based on tiler.overlap
merger = Merger(tiler=tiler, window='overlap-tile')


# Let's define a function that will be applied to each tile
def process(patch: np.ndarray, sanity_check: bool = True) -> np.ndarray:

    # One example can be a sanity check
    # Make the parts that should be removed black
    # There should not appear any black spots in the final merged image
    if sanity_check:
        patch[:32, :, :] = 0
        patch[-32:, :, :] = 0
        patch[:, :32, :] = 0
        patch[:, -32:, :] = 0
        return patch
예제 #5
0
# That means we need to pad the image by 14 from each side
# To extrapolate missing context let's use reflect mode
padded_volume = np.pad(volume, 14, mode='reflect')

# Specifying tiling
# The overlap should be 28 voxels
tiler = Tiler(data_shape=padded_volume.shape,
              tile_shape=(48, 48, 48),
              overlap=(28, 28, 28))

# Window function for merging
window = np.zeros((48, 48, 48))
window[14:-14, 14:-14, 14:-14] = 1

# Specifying merging
merger = Merger(tiler=tiler, window=window)

# Let's define a function that will be applied to each tile
# For this example, let's black out the sides that should be "cropped" by window function
# as a way to confirm that only the middle parts are being merged
def process(patch: np.ndarray) -> np.ndarray:
    patch[:14, :, :] = 0
    patch[-14:, :, :] = 0
    patch[:, :14, :] = 0
    patch[:, -14:, :] = 0
    patch[:, :, :14] = 0
    patch[:, :, -14:] = 0
    return patch

# Iterate through all the tiles and apply the processing function and merge everything back
for tile_id, tile in tiler(padded_volume, progress_bar=True):
예제 #6
0
import numpy as np
from PIL import Image
from tiler import Tiler, Merger

# Loading image
# Photo by Christian Holzinger on Unsplash: https://unsplash.com/photos/CUY_YHhCFl4
image = np.array(Image.open('example_image.jpg'))  # 1280x1920x3

# Setup Tiler and Merger
tiler = Tiler(data_shape=image.shape,
              tile_shape=(200, 200, 3),
              channel_dimension=2)
merger = Merger(tiler)

# Example 1: process all tiles one by one, i.e. batch_size=0
for tile_i, tile in tiler(image, batch_size=0):
    merger.add(tile_i, tile)
result_bs0 = merger.merge().astype(np.uint8)

# Example 2: process all tiles in batches of 1, i.e. batch_size=1
merger.reset()
for batch_i, batch in tiler(image, batch_size=1):
    merger.add_batch(batch_i, 1, batch)
result_bs1 = merger.merge().astype(np.uint8)

# Example 3: process all tiles in batches of 10, i.e. batch_size=10
merger.reset()
for batch_i, batch in tiler(image, batch_size=10):
    merger.add_batch(batch_i, 10, batch)
result_bs10 = merger.merge().astype(np.uint8)
예제 #7
0
    def test_batch_add(self):
        tiler = Tiler(data_shape=self.data.shape, tile_shape=(10, ))
        merger = Merger(tiler)

        batch1 = [x for _, x in tiler(self.data, False, batch_size=1)]
        np.testing.assert_equal(len(batch1), 10)
        np.testing.assert_equal(batch1[0].shape, (
            1,
            10,
        ))
        for i, b in enumerate(batch1):
            merger.add_batch(i, 1, b)
        np.testing.assert_equal(merger.merge(), self.data)
        merger.reset()

        batch10 = [x for _, x in tiler(self.data, False, batch_size=10)]
        for i, b in enumerate(batch10):
            merger.add_batch(i, 10, b)
        np.testing.assert_equal(merger.merge(), self.data)
        merger.reset()

        batch8 = [x for _, x in tiler(self.data, False, batch_size=8)]
        np.testing.assert_equal(len(batch8), 2)
        np.testing.assert_equal(batch8[0].shape, (
            8,
            10,
        ))
        np.testing.assert_equal(batch8[1].shape, (
            2,
            10,
        ))
        for i, b in enumerate(batch8):
            merger.add_batch(i, 8, b)
        np.testing.assert_equal(merger.merge(), self.data)
        merger.reset()

        batch8_drop = [
            x for _, x in tiler(self.data, False, batch_size=8, drop_last=True)
        ]
        np.testing.assert_equal(len(batch8_drop), 1)
        np.testing.assert_equal(batch8_drop[0].shape, (
            8,
            10,
        ))
        for i, b in enumerate(batch8_drop):
            merger.add_batch(i, 8, b)
        np.testing.assert_equal(merger.merge()[:80], self.data[:80])
        np.testing.assert_equal(merger.merge()[80:], np.zeros((20, )))

        with self.assertRaises(IndexError):
            merger.add_batch(-1, 10, batch10[0])

        with self.assertRaises(IndexError):
            merger.add_batch(10, 10, batch10[9])
예제 #8
0
    def test_add(self):
        tiler = Tiler(data_shape=self.data.shape, tile_shape=(10, ))
        tiler2 = Tiler(data_shape=self.data.shape,
                       tile_shape=(12, ),
                       mode='irregular')
        tiler3 = Tiler(data_shape=(3, ) + self.data.shape,
                       tile_shape=(
                           3,
                           10,
                       ),
                       channel_dimension=0)

        merger = Merger(tiler)
        merger_logits = Merger(tiler, logits=3)
        merger_irregular = Merger(tiler2)
        merger_channel_dim = Merger(tiler3)

        tile = tiler.get_tile(self.data, 0)
        tile_logits = np.vstack((tile, tile, tile))
        tile_irregular = tiler2.get_tile(self.data, len(tiler2) - 1)

        # Wrong tile id cases
        with self.assertRaises(IndexError):
            merger.add(-1, np.ones((10, )))
        with self.assertRaises(IndexError):
            merger.add(len(tiler), np.ones((10, )))

        # Usual mergers expect tile_shape == data_shape
        with self.assertRaises(ValueError):
            merger.add(0, np.ones((
                3,
                10,
            )))
        merger.add(0, tile)
        np.testing.assert_equal(merger.merge()[:10], tile)

        # Logits merger expects an extra dimension in front for logits
        with self.assertRaises(ValueError):
            merger_logits.add(0, np.ones((10, )))
        merger_logits.add(0, tile_logits)
        np.testing.assert_equal(merger_logits.merge()[:, :10], tile_logits)
        np.testing.assert_equal(
            merger_logits.merge(argmax=True)[:10], np.zeros((10, )))

        # Irregular merger expects all(data_shape <= tile_shape)
        with self.assertRaises(ValueError):
            merger_irregular.add(0, np.ones((13, )))
        merger_irregular.add(len(tiler2) - 1, tile_irregular)
        np.testing.assert_equal(
            merger_irregular.merge()[-len(tile_irregular):], tile_irregular)

        # Channel dimension merger
        with self.assertRaises(ValueError):
            merger_channel_dim.add(0, np.ones((10, )))
        merger_channel_dim.add(0, tile_logits)
        np.testing.assert_equal(merger_channel_dim.merge()[:, :10],
                                tile_logits)

        # gotta get that 100% coverage
        # this should just print a warning
        # let's suppress it to avoid confusion
        with open(os.devnull, "w") as null:
            with redirect_stderr(null):
                merger.set_window('boxcar')
예제 #9
0
    def test_merge(self):

        # Test padding
        tiler = Tiler(data_shape=self.data.shape, tile_shape=(12, ))
        merger = Merger(tiler)
        for t_id, t in tiler(self.data):
            merger.add(t_id, t)

        np.testing.assert_equal(merger.merge(unpad=True), self.data)
        np.testing.assert_equal(
            merger.merge(unpad=False),
            np.hstack((self.data, [0, 0, 0, 0, 0, 0, 0, 0])))

        # Test argmax
        merger = Merger(tiler, logits=3)
        for t_id, t in tiler(self.data):
            merger.add(t_id, np.vstack((t, t / 2, t / 3)))

        np.testing.assert_equal(merger.merge(unpad=True, argmax=True),
                                np.zeros((100, )))
        np.testing.assert_equal(
            merger.merge(unpad=True, argmax=False),
            np.vstack((self.data, self.data / 2, self.data / 3)))

        np.testing.assert_equal(merger.merge(unpad=False, argmax=True),
                                np.zeros((108, )))
        np.testing.assert_equal(
            merger.merge(unpad=False, argmax=False),
            np.vstack((np.hstack((self.data, [0, 0, 0, 0, 0, 0, 0, 0])),
                       np.hstack((self.data, [0, 0, 0, 0, 0, 0, 0, 0])) / 2,
                       np.hstack((self.data, [0, 0, 0, 0, 0, 0, 0, 0])) / 3)))