Ejemplo n.º 1
0
    def __init__(self,
                 pool_size=(2, 2),
                 strides=(2, 2),
                 padding="SAME",
                 **kwargs):
        super(MaxUnpooling2D, self).__init__(**kwargs)

        if padding != "SAME" and padding != "VALID":
            raise ValueError('Padding must be a string from: "SAME", "VALID"')

        self.pool_size = normalize_tuple(pool_size, 2, "pool_size")
        self.strides = normalize_tuple(strides, 2, "strides")
        self.padding = padding
Ejemplo n.º 2
0
def mean_filter2d(
    image: TensorLike,
    filter_shape: Union[List[int], Tuple[int], int] = [3, 3],
    padding: str = "REFLECT",
    constant_values: TensorLike = 0,
    name: Optional[str] = None,
) -> tf.Tensor:
    """Perform mean filtering on image(s).

    Args:
      image: Either a 2-D `Tensor` of shape `[height, width]`,
        a 3-D `Tensor` of shape `[height, width, channels]`,
        or a 4-D `Tensor` of shape `[batch_size, height, width, channels]`.
      filter_shape: An `integer` or `tuple`/`list` of 2 integers, specifying
        the height and width of the 2-D mean filter. Can be a single integer
        to specify the same value for all spatial dimensions.
      padding: A `string`, one of "REFLECT", "CONSTANT", or "SYMMETRIC".
        The type of padding algorithm to use, which is compatible with
        `mode` argument in `tf.pad`. For more details, please refer to
        https://www.tensorflow.org/api_docs/python/tf/pad.
      constant_values: A `scalar`, the pad value to use in "CONSTANT"
        padding mode.
      name: A name for this operation (optional).
    Returns:
      2-D, 3-D or 4-D `Tensor` of the same dtype as input.
    Raises:
      ValueError: If `image` is not 2, 3 or 4-dimensional,
        if `padding` is other than "REFLECT", "CONSTANT" or "SYMMETRIC",
        or if `filter_shape` is invalid.
    """
    with tf.name_scope(name or "mean_filter2d"):
        image = tf.convert_to_tensor(image, name="image")
        original_ndims = img_utils.get_ndims(image)
        image = img_utils.to_4D_image(image)

        filter_shape = keras_utils.normalize_tuple(filter_shape, 2, "filter_shape")

        # Keep the precision if it's float;
        # otherwise, convert to float32 for computing.
        orig_dtype = image.dtype
        if not image.dtype.is_floating:
            image = tf.dtypes.cast(image, tf.dtypes.float32)

        # Explicitly pad the image
        image = _pad(image, filter_shape, mode=padding, constant_values=constant_values)

        # Filter of shape (filter_width, filter_height, in_channels, 1)
        # has the value of 1 for each element.
        area = tf.constant(filter_shape[0] * filter_shape[1], dtype=image.dtype)
        filter_shape += (tf.shape(image)[-1], 1)
        kernel = tf.ones(shape=filter_shape, dtype=image.dtype)

        output = tf.nn.depthwise_conv2d(
            image, kernel, strides=(1, 1, 1, 1), padding="VALID"
        )

        output /= area

        output = img_utils.from_4D_image(output, original_ndims)
        return tf.dtypes.cast(output, orig_dtype)
Ejemplo n.º 3
0
    def __init__(
        self,
        output_size: Iterable[int],
        **kwargs,
    ):
        super(MaxUnpooling2DV2, self).__init__(**kwargs)

        self.output_size = normalize_tuple(output_size, 4, "output_size")
 def __init__(self,
              reduce_function: Callable,
              output_size: Union[int, Iterable[int]],
              data_format=None,
              **kwargs):
     self.data_format = conv_utils.normalize_data_format(data_format)
     self.reduce_function = reduce_function
     self.output_size = conv_utils.normalize_tuple(output_size, 1,
                                                   "output_size")
     super().__init__(**kwargs)
Ejemplo n.º 5
0
 def __init__(self,
              bins: Union[Iterable[int], Iterable[Iterable[int]]],
              data_format=None,
              *args,
              **kwargs):
     self.bins = [conv_utils.normalize_tuple(bin, 2, "bin") for bin in bins]
     self.data_format = conv_utils.normalize_data_format(data_format)
     self.pool_layers = []
     for bin in self.bins:
         self.pool_layers.append(
             AdaptiveAveragePooling2D(bin, self.data_format))
     super().__init__(*args, **kwargs)
