ICCVTutorial<FeatureType>::ICCVTutorial(pcl::Keypoint<pcl::PointXYZRGB, pcl::PointXYZI>::Ptr keypoint_detector,
                                        typename pcl::Feature<pcl::PointXYZRGB, FeatureType>::Ptr feature_extractor,
                                        pcl::PCLSurfaceBase<pcl::PointXYZRGBNormal>::Ptr surface_reconstructor,
                                        pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr source,
                                        pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr target)
: source_keypoints_ (new pcl::PointCloud<pcl::PointXYZI> ())
, target_keypoints_ (new pcl::PointCloud<pcl::PointXYZI> ())
, keypoint_detector_ (keypoint_detector)
, feature_extractor_ (feature_extractor)
, surface_reconstructor_ (surface_reconstructor)
, source_ (source)
, target_ (target)
, source_segmented_ (new pcl::PointCloud<pcl::PointXYZRGB>)
, target_segmented_ (new pcl::PointCloud<pcl::PointXYZRGB>)
, source_transformed_ (new pcl::PointCloud<pcl::PointXYZRGB>)
, source_registered_ (new pcl::PointCloud<pcl::PointXYZRGB>)
, source_features_ (new pcl::PointCloud<FeatureType>)
, target_features_ (new pcl::PointCloud<FeatureType>)
, correspondences_ (new pcl::Correspondences)
, show_source2target_ (false)
, show_target2source_ (false)
, show_correspondences (false)
{
  visualizer_.registerKeyboardCallback(&ICCVTutorial::keyboard_callback, *this, nullptr);

  segmentation (source_, source_segmented_);
  segmentation (target_, target_segmented_);

  detectKeypoints (source_segmented_, source_keypoints_);
  detectKeypoints (target_segmented_, target_keypoints_);

  extractDescriptors (source_segmented_, source_keypoints_, source_features_);
  extractDescriptors (target_segmented_, target_keypoints_, target_features_);

  findCorrespondences (source_features_, target_features_, source2target_);
  findCorrespondences (target_features_, source_features_, target2source_);

  filterCorrespondences ();

  determineInitialTransformation ();
  determineFinalTransformation ();

  reconstructSurface ();
}
int main(int argc, char *argv[])
{
  slParams sl_params;
  slCalib sl_calib;

  if( argc < 2 )
  {
    fprintf(stderr, "Usage: %s image_dir [config_file [calib_dir]]\n", argv[0]);
    exit(0);
  }

  if(!loadSLConfigXML(&sl_params, &sl_calib,
        argc>2 ? argv[2] : CONFIG_FILE,
        argc>3 ? argv[3] : NULL))
    fprintf(stderr, "Could not load the Structured Light Configuration XML file!\nPlease correct the file and restart the program.\n");
  else
    fprintf(stderr, "Configuration File Read Successfully!\n");

  printf("outdir: %s\n", sl_params.outdir);
  printf("%d x %d\n", sl_params.cam_w, sl_params.cam_h);
  printf("%d x %d\n", sl_params.proj_w, sl_params.proj_h);
  reconstructSurface(argv[1], &sl_params, &sl_calib);

  cvReleaseMat(&sl_calib.cam_intrinsic);
  cvReleaseMat(&sl_calib.cam_distortion);
  cvReleaseMat(&sl_calib.cam_extrinsic);
  cvReleaseMat(&sl_calib.proj_intrinsic);
  cvReleaseMat(&sl_calib.proj_distortion);
  cvReleaseMat(&sl_calib.proj_extrinsic);
  cvReleaseMat(&sl_calib.cam_center);
  cvReleaseMat(&sl_calib.proj_center);
  cvReleaseMat(&sl_calib.cam_rays);
  cvReleaseMat(&sl_calib.proj_rays);
  cvReleaseMat(&sl_calib.proj_column_planes);
  cvReleaseMat(&sl_calib.proj_row_planes);
  cvReleaseMat(&sl_calib.background_depth_map);
  cvReleaseImage(&sl_calib.background_image);
  cvReleaseImage(&sl_calib.background_mask);

  return 0;
}