a preprocessing layer which randomly adjusts brightness during training this layer will randomly increasereduce the brightness for the input rgb images at inference time the output will be identical to the input call the layer with trainingtrue to adjust the brightness of the input note this layer is safe to use inside a tf data pipeline independently of which backend you re using args factor float or a listtuple of 2 floats between 1 0 and 1 0 the factor is used to determine the lower bound and upper bound of the brightness adjustment a float value will be chosen randomly between the limits when 1 0 is chosen the output image will be black and when 1 0 is chosen the image will be fully white when only one float is provided eg 0 2 then 0 2 will be used for lower bound and 0 2 will be used for upper bound valuerange optional listtuple of 2 floats for the lower and upper limit of the values of the input data to make no change use 0 0 1 0 e g if the image input has been scaled before this layer defaults to 0 0 255 0 the brightness adjustment will be scaled to this range and the output values will be clipped to this range seed optional integer for fixed rng behavior inputs 3d hwc or 4d nhwc tensor with float or int dtype input pixel values can be of any range e g 0 1 or 0 255 output 3d hwc or 4d nhwc tensor with brightness adjusted based on the factor by default the layer will output floats the output value will be clipped to the range 0 255 the valid range of rgb colors and rescaled based on the valuerange if needed sample usage python randombright keras layers randombrightnessfactor0 2 an image with shape 2 2 3 image 1 2 3 4 5 6 7 8 9 10 11 12 assume we randomly select the factor to be 0 1 then it will apply 0 1 255 to all the channel output randombrightimage trainingtrue output will be int64 with 25 5 added to each channel and round down array26 5 27 5 28 5 29 5 30 5 31 5 32 5 33 5 34 5 35 5 36 5 37 5 shape2 2 3 dtypeint64 keep only the batch dim this will ensure to have same adjustment with in one image but different across the images a preprocessing layer which randomly adjusts brightness during training this layer will randomly increase reduce the brightness for the input rgb images at inference time the output will be identical to the input call the layer with training true to adjust the brightness of the input note this layer is safe to use inside a tf data pipeline independently of which backend you re using args factor float or a list tuple of 2 floats between 1 0 and 1 0 the factor is used to determine the lower bound and upper bound of the brightness adjustment a float value will be chosen randomly between the limits when 1 0 is chosen the output image will be black and when 1 0 is chosen the image will be fully white when only one float is provided eg 0 2 then 0 2 will be used for lower bound and 0 2 will be used for upper bound value_range optional list tuple of 2 floats for the lower and upper limit of the values of the input data to make no change use 0 0 1 0 e g if the image input has been scaled before this layer defaults to 0 0 255 0 the brightness adjustment will be scaled to this range and the output values will be clipped to this range seed optional integer for fixed rng behavior inputs 3d hwc or 4d nhwc tensor with float or int dtype input pixel values can be of any range e g 0 1 or 0 255 output 3d hwc or 4d nhwc tensor with brightness adjusted based on the factor by default the layer will output floats the output value will be clipped to the range 0 255 the valid range of rgb colors and rescaled based on the value_range if needed sample usage python random_bright keras layers randombrightness factor 0 2 an image with shape 2 2 3 image 1 2 3 4 5 6 7 8 9 10 11 12 assume we randomly select the factor to be 0 1 then it will apply 0 1 255 to all the channel output random_bright image training true output will be int64 with 25 5 added to each channel and round down array 26 5 27 5 28 5 29 5 30 5 31 5 32 5 33 5 34 5 35 5 36 5 37 5 shape 2 2 3 dtype int64 keep only the batch dim this will ensure to have same adjustment with in one image but different across the images
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.RandomBrightness")
class RandomBrightness(TFDataLayer):
    

    _FACTOR_VALIDATION_ERROR = (
        "The `factor` argument should be a number (or a list of two numbers) "
        "in the range [-1.0, 1.0]. "
    )
    _VALUE_RANGE_VALIDATION_ERROR = (
        "The `value_range` argument should be a list of two numbers. "
    )

    def __init__(self, factor, value_range=(0, 255), seed=None, **kwargs):
        super().__init__(**kwargs)
        self._set_factor(factor)
        self._set_value_range(value_range)
        self.seed = seed
        self.generator = SeedGenerator(seed)

    def _set_value_range(self, value_range):
        if not isinstance(value_range, (tuple, list)):
            raise ValueError(
                self.value_range_VALIDATION_ERROR
                + f"Received: value_range={value_range}"
            )
        if len(value_range) != 2:
            raise ValueError(
                self.value_range_VALIDATION_ERROR
                + f"Received: value_range={value_range}"
            )
        self.value_range = sorted(value_range)

    def _set_factor(self, factor):
        if isinstance(factor, (tuple, list)):
            if len(factor) != 2:
                raise ValueError(
                    self._FACTOR_VALIDATION_ERROR + f"Received: factor={factor}"
                )
            self._check_factor_range(factor[0])
            self._check_factor_range(factor[1])
            self._factor = sorted(factor)
        elif isinstance(factor, (int, float)):
            self._check_factor_range(factor)
            factor = abs(factor)
            self._factor = [-factor, factor]
        else:
            raise ValueError(
                self._FACTOR_VALIDATION_ERROR + f"Received: factor={factor}"
            )

    def _check_factor_range(self, input_number):
        if input_number > 1.0 or input_number < -1.0:
            raise ValueError(
                self._FACTOR_VALIDATION_ERROR
                + f"Received: input_number={input_number}"
            )

    def call(self, inputs, training=True):
        inputs = self.backend.cast(inputs, self.compute_dtype)
        if training:
            return self._randomly_adjust_brightness(inputs)
        else:
            return inputs

    def _randomly_adjust_brightness(self, images):
        images_shape = self.backend.shape(images)
        rank = len(images_shape)
        if rank == 3:
            rgb_delta_shape = (1, 1, 1)
        elif rank == 4:
            
            
            rgb_delta_shape = [images_shape[0], 1, 1, 1]
        else:
            raise ValueError(
                "Expected the input image to be rank 3 or 4. Received "
                f"inputs.shape={images_shape}"
            )

        seed_generator = self._get_seed_generator(self.backend._backend)
        rgb_delta = self.backend.random.uniform(
            minval=self._factor[0],
            maxval=self._factor[1],
            shape=rgb_delta_shape,
            seed=seed_generator,
        )
        rgb_delta = rgb_delta * (self.value_range[1] - self.value_range[0])
        rgb_delta = self.backend.cast(rgb_delta, images.dtype)
        images += rgb_delta
        return self.backend.numpy.clip(
            images, self.value_range[0], self.value_range[1]
        )

    def compute_output_shape(self, input_shape):
        return input_shape

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