Esempio n. 1
0
template <typename PointSource, typename PointTarget> void
pcl::registration::CorrespondenceEstimation<PointSource, PointTarget>::determineReciprocalCorrespondences (
    pcl::Correspondences &correspondences)
{
  typedef typename pcl::traits::fieldList<PointSource>::type FieldListSource;
  typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget;
  typedef typename pcl::intersect<FieldListSource, FieldListTarget>::type FieldList;
  
  if (!initCompute ())
    return;

  if (!target_)
  {
    PCL_WARN ("[pcl::%s::compute] No input target dataset was given!\n", getClassName ().c_str ());
    return;
  }

  // setup tree for reciprocal search
  pcl::KdTreeFLANN<PointSource> tree_reciprocal;
  tree_reciprocal.setInputCloud (input_, indices_);

  correspondences.resize (indices_->size());
  std::vector<int> index (1);
  std::vector<float> distance (1);
  std::vector<int> index_reciprocal (1);
  std::vector<float> distance_reciprocal (1);
  pcl::Correspondence corr;
  unsigned int nr_valid_correspondences = 0;

  for (size_t i = 0; i < indices_->size (); ++i)
  {
    // Copy the source data to a target PointTarget format so we can search in the tree
    PointTarget pt_src;
    pcl::for_each_type <FieldList> (pcl::NdConcatenateFunctor <PointSource, PointTarget> (
          input_->points[(*indices_)[i]], 
          pt_src));

    //tree_->nearestKSearch (input_->points[(*indices_)[i]], 1, index, distance);
    tree_->nearestKSearch (pt_src, 1, index, distance);

    // Copy the target data to a target PointSource format so we can search in the tree_reciprocal
    PointSource pt_tgt;
    pcl::for_each_type <FieldList> (pcl::NdConcatenateFunctor <PointTarget, PointSource> (
          target_->points[index[0]],
          pt_tgt));
    //tree_reciprocal.nearestKSearch (target_->points[index[0]], 1, index_reciprocal, distance_reciprocal);
    tree_reciprocal.nearestKSearch (pt_tgt, 1, index_reciprocal, distance_reciprocal);

    if ((*indices_)[i] == index_reciprocal[0])
    {
      corr.index_query = (*indices_)[i];
      corr.index_match = index[0];
      corr.distance = distance[0];
      correspondences[nr_valid_correspondences] = corr;
      ++nr_valid_correspondences;
    }
  }
  correspondences.resize (nr_valid_correspondences);

  deinitCompute ();
}
template <typename PointSource, typename PointTarget, typename Scalar> void
pcl::registration::CorrespondenceEstimation<PointSource, PointTarget, Scalar>::determineReciprocalCorrespondences (
    pcl::Correspondences &correspondences, double max_distance)
{
  if (!initCompute ())
    return;
  
  typedef typename pcl::traits::fieldList<PointSource>::type FieldListSource;
  typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget;
  typedef typename pcl::intersect<FieldListSource, FieldListTarget>::type FieldList;
  
  // setup tree for reciprocal search
  pcl::KdTreeFLANN<PointSource> tree_reciprocal;
  // Set the internal point representation of choice
  if (point_representation_)
    tree_reciprocal.setPointRepresentation (point_representation_);

  tree_reciprocal.setInputCloud (input_, indices_);

  double max_dist_sqr = max_distance * max_distance;

  correspondences.resize (indices_->size());
  std::vector<int> index (1);
  std::vector<float> distance (1);
  std::vector<int> index_reciprocal (1);
  std::vector<float> distance_reciprocal (1);
  pcl::Correspondence corr;
  unsigned int nr_valid_correspondences = 0;
  int target_idx = 0;

  // Check if the template types are the same. If true, avoid a copy.
  // Both point types MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro!
  if (isSamePointType<PointSource, PointTarget> ())
  {
    // Iterate over the input set of source indices
    for (std::vector<int>::const_iterator idx = indices_->begin (); idx != indices_->end (); ++idx)
    {
      tree_->nearestKSearch (input_->points[*idx], 1, index, distance);
      if (distance[0] > max_dist_sqr)
        continue;

      target_idx = index[0];

      tree_reciprocal.nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal);
      if (distance_reciprocal[0] > max_dist_sqr || *idx != index_reciprocal[0])
        continue;

      corr.index_query = *idx;
      corr.index_match = index[0];
      corr.distance = distance[0];
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  else
  {
    PointTarget pt_src;
    PointSource pt_tgt;
   
    // Iterate over the input set of source indices
    for (std::vector<int>::const_iterator idx = indices_->begin (); idx != indices_->end (); ++idx)
    {
      // Copy the source data to a target PointTarget format so we can search in the tree
      pcl::for_each_type <FieldList> (pcl::NdConcatenateFunctor <PointSource, PointTarget> (
            input_->points[*idx], 
            pt_src));

      tree_->nearestKSearch (pt_src, 1, index, distance);
      if (distance[0] > max_dist_sqr)
        continue;

      target_idx = index[0];

      // Copy the target data to a target PointSource format so we can search in the tree_reciprocal
      pcl::for_each_type<FieldList> (pcl::NdConcatenateFunctor <PointTarget, PointSource> (
            target_->points[target_idx],
            pt_tgt));

      tree_reciprocal.nearestKSearch (pt_tgt, 1, index_reciprocal, distance_reciprocal);
      if (distance_reciprocal[0] > max_dist_sqr || *idx != index_reciprocal[0])
        continue;

      corr.index_query = *idx;
      corr.index_match = index[0];
      corr.distance = distance[0];
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  correspondences.resize (nr_valid_correspondences);
  deinitCompute ();
}
template <typename PointSource, typename PointTarget, typename NormalT> void
pcl::registration::CorrespondenceEstimationBackProjection<PointSource, PointTarget, NormalT>::determineReciprocalCorrespondences (
    pcl::Correspondences &correspondences, double max_distance)
{
  if (!initCompute ())
    return;

  typedef typename pcl::traits::fieldList<PointSource>::type FieldListSource;
  typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget;
  typedef typename pcl::intersect<FieldListSource, FieldListTarget>::type FieldList;
  
  // setup tree for reciprocal search
  pcl::KdTreeFLANN<PointSource> tree_reciprocal;
  // Set the internal point representation of choice
  if (point_representation_)
    tree_reciprocal.setPointRepresentation (point_representation_);

  tree_reciprocal.setInputCloud (input_, indices_);

  correspondences.resize (indices_->size ());

  std::vector<int> nn_indices (k_);
  std::vector<float> nn_dists (k_);
  std::vector<int> index_reciprocal (1);
  std::vector<float> distance_reciprocal (1);

  float min_dist = std::numeric_limits<float>::max ();
  int min_index = 0;
  
  pcl::Correspondence corr;
  unsigned int nr_valid_correspondences = 0;
  int target_idx = 0;

  // Check if the template types are the same. If true, avoid a copy.
  // Both point types MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro!
  if (isSamePointType<PointSource, PointTarget> ())
  {
    PointTarget pt;
    // Iterate over the input set of source indices
    for (std::vector<int>::const_iterator idx_i = indices_->begin (); idx_i != indices_->end (); ++idx_i)
    {
      tree_->nearestKSearch (input_->points[*idx_i], k_, nn_indices, nn_dists);

      // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal
      min_dist = std::numeric_limits<float>::max ();
      
      // Find the best correspondence
      for (size_t j = 0; j < nn_indices.size (); j++)
      {
        float cos_angle = source_normals_->points[*idx_i].normal_x * target_normals_->points[nn_indices[j]].normal_x +
                          source_normals_->points[*idx_i].normal_y * target_normals_->points[nn_indices[j]].normal_y +
                          source_normals_->points[*idx_i].normal_z * target_normals_->points[nn_indices[j]].normal_z ;
        float dist = nn_dists[min_index] * (2.0f - cos_angle * cos_angle);
        
        if (dist < min_dist)
        {
          min_dist = dist;
          min_index = j;
        }
      }
      if (min_dist > max_distance)
        continue;

      // Check if the correspondence is reciprocal
      if (target_indices_)
        target_idx = (*target_indices_)[nn_indices[min_index]];
      else
        target_idx = nn_indices[min_index];
      tree_reciprocal.nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal);

      if (*idx_i != index_reciprocal[0])
        continue;

      corr.index_query = *idx_i;
      corr.index_match = nn_indices[min_index];
      corr.distance = nn_dists[min_index];//min_dist;
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  else
  {
    PointTarget pt;
    
    // Iterate over the input set of source indices
    for (std::vector<int>::const_iterator idx_i = indices_->begin (); idx_i != indices_->end (); ++idx_i)
    {
      tree_->nearestKSearch (input_->points[*idx_i], k_, nn_indices, nn_dists);
 
      // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal
      min_dist = std::numeric_limits<float>::max ();
      
      // Find the best correspondence
      for (size_t j = 0; j < nn_indices.size (); j++)
      {
        PointSource pt_src;
        // Copy the source data to a target PointTarget format so we can search in the tree
        pcl::for_each_type <FieldListTarget> (pcl::NdConcatenateFunctor <PointSource, PointTarget> (
            input_->points[*idx_i], 
            pt_src));

        float cos_angle = source_normals_->points[*idx_i].normal_x * target_normals_->points[nn_indices[j]].normal_x +
                          source_normals_->points[*idx_i].normal_y * target_normals_->points[nn_indices[j]].normal_y +
                          source_normals_->points[*idx_i].normal_z * target_normals_->points[nn_indices[j]].normal_z ;
        float dist = nn_dists[min_index] * (2.0f - cos_angle * cos_angle);
        
        if (dist < min_dist)
        {
          min_dist = dist;
          min_index = j;
        }
      }
      if (min_dist > max_distance)
        continue;
      
      // Check if the correspondence is reciprocal
      if (target_indices_)
        target_idx = (*target_indices_)[nn_indices[min_index]];
      else
        target_idx = nn_indices[min_index];
      tree_reciprocal.nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal);

      if (*idx_i != index_reciprocal[0])
        continue;

      corr.index_query = *idx_i;
      corr.index_match = nn_indices[min_index];
      corr.distance = nn_dists[min_index];//min_dist;
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  correspondences.resize (nr_valid_correspondences);
  deinitCompute ();
}
template <typename PointSource, typename PointTarget, typename NormalT, typename Scalar> void
pcl::registration::CorrespondenceEstimationNormalShooting<PointSource, PointTarget, NormalT, Scalar>::determineReciprocalCorrespondences (
    pcl::Correspondences &correspondences, double max_distance)
{
  if (!initCompute ())
    return;

  typedef typename pcl::traits::fieldList<PointSource>::type FieldListSource;
  typedef typename pcl::traits::fieldList<PointTarget>::type FieldListTarget;
  typedef typename pcl::intersect<FieldListSource, FieldListTarget>::type FieldList;
  
  // setup tree for reciprocal search
  // Set the internal point representation of choice
  if (!initComputeReciprocal ())
    return;

  correspondences.resize (indices_->size ());

  std::vector<int> nn_indices (k_);
  std::vector<float> nn_dists (k_);
  std::vector<int> index_reciprocal (1);
  std::vector<float> distance_reciprocal (1);

  double min_dist = std::numeric_limits<double>::max ();
  int min_index = 0;
  
  pcl::Correspondence corr;
  unsigned int nr_valid_correspondences = 0;
  int target_idx = 0;

  // Check if the template types are the same. If true, avoid a copy.
  // Both point types MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro!
  if (isSamePointType<PointSource, PointTarget> ())
  {
    PointTarget pt;
    // Iterate over the input set of source indices
    for (std::vector<int>::const_iterator idx_i = indices_->begin (); idx_i != indices_->end (); ++idx_i)
    {
      tree_->nearestKSearch (input_->points[*idx_i], k_, nn_indices, nn_dists);

      // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal
      min_dist = std::numeric_limits<double>::max ();
      
      // Find the best correspondence
      for (size_t j = 0; j < nn_indices.size (); j++)
      {
        // computing the distance between a point and a line in 3d. 
        // Reference - http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
        pt.x = target_->points[nn_indices[j]].x - input_->points[*idx_i].x;
        pt.y = target_->points[nn_indices[j]].y - input_->points[*idx_i].y;
        pt.z = target_->points[nn_indices[j]].z - input_->points[*idx_i].z;

        const NormalT &normal = source_normals_->points[*idx_i];
        Eigen::Vector3d N (normal.normal_x, normal.normal_y, normal.normal_z);
        Eigen::Vector3d V (pt.x, pt.y, pt.z);
        Eigen::Vector3d C = N.cross (V);
        
        // Check if we have a better correspondence
        double dist = C.dot (C);
        if (dist < min_dist)
        {
          min_dist = dist;
          min_index = static_cast<int> (j);
        }
      }
      if (min_dist > max_distance)
        continue;

      // Check if the correspondence is reciprocal
      target_idx = nn_indices[min_index];
      tree_reciprocal_->nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal);

      if (*idx_i != index_reciprocal[0])
        continue;

      // Correspondence IS reciprocal, save it and continue
      corr.index_query = *idx_i;
      corr.index_match = nn_indices[min_index];
      corr.distance = nn_dists[min_index];//min_dist;
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  else
  {
    PointTarget pt;
    
    // Iterate over the input set of source indices
    for (std::vector<int>::const_iterator idx_i = indices_->begin (); idx_i != indices_->end (); ++idx_i)
    {
      tree_->nearestKSearch (input_->points[*idx_i], k_, nn_indices, nn_dists);

      // Among the K nearest neighbours find the one with minimum perpendicular distance to the normal
      min_dist = std::numeric_limits<double>::max ();
      
      // Find the best correspondence
      for (size_t j = 0; j < nn_indices.size (); j++)
      {
        PointSource pt_src;
        // Copy the source data to a target PointTarget format so we can search in the tree
        pcl::for_each_type <FieldListTarget> (pcl::NdConcatenateFunctor <PointSource, PointTarget> (
            input_->points[*idx_i], 
            pt_src));

        // computing the distance between a point and a line in 3d. 
        // Reference - http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
        pt.x = target_->points[nn_indices[j]].x - pt_src.x;
        pt.y = target_->points[nn_indices[j]].y - pt_src.y;
        pt.z = target_->points[nn_indices[j]].z - pt_src.z;
        
        const NormalT &normal = source_normals_->points[*idx_i];
        Eigen::Vector3d N (normal.normal_x, normal.normal_y, normal.normal_z);
        Eigen::Vector3d V (pt.x, pt.y, pt.z);
        Eigen::Vector3d C = N.cross (V);
        
        // Check if we have a better correspondence
        double dist = C.dot (C);
        if (dist < min_dist)
        {
          min_dist = dist;
          min_index = static_cast<int> (j);
        }
      }
      if (min_dist > max_distance)
        continue;

      // Check if the correspondence is reciprocal
      target_idx = nn_indices[min_index];
      tree_reciprocal_->nearestKSearch (target_->points[target_idx], 1, index_reciprocal, distance_reciprocal);

      if (*idx_i != index_reciprocal[0])
        continue;

      // Correspondence IS reciprocal, save it and continue
      corr.index_query = *idx_i;
      corr.index_match = nn_indices[min_index];
      corr.distance = nn_dists[min_index];//min_dist;
      correspondences[nr_valid_correspondences++] = corr;
    }
  }
  correspondences.resize (nr_valid_correspondences);
  deinitCompute ();
}