zeropadding layer for 3d data spatial or spatiotemporal examples inputshape 1 1 2 2 3 x np arangenp prodinputshape reshapeinputshape y keras layers zeropadding3dpadding2x y shape 1 5 6 6 3 args padding int or tuple of 3 ints or tuple of 3 tuples of 2 ints if int the same symmetric padding is applied to depth height and width if tuple of 3 ints interpreted as three different symmetric padding values for depth height and width symmetricdim1pad symmetricdim2pad symmetricdim3pad if tuple of 3 tuples of 2 ints interpreted as leftdim1pad rightdim1pad leftdim2pad rightdim2pad leftdim3pad rightdim3pad dataformat a string one of channelslast default or channelsfirst the ordering of the dimensions in the inputs channelslast corresponds to inputs with shape batchsize spatialdim1 spatialdim2 spatialdim3 channels while channelsfirst corresponds to inputs with shape batchsize channels spatialdim1 spatialdim2 spatialdim3 when unspecified uses imagedataformat value found in your keras config file at keraskeras json if exists defaults to channelslast input shape 5d tensor with shape if dataformat is channelslast batchsize firstaxistopad secondaxistopad thirdaxistopad depth if dataformat is channelsfirst batchsize depth firstaxistopad secondaxistopad thirdaxistopad output shape 5d tensor with shape if dataformat is channelslast batchsize firstpaddedaxis secondpaddedaxis thirdaxistopad depth if dataformat is channelsfirst batchsize depth firstpaddedaxis secondpaddedaxis thirdaxistopad zero padding layer for 3d data spatial or spatio temporal examples input_shape 1 1 2 2 3 x np arange np prod input_shape reshape input_shape y keras layers zeropadding3d padding 2 x y shape 1 5 6 6 3 args padding int or tuple of 3 ints or tuple of 3 tuples of 2 ints if int the same symmetric padding is applied to depth height and width if tuple of 3 ints interpreted as three different symmetric padding values for depth height and width symmetric_dim1_pad symmetric_dim2_pad symmetric_dim3_pad if tuple of 3 tuples of 2 ints interpreted as left_dim1_pad right_dim1_pad left_dim2_pad right_dim2_pad left_dim3_pad right_dim3_pad data_format a string one of channels_last default or channels_first the ordering of the dimensions in the inputs channels_last corresponds to inputs with shape batch_size spatial_dim1 spatial_dim2 spatial_dim3 channels while channels_first corresponds to inputs with shape batch_size channels spatial_dim1 spatial_dim2 spatial_dim3 when unspecified uses image_data_format value found in your keras config file at keras keras json if exists defaults to channels_last input shape 5d tensor with shape if data_format is channels_last batch_size first_axis_to_pad second_axis_to_pad third_axis_to_pad depth if data_format is channels_first batch_size depth first_axis_to_pad second_axis_to_pad third_axis_to_pad output shape 5d tensor with shape if data_format is channels_last batch_size first_padded_axis second_padded_axis third_axis_to_pad depth if data_format is channels_first batch_size depth first_padded_axis second_padded_axis third_axis_to_pad
from keras import backend
from keras import ops
from keras.api_export import keras_export
from keras.layers.input_spec import InputSpec
from keras.layers.layer import Layer
from keras.utils import argument_validation


@keras_export("keras.layers.ZeroPadding3D")
class ZeroPadding3D(Layer):
    

    def __init__(
        self, padding=((1, 1), (1, 1), (1, 1)), data_format=None, **kwargs
    ):
        super().__init__(**kwargs)
        self.data_format = backend.standardize_data_format(data_format)
        if isinstance(padding, int):
            self.padding = (
                (padding, padding),
                (padding, padding),
                (padding, padding),
            )
        elif hasattr(padding, "__len__"):
            if len(padding) != 3:
                raise ValueError(
                    f"`padding` should have 3 elements. Received: {padding}."
                )
            dim1_padding = argument_validation.standardize_tuple(
                padding[0], 2, "1st entry of padding", allow_zero=True
            )
            dim2_padding = argument_validation.standardize_tuple(
                padding[1], 2, "2nd entry of padding", allow_zero=True
            )
            dim3_padding = argument_validation.standardize_tuple(
                padding[2], 2, "3rd entry of padding", allow_zero=True
            )
            self.padding = (dim1_padding, dim2_padding, dim3_padding)
        else:
            raise ValueError(
                "`padding` should be either an int, a tuple of 3 ints "
                "(symmetric_dim1_pad, symmetric_dim2_pad, symmetric_dim3_pad), "
                "or a tuple of 3 tuples of 2 ints "
                "((left_dim1_pad, right_dim1_pad),"
                " (left_dim2_pad, right_dim2_pad),"
                " (left_dim3_pad, right_dim2_pad)). "
                f"Received: padding={padding}."
            )
        self.input_spec = InputSpec(ndim=5)

    def compute_output_shape(self, input_shape):
        output_shape = list(input_shape)
        spatial_dims_offset = 2 if self.data_format == "channels_first" else 1
        for index in range(0, 3):
            if output_shape[index + spatial_dims_offset] is not None:
                output_shape[index + spatial_dims_offset] += (
                    self.padding[index][0] + self.padding[index][1]
                )
        return tuple(output_shape)

    def call(self, inputs):
        if self.data_format == "channels_first":
            all_dims_padding = ((0, 0), (0, 0), *self.padding)
        else:
            all_dims_padding = ((0, 0), *self.padding, (0, 0))
        return ops.pad(inputs, all_dims_padding)

    def get_config(self):
        config = {"padding": self.padding, "data_format": self.data_format}
        base_config = super().get_config()
        return {**base_config, **config}