template <typename PointInT, typename PointOutT> void pcl::SIFTKeypoint<PointInT, PointOutT>::detectKeypoints (PointCloudOut &output) { if (surface_ && surface_ != input_) { PCL_WARN ("[pcl::%s::detectKeypoints] : ", name_.c_str ()); PCL_WARN ("A search surface has been set by setSearchSurface, but this SIFT keypoint detection algorithm does "); PCL_WARN ("not support search surfaces other than the input cloud. "); PCL_WARN ("The cloud provided in setInputCloud is being used instead.\n"); } // Check if the output has a "scale" field scale_idx_ = pcl::getFieldIndex<PointOutT> (output, "scale", out_fields_); // Make sure the output cloud is empty output.points.clear (); // Create a local copy of the input cloud that will be resized for each octave boost::shared_ptr<pcl::PointCloud<PointInT> > cloud (new pcl::PointCloud<PointInT> (*input_)); VoxelGrid<PointInT> voxel_grid; // Search for keypoints at each octave float scale = min_scale_; for (int i_octave = 0; i_octave < nr_octaves_; ++i_octave) { // Downsample the point cloud const float s = 1.0f * scale; // note: this can be adjusted voxel_grid.setLeafSize (s, s, s); voxel_grid.setInputCloud (cloud); boost::shared_ptr<pcl::PointCloud<PointInT> > temp (new pcl::PointCloud<PointInT>); voxel_grid.filter (*temp); cloud = temp; // Make sure the downsampled cloud still has enough points const size_t min_nr_points = 25; if (cloud->points.size () < min_nr_points) break; // Update the KdTree with the downsampled points tree_->setInputCloud (cloud); // Detect keypoints for the current scale detectKeypointsForOctave (*cloud, *tree_, scale, nr_scales_per_octave_, output, *keypoints_indices_); // Increase the scale by another octave scale *= 2; } // Set final properties output.height = 1; output.width = static_cast<uint32_t> (output.points.size ()); output.header = input_->header; output.sensor_origin_ = input_->sensor_origin_; output.sensor_orientation_ = input_->sensor_orientation_; }
template <typename PointInT, typename PointOutT> void pcl::SIFTKeypoint<PointInT, PointOutT>::detectKeypoints (PointCloudOut &output) { // Check for valid inputs if (min_scale_ == 0 || nr_octaves_ == 0 || nr_scales_per_octave_ == 0) { ROS_ERROR ("[pcl::%s::detectKeypoints] : A valid range of scales must be specified by setScales before detecting keypoints!", name_.c_str ()); return; } if (surface_ != input_) { ROS_WARN ("[pcl::%s::detectKeypoints] : A search surface has be set by setSearchSurface, but this SIFT keypoint detection algorithm does not support search surfaces other than the input cloud. The cloud provided in setInputCloud is being used instead.", name_.c_str ()); } // Make sure the output cloud is empty output.points.clear (); // Create a local copy of the input cloud that will be resized for each octave boost::shared_ptr<pcl::PointCloud<PointInT> > cloud = input_->makeShared (); // Search for keypoints at each octave float scale = min_scale_; for (int i_octave = 0; i_octave < nr_octaves_; ++i_octave) { // Downsample the point cloud VoxelGrid<PointInT> voxel_grid; float s = 1.0 * scale; // note: this can be adjusted voxel_grid.setLeafSize (s, s, s); voxel_grid.setInputCloud (cloud); voxel_grid.filter (*cloud); // Make sure the downsampled cloud still has enough points const size_t min_nr_points = 25; if (cloud->points.size () < min_nr_points) { return; } // Update the KdTree with the downsampled points tree_->setInputCloud (cloud); // Detect keypoints for the current scale detectKeypointsForOctave (*cloud, *tree_, scale, nr_scales_per_octave_, output); // Increase the scale by another octave scale *= 2; } }