Ejemplo n.º 6
0
    def test_normalize_tuple(self):
        self.assertEqual((2, 2, 2), normalize_tuple(2, n=3, name='strides'))
        self.assertEqual((2, 1, 2),
                         normalize_tuple((2, 1, 2), n=3, name='strides'))

        with self.assertRaises(ValueError):
            normalize_tuple((2, 1), n=3, name='strides')

        with self.assertRaises(ValueError):
            normalize_tuple(None, n=3, name='strides')
Ejemplo n.º 7
0
def test_normalize_tuple():
    assert (2, 2, 2) == keras_utils.normalize_tuple(2, n=3, name="strides")
    assert (2, 1, 2) == keras_utils.normalize_tuple((2, 1, 2),
                                                    n=3,
                                                    name="strides")

    with pytest.raises(ValueError):
        keras_utils.normalize_tuple((2, 1), n=3, name="strides")

    with pytest.raises(TypeError):
        keras_utils.normalize_tuple(None, n=3, name="strides")
Ejemplo n.º 8
0
    def test_normalize_tuple(self):
        self.assertEqual((2, 2, 2),
                         keras_utils.normalize_tuple(2, n=3, name="strides"))
        self.assertEqual((2, 1, 2),
                         keras_utils.normalize_tuple((2, 1, 2),
                                                     n=3,
                                                     name="strides"))

        with self.assertRaises(ValueError):
            keras_utils.normalize_tuple((2, 1), n=3, name="strides")

        with self.assertRaises(TypeError):
            keras_utils.normalize_tuple(None, n=3, name="strides")
Ejemplo n.º 9
0
def median_filter2d(image,
                    filter_shape=(3, 3),
                    padding="REFLECT",
                    constant_values=0,
                    name=None):
    """Perform median filtering on image(s).

    Args:
      image: Either a 2-D `Tensor` of shape `[height, width]`,
        a 3-D `Tensor` of shape `[height, width, channels]`,
        or a 4-D `Tensor` of shape `[batch_size, height, width, channels]`.
      filter_shape: An `integer` or `tuple`/`list` of 2 integers, specifying
        the height and width of the 2-D median filter. Can be a single integer
        to specify the same value for all spatial dimensions.
      padding: A `string`, one of "REFLECT", "CONSTANT", or "SYMMETRIC".
        The type of padding algorithm to use, which is compatible with
        `mode` argument in `tf.pad`. For more details, please refer to
        https://www.tensorflow.org/api_docs/python/tf/pad.
      constant_values: A `scalar`, the pad value to use in "CONSTANT"
        padding mode.
      name: A name for this operation (optional).
    Returns:
      3-D or 4-D `Tensor` of the same dtype as input.
    Raises:
      ValueError: If `image` is not 2, 3 or 4-dimensional,
        if `padding` is other than "REFLECT", "CONSTANT" or "SYMMETRIC",
        or if `filter_shape` is invalid.
    """
    with tf.name_scope(name or "median_filter2d"):
        image = tf.convert_to_tensor(image, name="image")
        original_ndims = img_utils.get_ndims(image)
        image = img_utils.to_4D_image(image)

        if padding not in ["REFLECT", "CONSTANT", "SYMMETRIC"]:
            raise ValueError(
                "padding should be one of \"REFLECT\", \"CONSTANT\", or "
                "\"SYMMETRIC\".")

        filter_shape = keras_utils.normalize_tuple(filter_shape, 2,
                                                   "filter_shape")

        image_shape = tf.shape(image)
        batch_size = image_shape[0]
        height = image_shape[1]
        width = image_shape[2]
        channels = image_shape[3]

        # Explicitly pad the image
        image = _pad(image,
                     filter_shape,
                     mode=padding,
                     constant_values=constant_values)

        area = filter_shape[0] * filter_shape[1]

        floor = (area + 1) // 2
        ceil = area // 2 + 1

        patches = tf.image.extract_patches(
            image,
            sizes=[1, filter_shape[0], filter_shape[1], 1],
            strides=[1, 1, 1, 1],
            rates=[1, 1, 1, 1],
            padding="VALID")

        patches = tf.reshape(patches,
                             shape=[batch_size, height, width, area, channels])

        patches = tf.transpose(patches, [0, 1, 2, 4, 3])

        # Note the returned median is casted back to the original type
        # Take [5, 6, 7, 8] for example, the median is (6 + 7) / 2 = 3.5
        # It turns out to be int(6.5) = 6 if the original type is int
        top = tf.nn.top_k(patches, k=ceil).values
        if area % 2 == 1:
            median = top[:, :, :, :, floor - 1]
        else:
            median = (top[:, :, :, :, floor - 1] +
                      top[:, :, :, :, ceil - 1]) / 2

        output = tf.cast(median, image.dtype)
        output = img_utils.from_4D_image(output, original_ndims)
        return output
