void LMS::fit(               //fit sample
              float &out_m,  //output line
              float &out_c) {
  inT32 index;                   //of median
  inT32 trials;                  //no of medians
  float test_m, test_c;          //candidate line
  float test_error;              //error of test line

  switch (samplecount) {
    case 0:
      m = 0.0f;                  //no info
      c = 0.0f;
      line_error = 0.0f;
      break;

    case 1:
      m = 0.0f;
      c = samples[0].y ();       //horiz thru pt
      line_error = 0.0f;
      break;

    case 2:
      if (samples[0].x () != samples[1].x ()) {
        m = (samples[1].y () - samples[0].y ())
          / (samples[1].x () - samples[0].x ());
        c = samples[0].y () - m * samples[0].x ();
      }
      else {
        m = 0.0f;
        c = (samples[0].y () + samples[1].y ()) / 2;
      }
      line_error = 0.0f;
      break;

    default:
      pick_line(m, c);  //use pts at random
      compute_errors(m, c);  //from given line
      index = choose_nth_item (samplecount / 2, errors, samplecount);
      line_error = errors[index];
      for (trials = 1; trials < lms_line_trials; trials++) {
                                 //random again
        pick_line(test_m, test_c);
        compute_errors(test_m, test_c);
        index = choose_nth_item (samplecount / 2, errors, samplecount);
        test_error = errors[index];
        if (test_error < line_error) {
                                 //find least median
          line_error = test_error;
          m = test_m;
          c = test_c;
        }
      }
  }
  fitted = TRUE;
  out_m = m;
  out_c = c;
  a = 0;
}
void LMS::constrained_fit(                //fit sample
                          float fixed_m,  //forced gradient
                          float &out_c) {
  inT32 index;                   //of median
  inT32 trials;                  //no of medians
  float test_c;                  //candidate line
  static uinT16 seeds[3] = { SEED1, SEED2, SEED3 };
  //for nrand
  float test_error;              //error of test line

  m = fixed_m;
  switch (samplecount) {
    case 0:
      c = 0.0f;
      line_error = 0.0f;
      break;

    case 1:
                                 //horiz thru pt
      c = samples[0].y () - m * samples[0].x ();
      line_error = 0.0f;
      break;

    case 2:
      c = (samples[0].y () + samples[1].y ()
        - m * (samples[0].x () + samples[1].x ())) / 2;
      line_error = m * samples[0].x () + c - samples[0].y ();
      line_error *= line_error;
      break;

    default:
      index = (inT32) nrand48 (seeds) % samplecount;
                                 //compute line
      c = samples[index].y () - m * samples[index].x ();
      compute_errors(m, c);  //from given line
      index = choose_nth_item (samplecount / 2, errors, samplecount);
      line_error = errors[index];
      for (trials = 1; trials < lms_line_trials; trials++) {
        index = (inT32) nrand48 (seeds) % samplecount;
        test_c = samples[index].y () - m * samples[index].x ();
        //compute line
        compute_errors(m, test_c);
        index = choose_nth_item (samplecount / 2, errors, samplecount);
        test_error = errors[index];
        if (test_error < line_error) {
                                 //find least median
          line_error = test_error;
          c = test_c;
        }
      }
  }
  fitted = TRUE;
  out_c = c;
  a = 0;
}
示例#3
0
// Compute all the cross product distances of the points from the line
// and return the true squared upper quartile distance.
double DetLineFit::ComputeErrors(const ICOORD start, const ICOORD end,
                                 int* distances) {
  ICOORDELT_IT it(&pt_list_);
  ICOORD line_vector = end;
  line_vector -= start;
  // Compute the distance of each point from the line.
  int pt_index = 0;
  for (it.mark_cycle_pt(); !it.cycled_list(); it.forward()) {
    ICOORD pt_vector = *it.data();
    pt_vector -= start;
    // Compute |line_vector||pt_vector|sin(angle between)
    int dist = line_vector * pt_vector;
    if (dist < 0)
      dist = -dist;
    distances[pt_index++] = dist;
  }
  // Now get the upper quartile distance.
  int index = choose_nth_item(3 * pt_index / 4, distances, pt_index,
                              sizeof(distances[0]), CompareInts);
  double dist = distances[index];
  // The true distance is the square root of the dist squared / the
  // squared length of line_vector (which is the dot product with itself)
  // Don't bother with the square root. Just return the square distance.
  return dist * dist / (line_vector % line_vector);
}
float LMS::compute_quadratic_errors(                          //fit sample
                                    float outlier_threshold,  //min outlier
                                    double line_a,
                                    float line_m,             //input gradient
                                    float line_c) {
  inT32 outlier_count;           //total outliers
  inT32 index;                   //picked point
  inT32 error_count;             //no in total
  double total_error;            //summed squares

  total_error = 0;
  outlier_count = 0;
  error_count = 0;
  for (index = 0; index < samplecount; index++) {
    errors[error_count] = line_c + samples[index].x ()
      * (line_m + samples[index].x () * line_a) - samples[index].y ();
    errors[error_count] *= errors[error_count];
    if (errors[error_count] > outlier_threshold) {
      outlier_count++;
      errors[samplecount - outlier_count] = errors[error_count];
    }
    else {
      total_error += errors[error_count++];
    }
  }
  if (outlier_count * 3 < error_count)
    return total_error / error_count;
  else {
    index = choose_nth_item (outlier_count / 2,
      errors + samplecount - outlier_count,
      outlier_count);
    //median outlier
    return errors[samplecount - outlier_count + index];
  }
}
示例#5
0
DLLSYM inT32
choose_nth_item (                //fast median
inT32 index,                     //index to choose
void *array,                     //array of items
inT32 count,                     //no of items
size_t size,                     //element size
                                 //comparator
int (*compar) (const void *, const void *)
) {
  int result;                    //of compar
  inT32 next_sample;             //next one to do
  inT32 next_lesser;             //space for new
  inT32 prev_greater;            //last one saved
  inT32 equal_count;             //no of equal ones
  inT32 pivot;                   //proposed median

  if (count <= 1)
    return 0;
  if (count == 2) {
    if (compar (array, (char *) array + size) < 0) {
      return index >= 1 ? 1 : 0;
    }
    else {
      return index >= 1 ? 0 : 1;
    }
  }
  if (index < 0)
    index = 0;                   //ensure lergal
  else if (index >= count)
    index = count - 1;
  pivot = (inT32) (rand () % count);
  swap_entries (array, size, pivot, 0);
  next_lesser = 0;
  prev_greater = count;
  equal_count = 1;
  for (next_sample = 1; next_sample < prev_greater;) {
    result =
      compar ((char *) array + size * next_sample,
      (char *) array + size * next_lesser);
    if (result < 0) {
      swap_entries (array, size, next_lesser++, next_sample++);
      //shuffle
    }
    else if (result > 0) {
      prev_greater--;
      swap_entries(array, size, prev_greater, next_sample);
    }
    else {
      equal_count++;
      next_sample++;
    }
  }
  if (index < next_lesser)
    return choose_nth_item (index, array, next_lesser, size, compar);
  else if (index < prev_greater)
    return next_lesser;          //in equal bracket
  else
    return choose_nth_item (index - prev_greater,
      (char *) array + size * prev_greater,
      count - prev_greater, size,
      compar) + prev_greater;
}
示例#6
0
DLLSYM inT32 choose_nth_item(               //fast median
                             inT32 index,   //index to choose
                             float *array,  //array of items
                             inT32 count    //no of items
                            ) {
  inT32 next_sample;             //next one to do
  inT32 next_lesser;             //space for new
  inT32 prev_greater;            //last one saved
  inT32 equal_count;             //no of equal ones
  float pivot;                   //proposed median
  float sample;                  //current sample

  if (count <= 1)
    return 0;
  if (count == 2) {
    if (array[0] < array[1]) {
      return index >= 1 ? 1 : 0;
    }
    else {
      return index >= 1 ? 0 : 1;
    }
  }
  else {
    if (index < 0)
      index = 0;                 //ensure lergal
    else if (index >= count)
      index = count - 1;
    equal_count = (inT32) (rand() % count);
    pivot = array[equal_count];
                                 //fill gap
    array[equal_count] = array[0];
    next_lesser = 0;
    prev_greater = count;
    equal_count = 1;
    for (next_sample = 1; next_sample < prev_greater;) {
      sample = array[next_sample];
      if (sample < pivot) {
                                 //shuffle
        array[next_lesser++] = sample;
        next_sample++;
      }
      else if (sample > pivot) {
        prev_greater--;
                                 //juggle
        array[next_sample] = array[prev_greater];
        array[prev_greater] = sample;
      }
      else {
        equal_count++;
        next_sample++;
      }
    }
    for (next_sample = next_lesser; next_sample < prev_greater;)
      array[next_sample++] = pivot;
    if (index < next_lesser)
      return choose_nth_item (index, array, next_lesser);
    else if (index < prev_greater)
      return next_lesser;        //in equal bracket
    else
      return choose_nth_item (index - prev_greater,
        array + prev_greater,
        count - prev_greater) + prev_greater;
  }
}