예제 #1
0
Transform simpleMotionsToTransform(TransformData* td,
                                   const LocalMotions* motions){
  int center_x = 0;
  int center_y = 0;
	Transform t = null_transform();
  if(motions==0) return t;
  int num_motions=vs_vector_size(motions);
  double *angles = (double*) vs_malloc(sizeof(double) * num_motions);
  LocalMotion meanmotion;
  int i;
  if(num_motions < 1)
    return t;

  // calc center point of all remaining fields
  for (i = 0; i < num_motions; i++) {
    center_x += LMGet(motions,i)->f.x;
    center_y += LMGet(motions,i)->f.y;
  }
  center_x /= num_motions;
  center_y /= num_motions;

  // cleaned mean
  meanmotion = cleanmean_localmotions(motions);

  // figure out angle
  if (num_motions < 6) {
    // the angle calculation is inaccurate for 5 and less fields
    t.alpha = 0;
  } else {
    for (i = 0; i < num_motions; i++) {
      // substract avg and calc angle
      LocalMotion m = sub_localmotion(LMGet(motions,i),&meanmotion);
      angles[i] = calcAngle(&m, center_x, center_y);
    }
    double min, max;
    t.alpha = -cleanmean(angles, num_motions, &min, &max);
    if (max - min > td->maxAngleVariation) {
      t.alpha = 0;
      vs_log_info(td->modName, "too large variation in angle(%f)\n",
		  max-min);
    }
  }
  vs_free(angles);
  // compensate for off-center rotation
  double p_x = (center_x - td->fiSrc.width / 2);
  double p_y = (center_y - td->fiSrc.height / 2);
  t.x = meanmotion.v.x + (cos(t.alpha) - 1) * p_x - sin(t.alpha) * p_y;
  t.y = meanmotion.v.y + sin(t.alpha) * p_x + (cos(t.alpha) - 1) * p_y;

  return t;
}
예제 #2
0
/* tries to register current frame onto previous frame.
 *   Algorithm:
 *   discards fields with low contrast
 *   select maxfields fields according to their contrast
 *   check theses fields for vertical and horizontal transformation
 *   use minimal difference of all possible positions
 *   calculate shift as cleaned mean of all remaining fields
 *   calculate rotation angle of each field in respect to center of fields
 *   after shift removal
 *   calculate rotation angle as cleaned mean of all angles
 *   compensate for possibly off-center rotation
 */
Transform calcTransFields(MotionDetect* md, calcFieldTransFunc fieldfunc,
                         contrastSubImgFunc contrastfunc) {
  Transform* ts = (Transform*) ds_malloc(sizeof(Transform) * md->fieldNum);
  Field** fs = (Field**) ds_malloc(sizeof(Field*) * md->fieldNum);
  double *angles = (double*) ds_malloc(sizeof(double) * md->fieldNum);
  int i, index = 0, num_trans;
  Transform t;
#ifdef STABVERBOSE
  FILE *file = NULL;
  char buffer[32];
  ds_snprintf(buffer, sizeof(buffer), "k%04i.dat", md->frameNum);
  file = fopen(buffer, "w");
  fprintf(file, "# plot \"%s\" w l, \"\" every 2:1:0\n", buffer);
#endif

  DSVector goodflds = selectfields(md, contrastfunc);
  // use all "good" fields and calculate optimal match to previous frame
#ifdef USE_OMP
#pragma omp parallel for shared(goodflds, md, ts, fs) // does not bring speedup
#endif
  for(index=0; index < ds_vector_size(&goodflds); index++){
    int i = ((contrast_idx*)ds_vector_get(&goodflds,index))->index;

    t = fieldfunc(md, &md->fields[i], i); // e.g. calcFieldTransYUV
#ifdef STABVERBOSE
    fprintf(file, "%i %i\n%f %f %i\n \n\n", md->fields[i].x, md->fields[i].y,
        md->fields[i].x + t.x, md->fields[i].y + t.y, t.extra);
#endif
    if (t.extra != -1) { // ignore if extra == -1 (unused at the moment)
      ts[index] = t;
      fs[index] = md->fields + i;
    }
  }

  t = null_transform();
  num_trans = ds_vector_size(&goodflds); // amount of transforms we actually have
  ds_vector_del(&goodflds);
  if (num_trans < 1) {
    ds_log_warn(md->modName, "too low contrast! No field remains.\n"
                             "(no translations are detected in frame %i)", md->frameNum);
    return t;
  }

  int center_x = 0;
  int center_y = 0;
  // calc center point of all remaining fields
  for (i = 0; i < num_trans; i++) {
    center_x += fs[i]->x;
    center_y += fs[i]->y;
  }
  center_x /= num_trans;
  center_y /= num_trans;

  if (md->show) { // draw fields and transforms into frame.
    // this has to be done one after another to handle possible overlap
    if (md->show > 1) {
      for (i = 0; i < num_trans; i++)
        drawFieldScanArea(md, fs[i], &ts[i]);
    }
    for (i = 0; i < num_trans; i++)
      drawField(md, fs[i], &ts[i]);
    for (i = 0; i < num_trans; i++)
      drawFieldTrans(md, fs[i], &ts[i]);
  }
  /* median over all transforms
     t= median_xy_transform(ts, md->field_num);*/
  // cleaned mean
  t = cleanmean_xy_transform(ts, num_trans);

  // substract avg
  for (i = 0; i < num_trans; i++) {
    ts[i] = sub_transforms(&ts[i], &t);
  }
  // figure out angle
  if (md->fieldNum < 6) {
    // the angle calculation is inaccurate for 5 and less fields
    t.alpha = 0;
  } else {
    for (i = 0; i < num_trans; i++) {
      angles[i] = calcAngle(md, fs[i], &ts[i], center_x, center_y);
    }
    double min, max;
    t.alpha = -cleanmean(angles, num_trans, &min, &max);
    if (max - min > md->maxAngleVariation) {
      t.alpha = 0;
      ds_log_info(md->modName, "too large variation in angle(%f)\n",
                  max-min);
    }
  }
  // compensate for off-center rotation
  double p_x = (center_x - md->fi.width / 2);
  double p_y = (center_y - md->fi.height / 2);
  t.x += (cos(t.alpha) - 1) * p_x - sin(t.alpha) * p_y;
  t.y += sin(t.alpha) * p_x + (cos(t.alpha) - 1) * p_y;

#ifdef STABVERBOSE
  fclose(file);
#endif
  return t;
}