Ejemplo n.º 10
0
def gaussian_filter2d(
    image: TensorLike,
    filter_shape: Union[List[int], Tuple[int], int] = [3, 3],
    sigma: Union[List[float], Tuple[float], float] = 1.0,
    padding: str = "REFLECT",
    constant_values: TensorLike = 0,
    name: Optional[str] = None,
) -> TensorLike:
    """Perform Gaussian blur on image(s).

    Args:
      image: Either a 2-D `Tensor` of shape `[height, width]`,
        a 3-D `Tensor` of shape `[height, width, channels]`,
        or a 4-D `Tensor` of shape `[batch_size, height, width, channels]`.
      filter_shape: An `integer` or `tuple`/`list` of 2 integers, specifying
        the height and width of the 2-D gaussian filter. Can be a single
        integer to specify the same value for all spatial dimensions.
      sigma: A `float` or `tuple`/`list` of 2 floats, specifying
        the standard deviation in x and y direction the 2-D gaussian filter.
        Can be a single float to specify the same value for all spatial
        dimensions.
      padding: A `string`, one of "REFLECT", "CONSTANT", or "SYMMETRIC".
        The type of padding algorithm to use, which is compatible with
        `mode` argument in `tf.pad`. For more details, please refer to
        https://www.tensorflow.org/api_docs/python/tf/pad.
      constant_values: A `scalar`, the pad value to use in "CONSTANT"
        padding mode.
      name: A name for this operation (optional).
    Returns:
      2-D, 3-D or 4-D `Tensor` of the same dtype as input.
    Raises:
      ValueError: If `image` is not 2, 3 or 4-dimensional,
        if `padding` is other than "REFLECT", "CONSTANT" or "SYMMETRIC",
        if `filter_shape` is invalid,
        or if `sigma` is invalid.
    """
    with tf.name_scope(name or "gaussian_filter2d"):
        if isinstance(sigma, (list, tuple)):
            if len(sigma) != 2:
                raise ValueError(
                    "sigma should be a float or a tuple/list of 2 floats")
        else:
            sigma = (sigma, ) * 2

        if any(s < 0 for s in sigma):
            raise ValueError("sigma should be greater than or equal to 0.")

        image = tf.convert_to_tensor(image, name="image")
        sigma = tf.convert_to_tensor(sigma, name="sigma")

        original_ndims = img_utils.get_ndims(image)
        image = img_utils.to_4D_image(image)

        # Keep the precision if it's float;
        # otherwise, convert to float32 for computing.
        orig_dtype = image.dtype
        if not image.dtype.is_floating:
            image = tf.cast(image, tf.float32)

        channels = tf.shape(image)[3]
        filter_shape = keras_utils.normalize_tuple(filter_shape, 2,
                                                   "filter_shape")

        sigma = tf.cast(sigma, image.dtype)
        gaussian_kernel_x = _get_gaussian_kernel(sigma[1], filter_shape[1])
        gaussian_kernel_x = gaussian_kernel_x[tf.newaxis, :]

        gaussian_kernel_y = _get_gaussian_kernel(sigma[0], filter_shape[0])
        gaussian_kernel_y = gaussian_kernel_y[:, tf.newaxis]

        gaussian_kernel_2d = _get_gaussian_kernel_2d(gaussian_kernel_y,
                                                     gaussian_kernel_x)
        gaussian_kernel_2d = gaussian_kernel_2d[:, :, tf.newaxis, tf.newaxis]
        gaussian_kernel_2d = tf.tile(gaussian_kernel_2d, [1, 1, channels, 1])

        image = _pad(image,
                     filter_shape,
                     mode=padding,
                     constant_values=constant_values)

        output = tf.nn.depthwise_conv2d(
            input=image,
            filter=gaussian_kernel_2d,
            strides=(1, 1, 1, 1),
            padding="VALID",
        )
        output = img_utils.from_4D_image(output, original_ndims)
        return tf.cast(output, orig_dtype)
