Пример #1
0
def test_tile_image_3D():
    shapes = [
        (3, 5, 21, 21, 1),
        (1, 10, 21, 31, 2),
        (1, 15, 31, 21, 1),
    ]
    model_input_shapes = [(4, 3, 4), (3, 5, 5), (3, 7, 7), (5, 12, 15)]

    stride_ratios = [0.25, 0.33, 0.5, 0.66, 0.75, 0.8, 1]

    dtypes = ['int32', 'float32', 'uint16', 'float16']

    prod = product(shapes, model_input_shapes, stride_ratios, dtypes)

    for shape, input_shape, stride_ratio, dtype in prod:
        big_image = (np.random.random(shape) * 100).astype(dtype)
        tiles, tiles_info = utils.tile_image_3D(big_image,
                                                input_shape,
                                                stride_ratio=stride_ratio)

        assert tiles.shape[1:] == input_shape + (shape[-1], )
        assert tiles.dtype == big_image.dtype

        ceil = lambda x: int(np.ceil(x))
        round_to_even = lambda x: int(np.ceil(x / 2.0) * 2)

        image_size_z, image_size_x, image_size_y = big_image.shape[1:4]
        tile_size_z = input_shape[0]
        tile_size_x = input_shape[1]
        tile_size_y = input_shape[2]

        stride_x = round_to_even(stride_ratio * tile_size_x)
        stride_y = round_to_even(stride_ratio * tile_size_y)
        stride_z = round_to_even(stride_ratio * tile_size_z)

        if stride_z > tile_size_z:
            stride_z = tile_size_z

        if stride_x > tile_size_x:
            stride_x = tile_size_x

        if stride_y > tile_size_y:
            stride_y = tile_size_y

        rep_number_x = ceil((image_size_x - tile_size_x) / stride_x + 1)
        rep_number_y = ceil((image_size_y - tile_size_y) / stride_y + 1)
        rep_number_z = ceil((image_size_z - tile_size_z) / stride_z + 1)

        expected_batches = big_image.shape[
            0] * rep_number_x * rep_number_y * rep_number_z

        assert tiles.shape[0] == expected_batches

    # test bad input shape
    bad_shape = (21, 21, 1)
    bad_image = (np.random.random(bad_shape) * 100)
    with pytest.raises(ValueError):
        utils.tile_image(bad_image, (5, 5), stride_ratio=0.75)
Пример #2
0
def reshape_training_data(X_data,
                          y_data,
                          resize_ratio,
                          final_size,
                          stride_ratio=1,
                          tolerance=1.5):
    """Takes a stack of X and y data and reshapes and crops them to match output dimensions

    Args:
        X_data: 4D numpy array of image data
        y_data: 4D numpy array of labeled data
        resize_ratio: resize ratio for the images
        final_size: the desired shape of the output image
        stride_ratio: amount of overlap between crops (1 is no overlap, 0.5 is half crop size)
        tolerance: ratio that determines when resizing occurs

    Returns:
        reshaped_X, reshaped_y: resized and cropped version of input images

    Raises:
        ValueError: If image data is not 4D
    """

    if len(X_data.shape) != 4:
        raise ValueError('Image data must be 4D')

    # resize if needed
    if resize_ratio > tolerance or resize_ratio < (1 / tolerance):
        new_shape = (int(X_data.shape[1] * resize_ratio),
                     int(X_data.shape[2] * resize_ratio))

        X_data = resize(data=X_data, shape=new_shape)
        y_data = resize(data=y_data, shape=new_shape, labeled_image=True)

    # crop if needed
    if X_data.shape[1:3] != final_size:
        # pad image so that crops divide evenly
        X_data = pad_image_stack(images=X_data, crop_size=final_size)
        y_data = pad_image_stack(images=y_data, crop_size=final_size)

        # create x and y crops
        X_data, _ = tile_image(image=X_data,
                               model_input_shape=final_size,
                               stride_ratio=stride_ratio)
        y_data, _ = tile_image(image=y_data,
                               model_input_shape=final_size,
                               stride_ratio=stride_ratio)
    return X_data, y_data
