Listing 6 Code implementing the histogram valley technique

   /*********************************************
   *   valley_threshold_segmentation(...
   *   This function segments an image using
   *   thresholdlng. It uses the histogram valleys
   *   to find the hi and low values of the
   *   threshold.
   *   If the segment parameter is 0, you only
   *   threshold the array - you do not segment.
   ***********************************************/

valley_threshold_segmentation(in_name, out_name,
                              the_image, out_image,
                              il, ie, ll, le,
                              value, segment)
   char   in_name[], out_name[];
   int    il, ie, ll, ie, segment;
   short  the_image[ROWS] [COLS],
         out_image[ROWS][COLS], value;
{
   int      length, peak1, peak2, width;
   short    hi, low;
   struct   tiff_header_struct image_header;
   unsigned long-histogram[GRAY_LEVELS+1];
   
   if(does_not_exist(out_name)){
      printf{"\n\nVTS> output file does not exist %s", out_name);
      read_tiff_header(in_name, &image_header);
      round_off_image_size(&image_header, &length, &width);
      image_header.image_length = length*ROWS;
      image_header.image_width  = width*COLS;
      create_allocate tiff_file(out_name, &image_header, out_image);
   }  /* ends if does_not_exist */
   
   read_tiff_image(in_name, the_image, il, ie, ll, ie);
   zero_histogram(histogram);
   calculate_histogram(the_image, histogram);
   smooth_histogram(histogram);
   find_peaks(histogram, &peak1, &peak2);
   valley_high_low(histogram, peak1, peak2, &hi, &low);
   threshold_image_array(the_image, out_image, hi, low, value);
   if(segment == 1)
      grow(out_image, value);
   write_array_into_tiff_image(out_name, out_image, il, ie, ll, le);

}  /* ends valley_threshold_segmentation */

     /******************************************
     *   valley_high_low(...
     *   This function uses the histogram array
     *   and the valleys to find the best high and
     *   low threshold values for the threshold
     *   function. You want the hi and low values
     *   so that you will threshold the image around
     *   the smaller of the two "humps" in the
     *   histogram. This is because the smaller
     *   hump represents the objects while the
     *   larger hump represents the background.
     *******************************************/

valley_high_low(histogram, peak1, peak2, hi, low)
   int peak1, peak2;
   short *hi, *low;
   unsigned long histogram[];
{
   int i, valley_point;
   unsigned long sum1 = 0, sum2 = 0;
   
   find_valley_point(histogram, peak1, peak2, &valley_point);
   /*printf("\nVHL> valley point is %d", valley_point);*/
   
   for(i=0; i<valley_point; i++)
      sum1 = sum1 + histogram[i];
   for(i=valley_point; i<=GRAY LEVELS; i++)
      sum2 = sum2 + histogram"[i];
   
   if(sum1 >= sum2){
      *low = valley point;
      *hi  = GRAY_LEVELS;
   }
   else{
      *low = 0;
      *hi = valley_point;
   }

}  /* ends valley_high low */

   /******************************************
   *   find_valley_point(...
   *   This function finds the low point of
   *   the valley between two peaks in a
   *   histogram. It starts at the lowest
   *   peak and works its way up to the
   *   highest peak. Along the way, it looks
   *   at each point in the histogram and inserts
   *   them into a list of points. When done,
   *   it has the location of the smallest histogram
   *   point - that is the valley point.
   *   The deltas array holds the delta value
   *   in the first place and its location in
   *   the second place.
   *******************************************/

find_valley_point(histogram, peak1, peak2, valley_point)
   int peak1, peak2, *valley_point;
   unsigned long histogram[];
{
   int       deltas[PEAKS][2], delta_hist, i;
   for(i=0; i<PEAKS; i++){
      deltas[i][0] = 10000;
      deltas[i][1] = -1;

   if(peak1 < peak2){
      for(i=peak1+1; i<peak2; i++){
         delta_hist = (int)(histogram[i]);
         insert_into_deltas(deltas, delta_hist, i);
      }  /* ends loop over i */
   }  /* ends if peak1 < peak2 */
   
   if(peak2 < peak1){
      for(i=peak2+1; i<peak1; i++){
         delta_hist = (int)(histogram[i]);
         insert_into_deltas(deltas, delta_hist, i);
      }  /* ends loop over i */
   }  /* ends if peak2 < peak1 */
   
   *valley_point = deltas[0][1];

}  /* ends find valley_point */

   /****************************************
   *   insert_into_deltas(...
   *   This function inserts histogram deltas
   *   into a deltas array. The smallest delta
   *   will be at the top of the array.
   *   The objective is to build a list of
   *   histogram area deltas and thier locations.
   *   The deltas array holds the delta value
   *   in the first place and its location in
   *   the second place.
   *******************************************/
insert_into_deltas(deltas, value, place)
   int value, place, deltas[PEAKS] [2];
{
   int i, j;
      /* first case */
   if(value < deltas[0] [0]){
      for(i=PEAKS-1; i>0; i--){
         deltas[i][0] = deltas[i-1][[0];
         deltas[i] [1] = deltas[i-1] [1];
      }
      deltas[0] [0] = value;
      deltas[0][1] = place;
   }  /* ends if */
   
      /* middle cases */
   for(j=0; j<PEAKS-3; j++){
      if(value > deltas[j][0] &&
         value < deltas [j+1] [0] ) {
         for(i=PEAKS-1; i>j+1; i--){
            deltas[i][0] = deltas[i-1][0];
            deltas[i][1] = deltas[i-1][1];
         }
         deltas[j+1][0] = value;
         deltas[j+1][1] = place;
      }  /* ends if */
   }  /* ends loop over j */

      /* last case */
   if(value > deltas[PEAKS-2][0]  &&
      value < deltas[PEAKS-i][o]){
      deltas[PEAKS-1][0] = value;
      deltas[PEAKS-1][1] = place;
   }  /* ends if */

}  /* ends insert_into_deltas */
/* End of File */