NormalizeOp.multipleChannels constructor

NormalizeOp.multipleChannels(
  1. List<double> mean,
  2. List<double> stddev
)

Initializes a NormalizeOp. When being called, it creates a new TensorBuffer, which satisfies:

  // Pseudo code. [...][i] means a certain element whose channel id is i.
  output[...][i] = (input[...][i] - mean[i]) / stddev[i]

Note: If all values in mean are set to 0 and all stddev are set to 1, no computation will happen, and original input will be directly returned in execution.

Note: The returned TensorBuffer is always a TfLiteType.float32 tensor at present, except that the input is a TfLiteType.uint8 tensor, all mean are set to 0 and all stddev are set to 1.

List

List

Throws ArgumentError if any stddev is zero, or mean has different number of elements with stddev, or any of them is empty.

Implementation

NormalizeOp.multipleChannels(List<double> mean, List<double> stddev) {
  SupportPreconditions.checkNotNull(mean, message: "Mean cannot be null");
  SupportPreconditions.checkNotNull(stddev, message: "Stddev cannot be null");
  SupportPreconditions.checkArgument(mean.length == stddev.length,
      errorMessage:
          "Per channel normalization requires same number of means and stddevs");
  SupportPreconditions.checkArgument(mean.length > 0,
      errorMessage: "Means and stddevs are empty.");
  this.mean = mean.toList();
  this.stddev = stddev.toList();

  bool allMeansAreZeroAndAllDevsAre1 = true;
  this.numChannels = mean.length;
  for (int i = 0; i < numChannels; i++) {
    SupportPreconditions.checkArgument(this.stddev[i] != 0,
        errorMessage: "Stddev cannot be zero.");
    if (this.stddev[i] != 1 || this.mean[i] != 0) {
      allMeansAreZeroAndAllDevsAre1 = false;
    }
  }
  this.isIdentityOp = allMeansAreZeroAndAllDevsAre1;
}