Camera tracking: libmv distortion API now also uses camera intrinsics
authorSergey Sharybin <sergey.vfx@gmail.com>
Mon, 25 Feb 2013 09:36:52 +0000 (09:36 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 25 Feb 2013 09:36:52 +0000 (09:36 +0000)
structure instead of passing all the parameters to every function.

Makes it much easier to tweak distortion model.

---
svn merge -r52854:52855 ^/branches/soc-2011-tomato

1  2 
source/blender/blenkernel/intern/tracking.c

index de0be829e8b0b0fa12cefd70bcf8cf68f620e58e,5e8ef23e0007beaf5c9cbc7586c415984d93e523..f625f5c85265472e9d809bbf60c1c9c2d190cb38
@@@ -141,10 -141,8 +141,10 @@@ static void tracking_dopesheet_free(Mov
        }
  
        BLI_freelistN(&dopesheet->channels);
 +      BLI_freelistN(&dopesheet->coverage_segments);
  
        dopesheet->channels.first = dopesheet->channels.last = NULL;
 +      dopesheet->coverage_segments.first = dopesheet->coverage_segments.last = NULL;
        dopesheet->tot_channel = 0;
  }
  
@@@ -171,9 -169,8 +171,9 @@@ void BKE_tracking_settings_init(MovieTr
  
        tracking->settings.default_motion_model = TRACK_MOTION_MODEL_TRANSLATION;
        tracking->settings.default_minimum_correlation = 0.75;
 -      tracking->settings.default_pattern_size = 11;
 +      tracking->settings.default_pattern_size = 15;
        tracking->settings.default_search_size = 61;
 +      tracking->settings.default_algorithm_flag |= TRACK_ALGORITHM_FLAG_USE_BRUTE;
        tracking->settings.dist = 1;
        tracking->settings.object_distance = 1;
        tracking->settings.reconstruction_success_threshold = 1e-3;
@@@ -1429,6 -1426,27 +1429,27 @@@ void BKE_tracking_camera_get_reconstruc
  
  /*********************** Distortion/Undistortion *************************/
  
+ #ifdef WITH_LIBMV
+ static void cameraIntrinscisOptionsFromTracking(libmv_cameraIntrinsicsOptions *camera_intrinsics_options,
+                                                 MovieTracking *tracking, int calibration_width, int calibration_height)
+ {
+       MovieTrackingCamera *camera = &tracking->camera;
+       float aspy = 1.0f / tracking->camera.pixel_aspect;
+       camera_intrinsics_options->focal_length = camera->focal;
+       camera_intrinsics_options->principal_point_x = camera->principal[0];
+       camera_intrinsics_options->principal_point_y = camera->principal[1] * aspy;
+       camera_intrinsics_options->k1 = camera->k1;
+       camera_intrinsics_options->k2 = camera->k2;
+       camera_intrinsics_options->k3 = camera->k3;
+       camera_intrinsics_options->image_width = calibration_width;
+       camera_intrinsics_options->image_height = (double) calibration_height * aspy;
+ }
+ #endif
  MovieDistortion *BKE_tracking_distortion_new(void)
  {
        MovieDistortion *distortion;
  void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking *tracking,
                                      int calibration_width, int calibration_height)
  {
-       MovieTrackingCamera *camera = &tracking->camera;
-       float aspy = 1.0f / tracking->camera.pixel_aspect;
  #ifdef WITH_LIBMV
+       libmv_cameraIntrinsicsOptions camera_intrinsics_options;
+       cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking,
+                                           calibration_width, calibration_height);
        if (!distortion->intrinsics) {
-               distortion->intrinsics = libmv_CameraIntrinsicsNew(camera->focal,
-                                                                  camera->principal[0], camera->principal[1] * aspy,
-                                                                  camera->k1, camera->k2, camera->k3,
-                                                                  calibration_width, calibration_height * aspy);
+               distortion->intrinsics = libmv_CameraIntrinsicsNew(&camera_intrinsics_options);
        }
        else {
-               libmv_CameraIntrinsicsUpdate(distortion->intrinsics, camera->focal,
-                                            camera->principal[0], camera->principal[1] * aspy,
-                                            camera->k1, camera->k2, camera->k3,
-                                            calibration_width, calibration_height * aspy);
+               libmv_CameraIntrinsicsUpdate(distortion->intrinsics, &camera_intrinsics_options);
        }
  #else
        (void) distortion;
@@@ -1543,15 -1557,17 +1560,17 @@@ void BKE_tracking_distort_v2(MovieTrack
        MovieTrackingCamera *camera = &tracking->camera;
  
  #ifdef WITH_LIBMV
+       libmv_cameraIntrinsicsOptions camera_intrinsics_options;
        double x, y;
        float aspy = 1.0f / tracking->camera.pixel_aspect;
  
+       cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
        /* normalize coords */
        x = (co[0] - camera->principal[0]) / camera->focal;
        y = (co[1] - camera->principal[1] * aspy) / camera->focal;
  
-       libmv_applyCameraIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
-                                   camera->k1, camera->k2, camera->k3, x, y, &x, &y);
+       libmv_applyCameraIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
  
        /* result is in image coords already */
        r_co[0] = x;
@@@ -1568,11 -1584,13 +1587,13 @@@ void BKE_tracking_undistort_v2(MovieTra
        MovieTrackingCamera *camera = &tracking->camera;
  
  #ifdef WITH_LIBMV
+       libmv_cameraIntrinsicsOptions camera_intrinsics_options;
        double x = co[0], y = co[1];
        float aspy = 1.0f / tracking->camera.pixel_aspect;
  
-       libmv_InvertIntrinsics(camera->focal, camera->principal[0], camera->principal[1] * aspy,
-                              camera->k1, camera->k2, camera->k3, x, y, &x, &y);
+       cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, 0, 0);
+       libmv_InvertIntrinsics(&camera_intrinsics_options, x, y, &x, &y);
  
        r_co[0] = x * camera->focal + camera->principal[0];
        r_co[1] = y * camera->focal + camera->principal[1] * aspy;
@@@ -1607,67 -1625,6 +1628,67 @@@ ImBuf *BKE_tracking_distort_frame(Movie
                                            calibration_height, overscan, FALSE);
  }
  
 +void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2])
 +{
 +      int a;
 +      float pos[2], warped_pos[2];
 +      const int coord_delta = 5;
 +
 +      delta[0] = delta[1] = -FLT_MAX;
 +
 +      for (a = rect->xmin; a <= rect->xmax + coord_delta; a += coord_delta) {
 +              if (a > rect->xmax)
 +                      a = rect->xmax;
 +
 +              /* bottom edge */
 +              pos[0] = a;
 +              pos[1] = rect->ymin;
 +
 +              BKE_tracking_undistort_v2(tracking, pos, warped_pos);
 +
 +              delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
 +              delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
 +
 +              /* top edge */
 +              pos[0] = a;
 +              pos[1] = rect->ymax;
 +
 +              BKE_tracking_undistort_v2(tracking, pos, warped_pos);
 +
 +              delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
 +              delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
 +
 +              if (a >= rect->xmax)
 +                      break;
 +      }
 +
 +      for (a = rect->ymin; a <= rect->ymax + coord_delta; a += coord_delta) {
 +              if (a > rect->ymax)
 +                      a = rect->ymax;
 +
 +              /* left edge */
 +              pos[0] = rect->xmin;
 +              pos[1] = a;
 +
 +              BKE_tracking_undistort_v2(tracking, pos, warped_pos);
 +
 +              delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
 +              delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
 +
 +              /* right edge */
 +              pos[0] = rect->xmax;
 +              pos[1] = a;
 +
 +              BKE_tracking_undistort_v2(tracking, pos, warped_pos);
 +
 +              delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0]));
 +              delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1]));
 +
 +              if (a >= rect->ymax)
 +                      break;
 +      }
 +}
 +
  /*********************** Image sampling *************************/
  
  static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale)
