calculateThreshold function

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 -1 if a valid threshold couldn't be determined.

Implementation

int calculateThreshold(List<int> histogram) {
  // need at least 3 elements to have a valley
  if (histogram.length >= 3) {
    // 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 - 2; 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 * 1.2)
          .toInt(); // Slightly higher than smallest valley
    }
  }
  // If no valleys found, return -1 to indicate that splitting is not possible
  return -1;
}