calculateThreshold static method

int calculateThreshold(
  1. List<int> histogram
)

Calculates an appropriate threshold for identifying valleys in a histogram

This function finds the smallest valleys (local minima) in the histogram, which represent the gaps between characters.

Parameters:

  • histogram: A list of integer values representing the histogram.

Returns: An integer threshold value, or _invalidThreshold if a valid threshold couldn't be determined.

Implementation

static int calculateThreshold(List<int> histogram) {
  // Need at least [_minHistogramLengthForValley] elements to have a valley.
  if (histogram.length >= _minHistogramLengthForValley) {
    // Find all valleys (local minima)
    List<int> valleys = [];

    // Handle single-point valleys
    for (int i = 1; i < histogram.length - 1; i++) {
      if (histogram[i] < histogram[i - 1] &&
          histogram[i] < histogram[i + 1]) {
        valleys.add(histogram[i]);
      }
    }

    // Handle flat valleys (consecutive identical values that are lower than neighbors)
    for (int i = 1; i < histogram.length - _flatValleyLookahead; i++) {
      // Check if we have a sequence of identical values
      if (histogram[i] == histogram[i + 1]) {
        // Find the end of this flat region
        int j = i + 1;
        while (j < histogram.length - 1 && histogram[j] == histogram[i]) {
          j++;
        }

        // Check if this flat region is a valley (lower than both neighbors)
        if (i > 0 &&
            j < histogram.length &&
            histogram[i] < histogram[i - 1] &&
            histogram[i] < histogram[j]) {
          valleys.add(histogram[i]);
        }

        // Skip to the end of this flat region
        i = j - 1;
      }
    }

    // If we found valleys, use the smallest one as threshold
    if (valleys.isNotEmpty) {
      int smallestValley = valleys.reduce(min);
      return (smallestValley * _valleyThresholdMultiplier)
          .toInt(); // Slightly higher than smallest valley
    }
  }
  // If no valleys found, return the invalid threshold sentinel.
  return _invalidThreshold;
}