def set_pre_processing_parameters(
        self,
        image_input_names=None,
        is_bgr=False,
        red_bias=0.0,
        green_bias=0.0,
        blue_bias=0.0,
        gray_bias=0.0,
        image_scale=1.0,
        image_format="NCHW",
    ):
        """
        Add a pre-processing parameters layer to the neural network object.

        Parameters
        ----------
        image_input_names: list of str
            Name of input blobs that are images

        is_bgr: boolean or dict()
            Channel order for input blobs that are images. BGR if True else RGB.
            To specify a different value for each image input,
            provide a dictionary with input names as keys.

        red_bias: float or dict()
            Image re-centering parameter (red channel)

        blue_bias: float or dict()
            Image re-centering parameter (blue channel)

        green_bias: float or dict()
            Image re-centering parameter (green channel)

        gray_bias: float or dict()
            Image re-centering parameter (for grayscale images)

        image_scale: float or dict()
            Value by which to scale the images.

        image_format: str
            Image format, either 'NCHW' / 'NHWC'

        See Also
        --------
        set_input, set_output, set_class_labels
        """
        if not image_input_names:
            return  # nothing to do here

        image_format = (
            image_format.upper()
            if isinstance(image_format, str)
            else image_format
        )
        if image_format != "NCHW" and image_format != "NHWC":
            raise ValueError(
                "Input image format must be either 'NCHW' or 'NHWC'. Provided {}".format(
                    image_format
                )
            )

        if not isinstance(is_bgr, dict):
            is_bgr = dict.fromkeys(image_input_names, is_bgr)
        if not isinstance(red_bias, dict):
            red_bias = dict.fromkeys(image_input_names, red_bias)
        if not isinstance(blue_bias, dict):
            blue_bias = dict.fromkeys(image_input_names, blue_bias)
        if not isinstance(green_bias, dict):
            green_bias = dict.fromkeys(image_input_names, green_bias)
        if not isinstance(gray_bias, dict):
            gray_bias = dict.fromkeys(image_input_names, gray_bias)
        if not isinstance(image_scale, dict):
            image_scale = dict.fromkeys(image_input_names, image_scale)

        # Raise error if any key in image preprocessing parameters
        # are not in image_input_names.
        def check_valid_preprocessing_keys(input, target, input_name):
            for key in input:
                if key not in target:
                    raise ValueError("Invalid key {} in {}.".format(key, input_name))

        target = image_input_names
        check_valid_preprocessing_keys(is_bgr, target, "is_bgr")
        check_valid_preprocessing_keys(red_bias, target, "red_bias")
        check_valid_preprocessing_keys(blue_bias, target, "blue_bias")
        check_valid_preprocessing_keys(green_bias, target, "green_bias")
        check_valid_preprocessing_keys(gray_bias, target, "gray_bias")
        check_valid_preprocessing_keys(image_scale, target, "image_scale")

        spec = self.spec

        # Add image inputs
        for input_ in spec.description.input:
            if input_.name in image_input_names:
                if input_.type.WhichOneof("Type") == "multiArrayType":
                    array_shape = tuple(input_.type.multiArrayType.shape)

                    if len(array_shape) == 4:
                        input_indices = (
                            [0, 1, 2, 3] if image_format == "NCHW" else [0, 3, 1, 2]
                        )
                    elif len(array_shape) == 3:
                        # Adding dummy index for 'batch' for compatibility
                        input_indices = (
                            [0, 0, 1, 2] if image_format == "NCHW" else [0, 2, 0, 1]
                        )
                    else:
                        raise ValueError(
                            "Invalid input shape. Input of rank {}, but expecting input of either rank 3 or rank 4".format(
                                len(array_shape)
                            )
                        )

                    # Extract image shape depending on input format
                    _, channels, height, width = [array_shape[e] for e in input_indices]

                    if image_format == "NHWC":
                        # If input format is 'NHWC' for TF model, it will be
                        # 'NCHW' for CoreML model. Therefore, add transpose to
                        # NHWC after the input and replace all use of input
                        layers = self.nn_spec.layers
                        complement_transpose = True
                        transpose_names = set()
                        transpose_outputs = []
                        for layer_ in layers:
                            if (
                                layer_.HasField("transpose")
                                and layer_.input[0] == input_.name
                            ):
                                transpose_order = list(layer_.transpose.axes)
                                if transpose_order == [
                                    0,
                                    3,
                                    1,
                                    2,
                                ] or transpose_order == [2, 0, 1]:
                                    transpose_names.add(layer_.name)
                                    transpose_outputs += list(layer_.output)
                                else:
                                    complement_transpose = False
                                    break
                            else:
                                for i in layer_.input:
                                    if i == input_.name:
                                        complement_transpose = False
                                        break
                        if complement_transpose:
                            for layer_ in layers:
                                for i in range(len(layer_.input)):
                                    if layer_.input[i] in transpose_names:
                                        layer_.input[i] = input_.name
                            for layer_ in layers:
                                if layer_.name == input_.name:
                                    del layer_.output[:]
                                    layer_.output.extend(transpose_outputs)
                                    break
                            while len(transpose_names) > 0:
                                for idx, layer_ in enumerate(layers):
                                    if layer_.name in transpose_names:
                                        del layers[idx]
                                        transpose_names.remove(layer_.name)
                        else:
                            axes = [1, 2, 0]
                            if len(array_shape) == 4:
                                axes = [0, 2, 3, 1]
                            input_transpose = input_.name + "_to_nhwc"
                            transpose_layer = self.add_transpose(
                                name=input_transpose,
                                axes=axes,
                                input_name=input_.name,
                                output_name=input_transpose,
                            )
                            layers.insert(0, layers.pop())
                            for layer_ in layers:
                                for i in range(len(layer_.input)):
                                    if layer_.name == input_transpose:
                                        continue
                                    if layer_.input[i] == input_.name:
                                        layer_.input[i] = input_transpose

                    # TODO: If input is not rank 3 or 4, then accordingly handle
                    # e.g. for rank-2 input, squeeze additional dimension in case of Gray scale image
                    if channels == 1:
                        input_.type.imageType.colorSpace = (
                            _proto.FeatureTypes_pb2.ImageFeatureType.ColorSpace.Value("GRAYSCALE")
                        )
                    elif channels == 3:
                        if input_.name in is_bgr:
                            if is_bgr[input_.name]:
                                input_.type.imageType.colorSpace = (
                                    _proto.FeatureTypes_pb2.ImageFeatureType.ColorSpace.Value("BGR")
                                )
                            else:
                                input_.type.imageType.colorSpace = (
                                    _proto.FeatureTypes_pb2.ImageFeatureType.ColorSpace.Value("RGB")
                                )
                        else:
                            input_.type.imageType.colorSpace = (
                                _proto.FeatureTypes_pb2.ImageFeatureType.ColorSpace.Value("RGB")
                            )
                    else:
                        raise ValueError(
                            "Channel Value %d not supported for image inputs" % channels
                        )
                    input_.type.imageType.width = width
                    input_.type.imageType.height = height

                preprocessing = self.nn_spec.preprocessing.add()
                preprocessing.featureName = input_.name
                scaler = preprocessing.scaler
                if input_.name in image_scale:
                    scaler.channelScale = image_scale[input_.name]
                else:
                    scaler.channelScale = 1.0
                if input_.name in red_bias:
                    scaler.redBias = red_bias[input_.name]
                if input_.name in blue_bias:
                    scaler.blueBias = blue_bias[input_.name]
                if input_.name in green_bias:
                    scaler.greenBias = green_bias[input_.name]
                if input_.name in gray_bias:
                    scaler.grayBias = gray_bias[input_.name]

        Add a pre-processing parameters layer to the neural network object.

        Parameters
        ----------
        image_input_names: list of str
            Name of input blobs that are images

        is_bgr: boolean or dict()
            Channel order for input blobs that are images. BGR if True else RGB.
            To specify a different value for each image input,
            provide a dictionary with input names as keys.

        red_bias: float or dict()
            Image re-centering parameter (red channel)

        blue_bias: float or dict()
            Image re-centering parameter (blue channel)

        green_bias: float or dict()
            Image re-centering parameter (green channel)

        gray_bias: float or dict()
            Image re-centering parameter (for grayscale images)

        image_scale: float or dict()
            Value by which to scale the images.

        image_format: str
            Image format, either 'NCHW' / 'NHWC'

        See Also
        --------
        set_input, set_output, set_class_labels
        
coremltools/models/neural_network/builder.py