@@@ -1724,7 -1681,7 +1745,7 @@@ ImBuf *BKE_tracking_sample_pattern(int 
        /* real sampling requires libmv, but areas are supposing pattern would be
         * sampled if search area does exists, so we'll need to create empty
         * pattern area here to prevent adding NULL-checks all over just to deal
 -       * with situation when lubmv is disabled
 +       * with situation when libmv is disabled
         */
  
        (void) frame_width;
@@@ -3008,6 -2965,9 +3029,9 @@@ static void camraIntrincicsOptionsFromC
        camera_intrinsics_options->k1 = context->k1;
        camera_intrinsics_options->k2 = context->k2;
        camera_intrinsics_options->k3 = context->k3;
+       camera_intrinsics_options->image_width = 0;
+       camera_intrinsics_options->image_height = 0;
  }
  
  static void reconstructionOptionsFromContext(libmv_reconstructionOptions *reconstruction_options,
@@@ -3546,15 -3506,15 +3570,15 @@@ ImBuf *BKE_tracking_stabilize_frame(Mov
                BKE_tracking_stabilization_data_to_mat4(ibuf->x, ibuf->y, aspect, tloc, tscale, tangle, mat);
                invert_m4(mat);
  
 -              if (filter == TRACKING_FILTER_NEAREAST)
 -                      interpolation = neareast_interpolation;
 +              if (filter == TRACKING_FILTER_NEAREST)
 +                      interpolation = nearest_interpolation;
                else if (filter == TRACKING_FILTER_BILINEAR)
                        interpolation = bilinear_interpolation;
                else if (filter == TRACKING_FILTER_BICUBIC)
                        interpolation = bicubic_interpolation;
                else
                        /* fallback to default interpolation method */
 -                      interpolation = neareast_interpolation;
 +                      interpolation = nearest_interpolation;
  
                for (j = 0; j < tmpibuf->y; j++) {
                        for (i = 0; i < tmpibuf->x; i++) {
@@@ -3806,88 -3766,6 +3830,88 @@@ static void tracking_dopesheet_sort(Mov
        }
  }
  
 +static int coverage_from_count(int count)
 +{
 +      if (count < 8)
 +              return TRACKING_COVERAGE_BAD;
 +      else if (count < 16)
 +              return TRACKING_COVERAGE_ACCEPTABLE;
 +      return TRACKING_COVERAGE_OK;
 +}
 +
 +static void tracking_dopesheet_calc_coverage(MovieTracking *tracking)
 +{
 +      MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
 +      MovieTrackingObject *object = BKE_tracking_object_get_active(tracking);
 +      ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object);
 +      MovieTrackingTrack *track;
 +      int frames, start_frame = INT_MAX, end_frame = -INT_MAX;
 +      int *per_frame_counter;
 +      int prev_coverage, last_segment_frame;
 +      int i;
 +
 +      /* find frame boundaries */
 +      for (track = tracksbase->first; track; track = track->next) {
 +              start_frame = min_ii(start_frame, track->markers[0].framenr);
 +              end_frame = max_ii(end_frame, track->markers[track->markersnr - 1].framenr);
 +      }
 +
 +      frames = end_frame - start_frame + 1;
 +
 +      /* this is a per-frame counter of markers (how many markers belongs to the same frame) */
 +      per_frame_counter = MEM_callocN(sizeof(int) * frames, "per frame track counter");
 +
 +      /* find per-frame markers count */
 +      for (track = tracksbase->first; track; track = track->next) {
 +              int i;
 +
 +              for (i = 0; i < track->markersnr; i++) {
 +                      MovieTrackingMarker *marker = &track->markers[i];
 +
 +                      /* TODO: perhaps we need to add check for non-single-frame track here */
 +                      if ((marker->flag & MARKER_DISABLED) == 0)
 +                              per_frame_counter[marker->framenr - start_frame]++;
 +              }
 +      }
 +
 +      /* convert markers count to coverage and detect segments with the same coverage */
 +      prev_coverage = coverage_from_count(per_frame_counter[0]);
 +      last_segment_frame = start_frame;
 +
 +      /* means only disabled tracks in the beginning, could be ignored */
 +      if (!per_frame_counter[0])
 +              prev_coverage = TRACKING_COVERAGE_OK;
 +
 +      for (i = 1; i < frames; i++) {
 +              int coverage = coverage_from_count(per_frame_counter[i]);
 +
 +              /* means only disabled tracks in the end, could be ignored */
 +              if (i == frames - 1 && !per_frame_counter[i])
 +                      coverage = TRACKING_COVERAGE_OK;
 +
 +              if (coverage != prev_coverage || i == frames - 1) {
 +                      MovieTrackingDopesheetCoverageSegment *coverage_segment;
 +                      int end_segment_frame = i - 1 + start_frame;
 +
 +                      if (end_segment_frame == last_segment_frame)
 +                              end_segment_frame++;
 +
 +                      coverage_segment = MEM_callocN(sizeof(MovieTrackingDopesheetCoverageSegment), "tracking coverage segment");
 +                      coverage_segment->coverage = prev_coverage;
 +                      coverage_segment->start_frame = last_segment_frame;
 +                      coverage_segment->end_frame = end_segment_frame;
 +
 +                      BLI_addtail(&dopesheet->coverage_segments, coverage_segment);
 +
 +                      last_segment_frame = end_segment_frame;
 +              }
 +
 +              prev_coverage = coverage;
 +      }
 +
 +      MEM_freeN(per_frame_counter);
 +}
 +
  void BKE_tracking_dopesheet_tag_update(MovieTracking *tracking)
  {
        MovieTrackingDopesheet *dopesheet = &tracking->dopesheet;
@@@ -3915,7 -3793,6 +3939,7 @@@ void BKE_tracking_dopesheet_update(Movi
  
        reconstruction = BKE_tracking_object_get_reconstruction(tracking, object);
  
 +      /* channels */
        for (track = tracksbase->first; track; track = track->next) {
                MovieTrackingDopesheetChannel *channel;
  
  
        tracking_dopesheet_sort(tracking, sort_method, inverse);
  
 +      /* frame coverage */
 +      tracking_dopesheet_calc_coverage(tracking);
 +
        dopesheet->ok = TRUE;
  }