Ejemplo n.º 11
0
def gaussian_filter2d(
    image: FloatTensorLike,
    filter_shape: Union[List[int], Tuple[int]] = [3, 3],
    sigma: FloatTensorLike = 1,
    padding: str = "REFLECT",
    constant_values: TensorLike = 0,
    name: Optional[str] = None,
) -> FloatTensorLike:
    """Perform Gaussian blur on image(s).

    Args:
      image: Either a 2-D `Tensor` of shape `[height, width]`,
        a 3-D `Tensor` of shape `[height, width, channels]`,
        or a 4-D `Tensor` of shape `[batch_size, height, width, channels]`.
      filter_shape: An `integer` or `tuple`/`list` of 2 integers, specifying
        the height and width of the 2-D gaussian filter. Can be a single
        integer to specify the same value for all spatial dimensions.
      sigma: Standard deviation of Gaussian.
      padding: A `string`, one of "REFLECT", "CONSTANT", or "SYMMETRIC".
        The type of padding algorithm to use, which is compatible with
        `mode` argument in `tf.pad`. For more details, please refer to
        https://www.tensorflow.org/api_docs/python/tf/pad.
      constant_values: A `scalar`, the pad value to use in "CONSTANT"
        padding mode.
      name: A name for this operation (optional).
    Returns:
      2-D, 3-D or 4-D `Tensor` of the same dtype as input.
    Raises:
      ValueError: If `image` is not 2, 3 or 4-dimensional,
        if `padding` is other than "REFLECT", "CONSTANT" or "SYMMETRIC",
        if `filter_shape` is invalid,
        or if `sigma` is less than or equal to 0.
    """
    with tf.name_scope(name or "gaussian_filter2d"):
        if sigma <= 0:
            raise ValueError("Sigma should not be zero")
        if padding not in ["REFLECT", "CONSTANT", "SYMMETRIC"]:
            raise ValueError(
                "Padding should be REFLECT, CONSTANT, OR SYMMETRIC")

        image = tf.cast(image, tf.float32)
        original_ndims = img_utils.get_ndims(image)
        image = img_utils.to_4D_image(image)
        channels = tf.shape(image)[3]
        filter_shape = keras_utils.normalize_tuple(filter_shape, 2,
                                                   "filter_shape")

        gaussian_filter_x = _get_gaussian_kernel(sigma, filter_shape[1])
        gaussian_filter_x = tf.cast(gaussian_filter_x, tf.float32)
        gaussian_filter_x = tf.reshape(gaussian_filter_x, [1, filter_shape[1]])

        gaussian_filter_y = _get_gaussian_kernel(sigma, filter_shape[0])
        gaussian_filter_y = tf.reshape(gaussian_filter_y, [filter_shape[0], 1])
        gaussian_filter_y = tf.cast(gaussian_filter_y, tf.float32)

        gaussian_filter_2d = _get_gaussian_kernel_2d(gaussian_filter_y,
                                                     gaussian_filter_x)
        gaussian_filter_2d = tf.repeat(gaussian_filter_2d, channels)
        gaussian_filter_2d = tf.reshape(
            gaussian_filter_2d,
            [filter_shape[0], filter_shape[1], channels, 1])

        image = _pad(
            image,
            filter_shape,
            mode=padding,
            constant_values=constant_values,
        )

        output = tf.nn.depthwise_conv2d(
            input=image,
            filter=gaussian_filter_2d,
            strides=(1, 1, 1, 1),
            padding="VALID",
        )
        output = img_utils.from_4D_image(output, original_ndims)
        return output