Пример #3
0
def test_untile_image():
    shapes = [(3, 8, 16, 2), (1, 64, 64, 1), (1, 41, 58, 1), (1, 93, 61, 1)]
    rand_rel_diff_thresh = 2e-2
    model_input_shapes = [(16, 20), (32, 32), (41, 51), (64, 64), (100, 90)]
    stride_ratios = [0.33, 0.5, 0.51, 0.66, 0.75, 1]
    dtypes = ['int32', 'float32', 'uint16', 'float16']
    prod = product(shapes, model_input_shapes, stride_ratios, dtypes)

    # Test that randomly generated arrays are unchanged within a moderate tolerance
    for shape, input_shape, stride_ratio, dtype in prod:

        big_image = (np.random.random(shape) * 100).astype(dtype)
        tiles, tiles_info = utils.tile_image(big_image,
                                             model_input_shape=input_shape,
                                             stride_ratio=stride_ratio)

        untiled_image = utils.untile_image(tiles, tiles_info)

        assert untiled_image.dtype == dtype
        assert untiled_image.shape == shape

        np.testing.assert_allclose(big_image, untiled_image,
                                   rand_rel_diff_thresh)

    # Test that constant arrays are unchanged by tile/untile
    for shape, input_shape, stride_ratio, dtype in prod:
        for x in [0, 1, np.random.randint(2, 99)]:
            big_image = np.empty(shape).astype(dtype).fill(x)
            tiles, tiles_info = utils.tile_image(big_image,
                                                 model_input_shape=input_shape,
                                                 stride_ratio=stride_ratio)
            untiled_image = utils.untile_image(tiles, tiles_info)
            assert untiled_image.dtype == dtype
            assert untiled_image.shape == shape
            np.testing.assert_equal(big_image, untiled_image)

    # test that a stride_fraction of 0 raises an error
    with pytest.raises(ValueError):

        big_image_test = np.zeros((4, 4)).astype('int32')
        tiles, tiles_info = utils.tile_image(big_image_test,
                                             model_input_shape=(2, 2),
                                             stride_ratio=0)
        untiled_image = utils.untile_image(tiles, tiles_info)
Пример #4
0
    def _tile_input(self, image, pad_mode='constant'):
        """Tile the input image to match shape expected by model
        using the ``deepcell_toolbox`` function.

        Only supports 4D images.

        Args:
            image (numpy.array): Input image to tile
            pad_mode (str): The padding mode, one of "constant" or "reflect".

        Raises:
            ValueError: Input images must have only 4 dimensions

        Returns:
            (numpy.array, dict): Tuple of tiled image and dict of tiling
            information.
        """
        if len(image.shape) != 4:
            raise ValueError(
                'deepcell_toolbox.tile_image only supports 4d images.'
                'Image submitted for predict has {} dimensions'.format(
                    len(image.shape)))

        # Check difference between input and model image size
        x_diff = image.shape[1] - self.model_image_shape[0]
        y_diff = image.shape[2] - self.model_image_shape[1]

        # Check if the input is smaller than model image size
        if x_diff < 0 or y_diff < 0:
            # Calculate padding
            x_diff, y_diff = abs(x_diff), abs(y_diff)
            x_pad = (x_diff // 2,
                     x_diff // 2 + 1) if x_diff % 2 else (x_diff // 2,
                                                          x_diff // 2)
            y_pad = (y_diff // 2,
                     y_diff // 2 + 1) if y_diff % 2 else (y_diff // 2,
                                                          y_diff // 2)

            tiles = np.pad(image, [(0, 0), x_pad, y_pad, (0, 0)], 'reflect')
            tiles_info = {'padding': True, 'x_pad': x_pad, 'y_pad': y_pad}
        # Otherwise tile images larger than model size
        else:
            # Tile images, needs 4d
            tiles, tiles_info = tile_image(
                image,
                model_input_shape=self.model_image_shape,
                stride_ratio=0.75,
                pad_mode=pad_mode)

        return tiles, tiles_info
Пример #5
0
    def _tile_input(self, image):
        """Tile the input image to match shape expected by model
        using the deepcell_toolbox function.
        Currently only supports 4d images and otherwise raises an error

        Args:
            image (array): Input image to tile

        Raises:
            ValueError: Input images must have only 4 dimensions

        Returns:
            (array, dict): Tuple of tiled image and dictionary of tiling specs
        """

        if len(image.shape) != 4:
            raise ValueError(
                'deepcell_toolbox.tile_image only supports 4d images.'
                'Image submitted for predict has {} dimensions'.format(
                    len(image.shape)))

        # Check difference between input and model image size
        x_diff = image.shape[1] - self.model_image_shape[0]
        y_diff = image.shape[2] - self.model_image_shape[1]

        # Check if the input is smaller than model image size
        if x_diff < 0 or y_diff < 0:
            # Calculate padding
            x_diff, y_diff = abs(x_diff), abs(y_diff)
            x_pad = (x_diff // 2,
                     x_diff // 2 + 1) if x_diff % 2 else (x_diff // 2,
                                                          x_diff // 2)
            y_pad = (y_diff // 2,
                     y_diff // 2 + 1) if y_diff % 2 else (y_diff // 2,
                                                          y_diff // 2)

            tiles = np.pad(image, [(0, 0), x_pad, y_pad, (0, 0)], 'reflect')
            tiles_info = {'padding': True, 'x_pad': x_pad, 'y_pad': y_pad}
        # Otherwise tile images larger than model size
        else:
            # Tile images, needs 4d
            tiles, tiles_info = tile_image(
                image, model_input_shape=self.model_image_shape)

        return tiles, tiles_info