Ejemplo n.º 1
0
template <typename PointInT, typename PointOutT> void
pcl::AgastKeypoint2D<PointInT, PointOutT>::detectKeypoints (PointCloudOut &output)
{
  // image size
  const size_t width = input_->width;
  const size_t height = input_->height;

  // destination for intensity data; will be forwarded to AGAST
  std::vector<unsigned char> image_data (width*height);

  for (size_t row_index = 0; row_index < height; ++row_index)
    for (size_t col_index = 0; col_index < width; ++col_index)
      image_data[row_index*width + col_index] = static_cast<unsigned char> (intensity_ ((*input_) (col_index, row_index)));

  if (!detector_)
    detector_.reset (new pcl::keypoints::agast::AgastDetector7_12s (width, height, threshold_, bmax_));

  if (apply_non_max_suppression_)
  {
    pcl::PointCloud<pcl::PointUV> tmp_cloud;
    detector_->detectKeypoints (image_data, tmp_cloud);

    pcl::keypoints::internal::AgastApplyNonMaxSuppresion<PointOutT> anms (
        image_data, tmp_cloud, detector_, output);
  }
  else
  {
    pcl::keypoints::internal::AgastDetector<PointOutT> dec (
        image_data, detector_, output);
  }

  // we do not change the denseness
  output.is_dense = true;
}
Ejemplo n.º 2
0
template <typename PointInT, typename PointOutT, typename IntensityT> void
pcl::BriskKeypoint2D<PointInT, PointOutT, IntensityT>::detectKeypoints (PointCloudOut &output)
{
  // image size
  const int width = int (input_->width);
  const int height = int (input_->height);

  // destination for intensity data; will be forwarded to BRISK
  std::vector<unsigned char> image_data (width*height);

  for (size_t i = 0; i < image_data.size (); ++i)
    image_data[i] = static_cast<unsigned char> (intensity_ ((*input_)[i]));

  pcl::keypoints::brisk::ScaleSpace brisk_scale_space (octaves_);
  brisk_scale_space.constructPyramid (image_data, width, height);
  // Check if the template types are the same. If true, avoid a copy.
  // The PointOutT MUST be registered using the POINT_CLOUD_REGISTER_POINT_STRUCT macro!
  if (isSamePointType<PointOutT, pcl::PointWithScale> ())
    brisk_scale_space.getKeypoints (threshold_, output.points);
  else
  {
    pcl::PointCloud<pcl::PointWithScale> output_temp;
    brisk_scale_space.getKeypoints (threshold_, output_temp.points);
    pcl::copyPointCloud<pcl::PointWithScale, PointOutT> (output_temp, output);
  }

  // we do not change the denseness
  output.width = int (output.points.size ());
  output.height = 1;
  output.is_dense = false;      // set to false to be sure

  // 2nd pass to remove the invalid set of 3D keypoints
  if (remove_invalid_3D_keypoints_)
  {
    PointCloudOut output_clean;
    for (size_t i = 0; i < output.size (); ++i)
    {
      PointOutT pt;
      // Interpolate its position in 3D, as the "u" and "v" are subpixel accurate
      bilinearInterpolation (input_, output[i].x, output[i].y, pt);

      // Check if the point is finite
      if (pcl::isFinite (pt))
        output_clean.push_back (output[i]);
    }
    output = output_clean;
    output.is_dense = true;      // set to true as there's no keypoint at an invalid XYZ
  }
}
Ejemplo n.º 3
0
template <typename PointInT, typename PointOutT, typename IntensityT> void
pcl::HarrisKeypoint2D<PointInT, PointOutT, IntensityT>::detectKeypoints (PointCloudOut &output)
{
  derivatives_cols_.resize (input_->width, input_->height);
  derivatives_rows_.resize (input_->width, input_->height);
  //Compute cloud intensities first derivatives along columns and rows
  //!!! nsallem 20120220 : we don't test here for density so if one term in nan the result is nan
  int w = static_cast<int> (input_->width) - 1;
  int h = static_cast<int> (input_->height) - 1;
  // j = 0 --> j-1 out of range ; use 0
  // i = 0 --> i-1 out of range ; use 0
  derivatives_cols_(0,0) = (intensity_ ((*input_) (0,1)) - intensity_ ((*input_) (0,0))) * 0.5;
  derivatives_rows_(0,0) = (intensity_ ((*input_) (1,0)) - intensity_ ((*input_) (0,0))) * 0.5;

// #ifdef _OPENMP
// //#pragma omp parallel for shared (derivatives_cols_, input_) num_threads (threads_)
// #pragma omp parallel for num_threads (threads_)
// #endif
  for(int i = 1; i < w; ++i)
	{
		derivatives_cols_(i,0) = (intensity_ ((*input_) (i,1)) - intensity_ ((*input_) (i,0))) * 0.5;
	}

  derivatives_rows_(w,0) = (intensity_ ((*input_) (w,0)) - intensity_ ((*input_) (w-1,0))) * 0.5;
  derivatives_cols_(w,0) = (intensity_ ((*input_) (w,1)) - intensity_ ((*input_) (w,0))) * 0.5;

// #ifdef _OPENMP
// //#pragma omp parallel for shared (derivatives_cols_, derivatives_rows_, input_) num_threads (threads_)
// #pragma omp parallel for num_threads (threads_)
// #endif
  for(int j = 1; j < h; ++j)
  {
    // i = 0 --> i-1 out of range ; use 0
		derivatives_rows_(0,j) = (intensity_ ((*input_) (1,j)) - intensity_ ((*input_) (0,j))) * 0.5;
    for(int i = 1; i < w; ++i)
    {
      // derivative with respect to rows
      derivatives_rows_(i,j) = (intensity_ ((*input_) (i+1,j)) - intensity_ ((*input_) (i-1,j))) * 0.5;

      // derivative with respect to cols
      derivatives_cols_(i,j) = (intensity_ ((*input_) (i,j+1)) - intensity_ ((*input_) (i,j-1))) * 0.5;
    }
    // i = w --> w+1 out of range ; use w
    derivatives_rows_(w,j) = (intensity_ ((*input_) (w,j)) - intensity_ ((*input_) (w-1,j))) * 0.5;
  }

  // j = h --> j+1 out of range use h
  derivatives_cols_(0,h) = (intensity_ ((*input_) (0,h)) - intensity_ ((*input_) (0,h-1))) * 0.5;
  derivatives_rows_(0,h) = (intensity_ ((*input_) (1,h)) - intensity_ ((*input_) (0,h))) * 0.5;

// #ifdef _OPENMP
// //#pragma omp parallel for shared (derivatives_cols_, input_) num_threads (threads_)
// #pragma omp parallel for num_threads (threads_)
// #endif
  for(int i = 1; i < w; ++i)
	{
    derivatives_cols_(i,h) = (intensity_ ((*input_) (i,h)) - intensity_ ((*input_) (i,h-1))) * 0.5;
	}
  derivatives_rows_(w,h) = (intensity_ ((*input_) (w,h)) - intensity_ ((*input_) (w-1,h))) * 0.5;
  derivatives_cols_(w,h) = (intensity_ ((*input_) (w,h)) - intensity_ ((*input_) (w,h-1))) * 0.5;

  float highest_response_;
  
  switch (method_)
  {
    case HARRIS:
      responseHarris(*response_, highest_response_);
      break;
    case NOBLE:
      responseNoble(*response_, highest_response_);
      break;
    case LOWE:
      responseLowe(*response_, highest_response_);
      break;
    case TOMASI:
      responseTomasi(*response_, highest_response_);
      break;
  }
  
  if (!nonmax_)
    output = *response_;
  else
  {    
    threshold_*= highest_response_;

    std::sort (indices_->begin (), indices_->end (), 
               boost::bind (&HarrisKeypoint2D::greaterIntensityAtIndices, this, _1, _2));
    
    output.clear ();
    output.reserve (response_->size());
    std::vector<bool> occupency_map (response_->size (), false);    
    int width (response_->width);
    int height (response_->height);
    const int occupency_map_size (occupency_map.size ());

#ifdef _OPENMP
#pragma omp parallel for shared (output, occupency_map) private (width, height) num_threads(threads_)   
#endif
    for (int idx = 0; idx < occupency_map_size; ++idx)
    {
      if (occupency_map[idx] || response_->points [indices_->at (idx)].intensity < threshold_ || !isFinite (response_->points[idx]))
        continue;
        
#ifdef _OPENMP
#pragma omp critical
#endif
      output.push_back (response_->at (indices_->at (idx)));
      
			int u_end = std::min (width, indices_->at (idx) % width + min_distance_);
			int v_end = std::min (height, indices_->at (idx) / width + min_distance_);
      for(int u = std::max (0, indices_->at (idx) % width - min_distance_); u < u_end; ++u)
        for(int v = std::max (0, indices_->at (idx) / width - min_distance_); v < v_end; ++v)
          occupency_map[v*input_->width+u] = true;
    }

    // if (refine_)
    //   refineCorners (output);

    output.height = 1;
    output.width = static_cast<uint32_t> (output.size());
  }

  // we don not change the denseness
  output.is_dense = input_->is_dense;
}
Ejemplo n.º 4
0
template <typename PointInT, typename IntensityT> void
pcl::tracking::PyramidalKLTTracker<PointInT, IntensityT>::computePyramids (const PointCloudInConstPtr& input,
                                                                    std::vector<FloatImageConstPtr>& pyramid,
                                                                    pcl::InterpolationType border_type) const
{
  int step = 3;
  pyramid.resize (step * nb_levels_);

  FloatImageConstPtr previous;
  FloatImagePtr tmp (new FloatImage (input->width, input->height));
#ifdef _OPENMP
#pragma omp parallel for num_threads (threads_)
#endif
  for (int i = 0; i < static_cast<int> (input->size ()); ++i)
    tmp->points[i] = intensity_ (input->points[i]);
  previous = tmp;

  FloatImagePtr img (new FloatImage (previous->width + 2*track_width_,
                                     previous->height + 2*track_height_));

  pcl::copyPointCloud (*tmp, *img, track_height_, track_height_, track_width_, track_width_,
                       border_type, 0.f);
  pyramid[0] = img;

  // compute first level gradients
  FloatImagePtr g_x (new FloatImage (input->width, input->height));
  FloatImagePtr g_y (new FloatImage (input->width, input->height));
  derivatives (*img, *g_x, *g_y);
  // copy to bigger clouds
  FloatImagePtr grad_x (new FloatImage (previous->width + 2*track_width_,
                                        previous->height + 2*track_height_));
  pcl::copyPointCloud (*g_x, *grad_x, track_height_, track_height_, track_width_, track_width_,
                       pcl::BORDER_CONSTANT, 0.f);
  pyramid[1] = grad_x;

  FloatImagePtr grad_y (new FloatImage (previous->width + 2*track_width_,
                                        previous->height + 2*track_height_));
  pcl::copyPointCloud (*g_y, *grad_y, track_height_, track_height_, track_width_, track_width_,
                       pcl::BORDER_CONSTANT, 0.f);
  pyramid[2] = grad_y;

  for (int level = 1; level < nb_levels_; ++level)
  {
    // compute current level and current level gradients
    FloatImageConstPtr current;
    FloatImageConstPtr g_x;
    FloatImageConstPtr g_y;
    downsample (previous, current, g_x, g_y);
    // copy to bigger clouds
    FloatImagePtr image (new FloatImage (current->width + 2*track_width_,
                                         current->height + 2*track_height_));
    pcl::copyPointCloud (*current, *image, track_height_, track_height_, track_width_, track_width_,
                         border_type, 0.f);
    pyramid[level*step] = image;
    FloatImagePtr gradx (new FloatImage (g_x->width + 2*track_width_, g_x->height + 2*track_height_));
    pcl::copyPointCloud (*g_x, *gradx, track_height_, track_height_, track_width_, track_width_,
                         pcl::BORDER_CONSTANT, 0.f);
    pyramid[level*step + 1] = gradx;
    FloatImagePtr grady (new FloatImage (g_y->width + 2*track_width_, g_y->height + 2*track_height_));
    pcl::copyPointCloud (*g_y, *grady, track_height_, track_height_, track_width_, track_width_,
                         pcl::BORDER_CONSTANT, 0.f);
    pyramid[level*step + 2] = grady;
    // set the new level
    previous = current;
  }
}
Ejemplo n.º 5
0
template <typename PointInT, typename PointNT, typename PointOutT, typename IntensitySelectorT> void
pcl::IntensityGradientEstimation <PointInT, PointNT, PointOutT, IntensitySelectorT>::computePointIntensityGradient (
  const pcl::PointCloud <PointInT> &cloud, const std::vector <int> &indices,
  const Eigen::Vector3f &point, float mean_intensity, const Eigen::Vector3f &normal, Eigen::Vector3f &gradient)
{
  if (indices.size () < 3)
  {
    gradient[0] = gradient[1] = gradient[2] = std::numeric_limits<float>::quiet_NaN ();
    return;
  }

  Eigen::Matrix3f A = Eigen::Matrix3f::Zero ();
  Eigen::Vector3f b = Eigen::Vector3f::Zero ();

  for (size_t i_point = 0; i_point < indices.size (); ++i_point)
  {
    PointInT p = cloud.points[indices[i_point]];
    if (!pcl_isfinite (p.x) ||
        !pcl_isfinite (p.y) ||
        !pcl_isfinite (p.z) ||
        !pcl_isfinite (intensity_ (p)))
      continue;

    p.x -= point[0];
    p.y -= point[1];
    p.z -= point[2];
    intensity_.demean (p, mean_intensity);

    A (0, 0) += p.x * p.x;
    A (0, 1) += p.x * p.y;
    A (0, 2) += p.x * p.z;

    A (1, 1) += p.y * p.y;
    A (1, 2) += p.y * p.z;

    A (2, 2) += p.z * p.z;

    b[0] += p.x * intensity_ (p);
    b[1] += p.y * intensity_ (p);
    b[2] += p.z * intensity_ (p);
  }
  // Fill in the lower triangle of A
  A (1, 0) = A (0, 1);
  A (2, 0) = A (0, 2);
  A (2, 1) = A (1, 2);

//*
  Eigen::Vector3f x = A.colPivHouseholderQr ().solve (b);
/*/

  Eigen::Vector3f eigen_values;
  Eigen::Matrix3f eigen_vectors;
  eigen33 (A, eigen_vectors, eigen_values);

  b = eigen_vectors.transpose () * b;

  if ( eigen_values (0) != 0)
    b (0) /= eigen_values (0);
  else
    b (0) = 0;

  if ( eigen_values (1) != 0)
    b (1) /= eigen_values (1);
  else
    b (1) = 0;

  if ( eigen_values (2) != 0)
    b (2) /= eigen_values (2);
  else
    b (2) = 0;


  Eigen::Vector3f x = eigen_vectors * b;

//  if (A.col (0).squaredNorm () != 0)
//    x [0] /= A.col (0).squaredNorm ();
//  b -= x [0] * A.col (0);
//
//
//  if (A.col (1).squaredNorm ()  != 0)
//    x [1] /= A.col (1).squaredNorm ();
//  b -= x[1] * A.col (1);
//
//  x [2] = b.dot (A.col (2));
//  if (A.col (2).squaredNorm () != 0)
//    x[2] /= A.col (2).squaredNorm ();
  // Fit a hyperplane to the data

//*/
//  std::cout << A << "\n*\n" << bb << "\n=\n" << x << "\nvs.\n" << x2 << "\n\n";
//  std::cout << A * x << "\nvs.\n" << A * x2 << "\n\n------\n";
  // Project the gradient vector, x, onto the tangent plane
  gradient = (Eigen::Matrix3f::Identity () - normal*normal.transpose ()) * x;
}
Ejemplo n.º 6
0
template <typename PointInT, typename PointNT, typename PointOutT, typename IntensitySelectorT> void
pcl::IntensityGradientEstimation<PointInT, PointNT, PointOutT, IntensitySelectorT>::computeFeature (PointCloudOut &output)
{
  // Allocate enough space to hold the results
  // \note This resize is irrelevant for a radiusSearch ().
  std::vector<int> nn_indices (k_);
  std::vector<float> nn_dists (k_);
  output.is_dense = true;

  // If the data is dense, we don't need to check for NaN
  if (surface_->is_dense)
  {
#ifdef _OPENMP
#pragma omp parallel for shared (output) private (nn_indices, nn_dists) num_threads(threads_)
#endif
    // Iterating over the entire index vector
    for (int idx = 0; idx < static_cast<int> (indices_->size ()); ++idx)
    {
      PointOutT &p_out = output.points[idx];

      if (!this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists))
      {
        p_out.gradient[0] = p_out.gradient[1] = p_out.gradient[2] = std::numeric_limits<float>::quiet_NaN ();
        output.is_dense = false;
        continue;
      }

      Eigen::Vector3f centroid;
      float mean_intensity = 0;
      // Initialize to 0
      centroid.setZero ();
      for (size_t i = 0; i < nn_indices.size (); ++i)
      {
        centroid += surface_->points[nn_indices[i]].getVector3fMap ();
        mean_intensity += intensity_ (surface_->points[nn_indices[i]]);
      }
      centroid /= static_cast<float> (nn_indices.size ());
      mean_intensity /= static_cast<float> (nn_indices.size ());

      Eigen::Vector3f normal = Eigen::Vector3f::Map (normals_->points[(*indices_) [idx]].normal);
      Eigen::Vector3f gradient;
      computePointIntensityGradient (*surface_, nn_indices, centroid, mean_intensity, normal, gradient);

      p_out.gradient[0] = gradient[0];
      p_out.gradient[1] = gradient[1];
      p_out.gradient[2] = gradient[2];
    }
  }
  else
  {
#ifdef _OPENMP
#pragma omp parallel for shared (output) private (nn_indices, nn_dists) num_threads(threads_)
#endif
    // Iterating over the entire index vector
    for (int idx = 0; idx < static_cast<int> (indices_->size ()); ++idx)
    {
      PointOutT &p_out = output.points[idx];
      if (!isFinite ((*surface_) [(*indices_)[idx]]) ||
          !this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists))
      {
        p_out.gradient[0] = p_out.gradient[1] = p_out.gradient[2] = std::numeric_limits<float>::quiet_NaN ();
        output.is_dense = false;
        continue;
      }
      Eigen::Vector3f centroid;
      float mean_intensity = 0;
      // Initialize to 0
      centroid.setZero ();
      unsigned cp = 0;
      for (size_t i = 0; i < nn_indices.size (); ++i)
      {
        // Check if the point is invalid
        if (!isFinite ((*surface_) [nn_indices[i]]))
          continue;

        centroid += surface_->points [nn_indices[i]].getVector3fMap ();
        mean_intensity += intensity_ (surface_->points [nn_indices[i]]);
        ++cp;
      }
      centroid /= static_cast<float> (cp);
      mean_intensity /= static_cast<float> (cp);
      Eigen::Vector3f normal = Eigen::Vector3f::Map (normals_->points[(*indices_) [idx]].normal);
      Eigen::Vector3f gradient;
      computePointIntensityGradient (*surface_, nn_indices, centroid, mean_intensity, normal, gradient);

      p_out.gradient[0] = gradient[0];
      p_out.gradient[1] = gradient[1];
      p_out.gradient[2] = gradient[2];
    }
  }
}
Ejemplo n.º 7
0
Archivo: susan.hpp Proyecto: 5irius/pcl
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::detectKeypoints (PointCloudOut &output)
{
  boost::shared_ptr<pcl::PointCloud<PointOutT> > response (new pcl::PointCloud<PointOutT> ());
  response->reserve (surface_->size ());

  // Check if the output has a "label" field
  label_idx_ = pcl::getFieldIndex<PointOutT> (output, "label", out_fields_);

  const int input_size = static_cast<int> (input_->size ());
//#ifdef _OPENMP
//#pragma omp parallel for shared (response) num_threads(threads_)
//#endif
  for (int point_index = 0; point_index < input_size; ++point_index)
  {
    const PointInT& point_in = input_->points [point_index];
    const NormalT& normal_in = normals_->points [point_index];
    if (!isFinite (point_in) || !isFinite (normal_in))
      continue;
    else
    {
      Eigen::Vector3f nucleus = point_in.getVector3fMap ();
      Eigen::Vector3f nucleus_normal = normals_->points [point_index].getNormalVector3fMap ();
      float nucleus_intensity = intensity_ (point_in);
      std::vector<int> nn_indices;
      std::vector<float> nn_dists;
      tree_->radiusSearch (point_in, search_radius_, nn_indices, nn_dists);
      float area = 0;
      Eigen::Vector3f centroid = Eigen::Vector3f::Zero ();
      // Exclude nucleus from the usan
      std::vector<int> usan; usan.reserve (nn_indices.size () - 1);
      for (std::vector<int>::const_iterator index = nn_indices.begin(); index != nn_indices.end(); ++index)
      {
        if ((*index != point_index) && pcl_isfinite (normals_->points[*index].normal_x))
        {
          // if the point fulfill condition
          if ((fabs (nucleus_intensity - intensity_ (input_->points[*index])) <= intensity_threshold_) ||
              (1 - nucleus_normal.dot (normals_->points[*index].getNormalVector3fMap ()) <= angular_threshold_))
          {
            ++area;
            centroid += input_->points[*index].getVector3fMap ();
            usan.push_back (*index);
          }
        }
      }

      float geometric_threshold = 0.5f * (static_cast<float> (nn_indices.size () - 1));
      if ((area > 0) && (area < geometric_threshold))
      {
        // if no geometric validation required add the point to the response
        if (!geometric_validation_)
        {
          PointOutT point_out;
          point_out.getVector3fMap () = point_in.getVector3fMap ();
          //point_out.intensity = geometric_threshold - area; 
          intensity_out_.set (point_out, geometric_threshold - area);
          // if a label field is found use it to save the index
          if (label_idx_ != -1)
          {
            // save the index in the cloud
            uint32_t label = static_cast<uint32_t> (point_index);
            memcpy (reinterpret_cast<char*> (&point_out) + out_fields_[label_idx_].offset,
                    &label, sizeof (uint32_t));
          }
//#ifdef _OPENMP
//#pragma omp critical
//#endif
          response->push_back (point_out);
        }
        else
        {
          centroid /= area;
          Eigen::Vector3f dist = nucleus - centroid;
          // Check the distance <= distance_threshold_
          if (dist.norm () >= distance_threshold_)
          {
            // point is valid from distance point of view 
            Eigen::Vector3f nc = centroid - nucleus;
            // Check the contiguity
            std::vector<int>::const_iterator usan_it = usan.begin ();
            for (; usan_it != usan.end (); ++usan_it)
            {
              if (!isWithinNucleusCentroid (nucleus, centroid, nc, input_->points[*usan_it]))
                break;
            }
            // All points within usan lies on the segment [nucleus centroid]
            if (usan_it == usan.end ())
            {
              PointOutT point_out;
              point_out.getVector3fMap () = point_in.getVector3fMap ();
              // point_out.intensity = geometric_threshold - area; 
              intensity_out_.set (point_out, geometric_threshold - area);
              // if a label field is found use it to save the index
              if (label_idx_ != -1)
              {
                // save the index in the cloud
                uint32_t label = static_cast<uint32_t> (point_index);
                memcpy (reinterpret_cast<char*> (&point_out) + out_fields_[label_idx_].offset,
                        &label, sizeof (uint32_t));
              }
//#ifdef _OPENMP
//#pragma omp critical
//#endif
              response->push_back (point_out);              
            }
          }
        }
      }
    }  
  }
  
  response->height = 1;
  response->width = static_cast<uint32_t> (response->size ());
  
  if (!nonmax_)
    output = *response;
  else
  {
    output.points.clear ();
    output.points.reserve (response->points.size());
    
//#ifdef _OPENMP
//#pragma omp parallel for shared (output) num_threads(threads_)   
//#endif
    for (int idx = 0; idx < static_cast<int> (response->points.size ()); ++idx)
    {
      const PointOutT& point_in = response->points [idx];
      const NormalT& normal_in = normals_->points [idx];
      //const float intensity = response->points[idx].intensity;
      const float intensity = intensity_out_ (response->points[idx]);
      if (!isFinite (point_in) || !isFinite (normal_in) || (intensity == 0))
        continue;
      std::vector<int> nn_indices;
      std::vector<float> nn_dists;
      tree_->radiusSearch (idx, search_radius_, nn_indices, nn_dists);
      bool is_minima = true;
      for (std::vector<int>::const_iterator nn_it = nn_indices.begin(); nn_it != nn_indices.end(); ++nn_it)
      {
//        if (intensity > response->points[*nn_it].intensity)
        if (intensity > intensity_out_ (response->points[*nn_it]))
        {
          is_minima = false;
          break;
        }
      }
      if (is_minima)
//#ifdef _OPENMP
//#pragma omp critical
//#endif
        output.points.push_back (response->points[idx]);
    }
    
    output.height = 1;
    output.width = static_cast<uint32_t> (output.points.size());  
  }
  // we don not change the denseness
  output.is_dense = input_->is_dense;
}
Ejemplo n.º 8
0
template <typename PointInT, typename PointOutT, typename KeypointT, typename IntensityT> void
pcl::BRISK2DEstimation<PointInT, PointOutT, KeypointT, IntensityT>::compute (
    PointCloudOutT &output)
{
  if (!input_cloud_->isOrganized ())
  {    
    PCL_ERROR ("[pcl::%s::initCompute] %s doesn't support non organized clouds!\n", name_.c_str ());
    return;
  }

  // image size
  const int width = int (input_cloud_->width);
  const int height = int (input_cloud_->height);

  // destination for intensity data; will be forwarded to BRISK
  std::vector<unsigned char> image_data (width*height);

  for (size_t row_index = 0; row_index < height; ++row_index)
  {
    for (size_t col_index = 0; col_index < width; ++col_index)
    {
      image_data[row_index*width + col_index] = static_cast<unsigned char> (intensity_ ((*input_cloud_) (col_index, row_index)));
    }
  }

  // Remove keypoints very close to the border
  size_t ksize = keypoints_->points.size ();
  std::vector<int> kscales; // remember the scale per keypoint
  kscales.resize (ksize);
 
  // initialize constants
   static const float log2 = 0.693147180559945f;
  static const float lb_scalerange = std::log (scalerange_) / (log2);

  typename std::vector<KeypointT, Eigen::aligned_allocator<KeypointT> >::iterator beginning = keypoints_->points.begin ();
  std::vector<int>::iterator beginningkscales = kscales.begin ();
  
  static const float basic_size_06 = basic_size_ * 0.6f;
  unsigned int basicscale = 0;

  if (!scale_invariance_enabled_)
    basicscale = std::max (static_cast<int> (float (scales_) / lb_scalerange * (log (1.45f * basic_size_ / (basic_size_06)) / log2) + 0.5f), 0);

  for (size_t k = 0; k < ksize; k++)
  {
    unsigned int scale;
    if (scale_invariance_enabled_)
    {
      scale = std::max (static_cast<int> (float (scales_) / lb_scalerange * (log (keypoints_->points[k].size / (basic_size_06)) / log2) + 0.5f), 0);
      // saturate
      if (scale >= scales_) scale = scales_ - 1;
      kscales[k] = scale;
    }
    else
    {
      scale = basicscale;
      kscales[k] = scale;
    }

    const int border   = size_list_[scale];
    const int border_x = width - border;
    const int border_y = height - border;

    if (RoiPredicate (float (border), float (border), float (border_x), float (border_y), keypoints_->points[k]))
    {
      keypoints_->points.erase (beginning + k);
      kscales.erase (beginningkscales + k);
      if (k == 0)
      {
        beginning = keypoints_->points.begin ();
        beginningkscales = kscales.begin ();
      }
      ksize--;
      k--;
    }
  }

  // first, calculate the integral image over the whole image:
  // current integral image
  std::vector<int> integral;    // the integral image
  //integral (image, integral);

  int* values = new int[points_]; // for temporary use

  // resize the descriptors:
  //output = zeros (ksize, strings_);

  // now do the extraction for all keypoints:

  // temporary variables containing gray values at sample points:
  int t1;
  int t2;

  // the feature orientation
  int direction0;
  int direction1;

  unsigned char* ptr = &output.points[0].descriptor[0];
  for (size_t k = 0; k < ksize; k++)
  {
    int theta;
    KeypointT &kp    = keypoints_->points[k];
    const int& scale = kscales[k];
    int shifter = 0;
    int* pvalues = values;
    const float& x = float (kp.x);
    const float& y = float (kp.y);
    if (true) // kp.angle==-1
    {
      if (!rotation_invariance_enabled_)
        // don't compute the gradient direction, just assign a rotation of 0°
        theta = 0;
      else
      {
        // get the gray values in the unrotated pattern
        for (unsigned int i = 0; i < points_; i++)
          *(pvalues++) = smoothedIntensity (image_data, width, height, integral, x, y, scale, 0, i);

        direction0 = 0;
        direction1 = 0;
        // now iterate through the long pairings
        const BriskLongPair* max = long_pairs_ + no_long_pairs_;

        for (BriskLongPair* iter = long_pairs_; iter < max; ++iter)
        {
          t1 = *(values + iter->i);
          t2 = *(values + iter->j);
          const int delta_t = (t1 - t2);

          // update the direction:
          const int tmp0 = delta_t * (iter->weighted_dx) / 1024;
          const int tmp1 = delta_t * (iter->weighted_dy) / 1024;
          direction0 += tmp0;
          direction1 += tmp1;
        }
        kp.angle = atan2 (float (direction1), float (direction0)) / float (M_PI) * 180.0f;
        theta = static_cast<int> ((float (n_rot_) * kp.angle) / (360.0f) + 0.5f);
        if (theta < 0)
          theta += n_rot_;
        if (theta >= int (n_rot_))
          theta -= n_rot_;
      }
    }
    else
    {
      // figure out the direction:
      //int theta=rotationInvariance*round((_n_rot*atan2(direction.at<int>(0,0),direction.at<int>(1,0)))/(2*M_PI));
      if (!rotation_invariance_enabled_)
        theta = 0;
      else
      {
        theta = static_cast<int> (n_rot_ * (kp.angle / (360.0)) + 0.5);
        if (theta < 0)
          theta += n_rot_;
        if (theta >= int (n_rot_))
          theta -= n_rot_;
      }
    }

    // now also extract the stuff for the actual direction:
    // let us compute the smoothed values
    shifter = 0;

    //unsigned int mean=0;
    pvalues = values;
    // get the gray values in the rotated pattern
    for (unsigned int i = 0; i < points_; i++)
      *(pvalues++) = smoothedIntensity (image_data, width, height, integral, x, y, scale, theta, i);

#ifdef __GNUC__
      typedef uint32_t __attribute__ ((__may_alias__)) UINT32_ALIAS;
#endif
#ifdef _MSC_VER
      // Todo: find the equivalent to may_alias
      #define UCHAR_ALIAS uint32_t //__declspec(noalias)
#endif

    // now iterate through all the pairings
    UINT32_ALIAS* ptr2 = reinterpret_cast<UINT32_ALIAS*> (ptr);
    const BriskShortPair* max = short_pairs_ + no_short_pairs_;
    
    for (BriskShortPair* iter = short_pairs_; iter < max; ++iter)
    {
      t1 = *(values + iter->i);
      t2 = *(values + iter->j);
      
      if (t1 > t2)
        *ptr2 |= ((1) << shifter);

      // else already initialized with zero
      // take care of the iterators:
      ++shifter;

      if (shifter == 32)
      {
        shifter = 0;
        ++ptr2;
      }
    }

    ptr += strings_;
 
    // Account for the scale + orientation;
    ptr += sizeof (output.points[0].scale);
    ptr += sizeof (output.points[0].orientation);
  }

  // we do not change the denseness
  output.width = int (output.points.size ());
  output.height = 1;
  output.is_dense = true;

  // clean-up
  delete [] values;
}