a preprocessing layer which randomly adjusts contrast during training this layer will randomly adjust the contrast of an image or images by a random factor contrast is adjusted independently for each channel of each image during training for each channel this layer computes the mean of the image pixels in the channel and then adjusts each component x of each pixel to x mean contrastfactor mean input pixel values can be of any range e g 0 1 or 0 255 and in integer or floating point dtype by default the layer will output floats note this layer is safe to use inside a tf data pipeline independently of which backend you re using input shape 3d unbatched or 4d batched tensor with shape height width channels in channelslast format output shape 3d unbatched or 4d batched tensor with shape height width channels in channelslast format args factor a positive float represented as fraction of value or a tuple of size 2 representing lower and upper bound when represented as a single float lower upper the contrast factor will be randomly picked between 1 0 lower 1 0 upper for any pixel x in the channel the output will be x mean factor mean where mean is the mean value of the channel seed integer used to create a random seed reduce mean on height reduce mean on width a preprocessing layer which randomly adjusts contrast during training this layer will randomly adjust the contrast of an image or images by a random factor contrast is adjusted independently for each channel of each image during training for each channel this layer computes the mean of the image pixels in the channel and then adjusts each component x of each pixel to x mean contrast_factor mean input pixel values can be of any range e g 0 1 or 0 255 and in integer or floating point dtype by default the layer will output floats note this layer is safe to use inside a tf data pipeline independently of which backend you re using input shape 3d unbatched or 4d batched tensor with shape height width channels in channels_last format output shape 3d unbatched or 4d batched tensor with shape height width channels in channels_last format args factor a positive float represented as fraction of value or a tuple of size 2 representing lower and upper bound when represented as a single float lower upper the contrast factor will be randomly picked between 1 0 lower 1 0 upper for any pixel x in the channel the output will be x mean factor mean where mean is the mean value of the channel seed integer used to create a random seed reduce mean on height reduce mean on width
from keras.api_export import keras_export
from keras.layers.preprocessing.tf_data_layer import TFDataLayer
from keras.random.seed_generator import SeedGenerator


@keras_export("keras.layers.RandomContrast")
class RandomContrast(TFDataLayer):
    

    def __init__(self, factor, seed=None, **kwargs):
        super().__init__(**kwargs)
        self.factor = factor
        if isinstance(factor, (tuple, list)):
            self.lower = factor[0]
            self.upper = factor[1]
        else:
            self.lower = self.upper = factor
        if self.lower < 0.0 or self.upper < 0.0 or self.lower > 1.0:
            raise ValueError(
                "`factor` argument cannot have negative values or values "
                "greater than 1."
                f"Received: factor={factor}"
            )
        self.seed = seed
        self.generator = SeedGenerator(seed)

    def call(self, inputs, training=True):
        inputs = self.backend.cast(inputs, self.compute_dtype)
        if training:
            seed_generator = self._get_seed_generator(self.backend._backend)
            factor = self.backend.random.uniform(
                shape=(),
                minval=1.0 - self.lower,
                maxval=1.0 + self.upper,
                seed=seed_generator,
                dtype=self.compute_dtype,
            )

            outputs = self._adjust_constrast(inputs, factor)
            outputs = self.backend.numpy.clip(outputs, 0, 255)
            self.backend.numpy.reshape(outputs, self.backend.shape(inputs))
            return outputs
        else:
            return inputs

    def _adjust_constrast(self, inputs, contrast_factor):
        
        inp_mean = self.backend.numpy.mean(inputs, axis=-3, keepdims=True)
        
        inp_mean = self.backend.numpy.mean(inp_mean, axis=-2, keepdims=True)

        outputs = (inputs - inp_mean) * contrast_factor + inp_mean
        return outputs

    def compute_output_shape(self, input_shape):
        return input_shape

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