456 lines
19 KiB
C++
456 lines
19 KiB
C++
|
|
/*
|
||
|
|
* Software License Agreement (BSD License)
|
||
|
|
*
|
||
|
|
* Point Cloud Library (PCL) - www.pointclouds.org
|
||
|
|
* Copyright (c) 2010-2011, Willow Garage, Inc.
|
||
|
|
*
|
||
|
|
* All rights reserved.
|
||
|
|
*
|
||
|
|
* Redistribution and use in source and binary forms, with or without
|
||
|
|
* modification, are permitted provided that the following conditions
|
||
|
|
* are met:
|
||
|
|
*
|
||
|
|
* * Redistributions of source code must retain the above copyright
|
||
|
|
* notice, this list of conditions and the following disclaimer.
|
||
|
|
* * Redistributions in binary form must reproduce the above
|
||
|
|
* copyright notice, this list of conditions and the following
|
||
|
|
* disclaimer in the documentation and/or other materials provided
|
||
|
|
* with the distribution.
|
||
|
|
* * Neither the name of Willow Garage, Inc. nor the names of its
|
||
|
|
* contributors may be used to endorse or promote products derived
|
||
|
|
* from this software without specific prior written permission.
|
||
|
|
*
|
||
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
|
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
|
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
|
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifndef PCL_SUSAN_IMPL_HPP_
|
||
|
|
#define PCL_SUSAN_IMPL_HPP_
|
||
|
|
|
||
|
|
#include <pcl/common/io.h> // for getFieldIndex
|
||
|
|
#include <pcl/keypoints/susan.h>
|
||
|
|
#include <pcl/features/normal_3d.h>
|
||
|
|
#include <pcl/features/integral_image_normal.h>
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setNonMaxSupression (bool nonmax)
|
||
|
|
{
|
||
|
|
nonmax_ = nonmax;
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setGeometricValidation (bool validate)
|
||
|
|
{
|
||
|
|
geometric_validation_ = validate;
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setRadius (float radius)
|
||
|
|
{
|
||
|
|
search_radius_ = radius;
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setDistanceThreshold (float distance_threshold)
|
||
|
|
{
|
||
|
|
distance_threshold_ = distance_threshold;
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setAngularThreshold (float angular_threshold)
|
||
|
|
{
|
||
|
|
angular_threshold_ = angular_threshold;
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setIntensityThreshold (float intensity_threshold)
|
||
|
|
{
|
||
|
|
intensity_threshold_ = intensity_threshold;
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setNormals (const PointCloudNConstPtr &normals)
|
||
|
|
{
|
||
|
|
normals_ = normals;
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setSearchSurface (const PointCloudInConstPtr &cloud)
|
||
|
|
{
|
||
|
|
surface_ = cloud;
|
||
|
|
normals_.reset (new pcl::PointCloud<NormalT>);
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::setNumberOfThreads (unsigned int nr_threads)
|
||
|
|
{
|
||
|
|
threads_ = nr_threads;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
// template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
// pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::USAN (const PointInT& nucleus,
|
||
|
|
// const NormalT& nucleus_normal,
|
||
|
|
// const pcl::Indices& neighbors,
|
||
|
|
// const float& t,
|
||
|
|
// float& response,
|
||
|
|
// Eigen::Vector3f& centroid) const
|
||
|
|
// {
|
||
|
|
// float area = 0;
|
||
|
|
// response = 0;
|
||
|
|
// float x0 = nucleus.x;
|
||
|
|
// float y0 = nucleus.y;
|
||
|
|
// float z0 = nucleus.z;
|
||
|
|
// //xx xy xz yy yz zz
|
||
|
|
// std::vector<float> coefficients(6);
|
||
|
|
// memset (&coefficients[0], 0, sizeof (float) * 6);
|
||
|
|
// for (const auto& index : neighbors)
|
||
|
|
// {
|
||
|
|
// if (std::isfinite ((*normals_)[index].normal_x))
|
||
|
|
// {
|
||
|
|
// Eigen::Vector3f diff = (*normals_)[index].getNormal3fMap () - nucleus_normal.getNormal3fMap ();
|
||
|
|
// float c = diff.norm () / t;
|
||
|
|
// c = -1 * pow (c, 6.0);
|
||
|
|
// c = std::exp (c);
|
||
|
|
// Eigen::Vector3f xyz = (*surface_)[index].getVector3fMap ();
|
||
|
|
// centroid += c * xyz;
|
||
|
|
// area += c;
|
||
|
|
// coefficients[0] += c * (x0 - xyz.x) * (x0 - xyz.x);
|
||
|
|
// coefficients[1] += c * (x0 - xyz.x) * (y0 - xyz.y);
|
||
|
|
// coefficients[2] += c * (x0 - xyz.x) * (z0 - xyz.z);
|
||
|
|
// coefficients[3] += c * (y0 - xyz.y) * (y0 - xyz.y);
|
||
|
|
// coefficients[4] += c * (y0 - xyz.y) * (z0 - xyz.z);
|
||
|
|
// coefficients[5] += c * (z0 - xyz.z) * (z0 - xyz.z);
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
// if (area > 0)
|
||
|
|
// {
|
||
|
|
// centroid /= area;
|
||
|
|
// if (area < geometric_threshold)
|
||
|
|
// response = geometric_threshold - area;
|
||
|
|
// // Look for edge direction
|
||
|
|
// // X direction
|
||
|
|
// if ((coefficients[3]/coefficients[0]) < 1 && (coefficients[5]/coefficients[0]) < 1)
|
||
|
|
// direction = Eigen::Vector3f (1, 0, 0);
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// // Y direction
|
||
|
|
// if ((coefficients[0]/coefficients[3]) < 1 && (coefficients[5]/coefficients[3]) < 1)
|
||
|
|
// direction = Eigen::Vector3f (0, 1, 0);
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// // Z direction
|
||
|
|
// if ((coefficients[0]/coefficients[5]) < 1 && (coefficients[3]/coefficients[5]) < 1)
|
||
|
|
// direction = Eigen::Vector3f (0, 1, 0);
|
||
|
|
// // Diagonal edge
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// //XY direction
|
||
|
|
// if ((coefficients[2]/coeffcients[1]) < 1 && (coeffcients[4]/coeffcients[1]) < 1)
|
||
|
|
// {
|
||
|
|
// if (coeffcients[1] > 0)
|
||
|
|
// direction = Eigen::Vector3f (1,1,0);
|
||
|
|
// else
|
||
|
|
// direction = Eigen::Vector3f (-1,1,0);
|
||
|
|
// }
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// //XZ direction
|
||
|
|
// if ((coefficients[1]/coeffcients[2]) > 1 && (coeffcients[4]/coeffcients[2]) < 1)
|
||
|
|
// {
|
||
|
|
// if (coeffcients[2] > 0)
|
||
|
|
// direction = Eigen::Vector3f (1,0,1);
|
||
|
|
// else
|
||
|
|
// direction = Eigen::Vector3f (-1,0,1);
|
||
|
|
// }
|
||
|
|
// //YZ direction
|
||
|
|
// else
|
||
|
|
// {
|
||
|
|
// if (coeffcients[4] > 0)
|
||
|
|
// direction = Eigen::Vector3f (0,1,1);
|
||
|
|
// else
|
||
|
|
// direction = Eigen::Vector3f (0,-1,1);
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
// // std::size_t max_index = std::distance (coefficients.begin (), max);
|
||
|
|
// // switch (max_index)
|
||
|
|
// // {
|
||
|
|
// // case 0 : direction = Eigen::Vector3f (1, 0, 0); break;
|
||
|
|
// // case 1 : direction = Eigen::Vector3f (1, 1, 0); break;
|
||
|
|
// // case 2 : direction = Eigen::Vector3f (1, 0, 1); break;
|
||
|
|
// // case 3 : direction = Eigen::Vector3f (0, 1, 0); break;
|
||
|
|
// // case 4 : direction = Eigen::Vector3f (0, 1, 1); break;
|
||
|
|
// // case 5 : direction = Eigen::Vector3f (0, 0, 1); break;
|
||
|
|
// // }
|
||
|
|
// }
|
||
|
|
// }
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> bool
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::initCompute ()
|
||
|
|
{
|
||
|
|
if (!Keypoint<PointInT, PointOutT>::initCompute ())
|
||
|
|
{
|
||
|
|
PCL_ERROR ("[pcl::%s::initCompute] init failed!\n", name_.c_str ());
|
||
|
|
return (false);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (normals_->empty ())
|
||
|
|
{
|
||
|
|
PointCloudNPtr normals (new PointCloudN ());
|
||
|
|
normals->reserve (normals->size ());
|
||
|
|
if (!surface_->isOrganized ())
|
||
|
|
{
|
||
|
|
pcl::NormalEstimation<PointInT, NormalT> normal_estimation;
|
||
|
|
normal_estimation.setInputCloud (surface_);
|
||
|
|
normal_estimation.setRadiusSearch (search_radius_);
|
||
|
|
normal_estimation.compute (*normals);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
IntegralImageNormalEstimation<PointInT, NormalT> normal_estimation;
|
||
|
|
normal_estimation.setNormalEstimationMethod (pcl::IntegralImageNormalEstimation<PointInT, NormalT>::SIMPLE_3D_GRADIENT);
|
||
|
|
normal_estimation.setInputCloud (surface_);
|
||
|
|
normal_estimation.setNormalSmoothingSize (5.0);
|
||
|
|
normal_estimation.compute (*normals);
|
||
|
|
}
|
||
|
|
normals_ = normals;
|
||
|
|
}
|
||
|
|
if (normals_->size () != surface_->size ())
|
||
|
|
{
|
||
|
|
PCL_ERROR ("[pcl::%s::initCompute] normals given, but the number of normals does not match the number of input points!\n", name_.c_str ());
|
||
|
|
return (false);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (true);
|
||
|
|
}
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> bool
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::isWithinNucleusCentroid (const Eigen::Vector3f& nucleus,
|
||
|
|
const Eigen::Vector3f& centroid,
|
||
|
|
const Eigen::Vector3f& nc,
|
||
|
|
const PointInT& point) const
|
||
|
|
{
|
||
|
|
Eigen::Vector3f pc = centroid - point.getVector3fMap ();
|
||
|
|
Eigen::Vector3f pn = nucleus - point.getVector3fMap ();
|
||
|
|
Eigen::Vector3f pc_cross_nc = pc.cross (nc);
|
||
|
|
return ((pc_cross_nc.norm () <= tolerance_) && (pc.dot (nc) >= 0) && (pn.dot (nc) <= 0));
|
||
|
|
}
|
||
|
|
|
||
|
|
// template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> bool
|
||
|
|
// pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::isValidQueryPoint3D (int point_index) const
|
||
|
|
// {
|
||
|
|
// return (isFinite (surface_->points [point_index]) &&
|
||
|
|
// isFinite (normals_->points [point_index]));
|
||
|
|
// }
|
||
|
|
|
||
|
|
// template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> bool
|
||
|
|
// pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::isValidQueryPoint2D (int point_index) const
|
||
|
|
// {
|
||
|
|
// return (isFinite (surface_->points [point_index]));
|
||
|
|
// }
|
||
|
|
|
||
|
|
// template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> bool
|
||
|
|
// pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::isWithinSusan2D (int nucleus, int neighbor) const
|
||
|
|
// {
|
||
|
|
// return (std::abs (intensity_ ((*surface_)[nucleus]) -
|
||
|
|
// intensity_ ((*surface_)[neighbor])) <= intensity_threshold_);
|
||
|
|
// }
|
||
|
|
|
||
|
|
// template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> bool
|
||
|
|
// pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::isWithinSusan3D (int nucleus, int neighbor) const
|
||
|
|
// {
|
||
|
|
// Eigen::Vector3f nucleus_normal = normals_->point[nucleus].getVector3fMap ();
|
||
|
|
// return (1 - nucleus_normal.dot ((*normals_)[*index].getNormalVector3fMap ()) <= angular_threshold_);
|
||
|
|
// }
|
||
|
|
|
||
|
|
// template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> bool
|
||
|
|
// pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::isWithinSusanH (int nucleus, int neighbor) const
|
||
|
|
// {
|
||
|
|
// Eigen::Vector3f nucleus_normal = normals_->point[nucleus].getVector3fMap ();
|
||
|
|
// return ((1 - nucleus_normal.dot ((*normals_)[*index].getNormalVector3fMap ()) <= angular_threshold_) ||
|
||
|
|
// (std::abs (intensity_ ((*surface_)[nucleus]) - intensity_ ((*surface_)[neighbor])) <= intensity_threshold_));
|
||
|
|
// }
|
||
|
|
|
||
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
template <typename PointInT, typename PointOutT, typename NormalT, typename IntensityT> void
|
||
|
|
pcl::SUSANKeypoint<PointInT, PointOutT, NormalT, IntensityT>::detectKeypoints (PointCloudOut &output)
|
||
|
|
{
|
||
|
|
typename pcl::PointCloud<PointOutT>::Ptr response (new pcl::PointCloud<PointOutT>);
|
||
|
|
response->reserve (surface_->size ());
|
||
|
|
|
||
|
|
// Check if the output has a "label" field
|
||
|
|
label_idx_ = pcl::getFieldIndex<PointOutT> ("label", out_fields_);
|
||
|
|
|
||
|
|
const auto input_size = static_cast<pcl::index_t> (input_->size ());
|
||
|
|
for (pcl::index_t 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;
|
||
|
|
|
||
|
|
Eigen::Vector3f nucleus = point_in.getVector3fMap ();
|
||
|
|
Eigen::Vector3f nucleus_normal = normals_->points [point_index].getNormalVector3fMap ();
|
||
|
|
float nucleus_intensity = intensity_ (point_in);
|
||
|
|
pcl::Indices 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 (const auto& index : nn_indices)
|
||
|
|
{
|
||
|
|
if ((index != point_index) && std::isfinite ((*normals_)[index].normal_x))
|
||
|
|
{
|
||
|
|
// if the point fulfill condition
|
||
|
|
if ((std::abs (nucleus_intensity - intensity_ ((*input_)[index])) <= intensity_threshold_) ||
|
||
|
|
(1 - nucleus_normal.dot ((*normals_)[index].getNormalVector3fMap ()) <= angular_threshold_))
|
||
|
|
{
|
||
|
|
++area;
|
||
|
|
centroid += (*input_)[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
|
||
|
|
std::uint32_t label = static_cast<std::uint32_t> (point_index);
|
||
|
|
memcpy (reinterpret_cast<char*> (&point_out) + out_fields_[label_idx_].offset,
|
||
|
|
&label, sizeof (std::uint32_t));
|
||
|
|
}
|
||
|
|
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
|
||
|
|
auto usan_it = usan.cbegin ();
|
||
|
|
for (; usan_it != usan.cend (); ++usan_it)
|
||
|
|
{
|
||
|
|
if (!isWithinNucleusCentroid (nucleus, centroid, nc, (*input_)[*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
|
||
|
|
std::uint32_t label = static_cast<std::uint32_t> (point_index);
|
||
|
|
memcpy (reinterpret_cast<char*> (&point_out) + out_fields_[label_idx_].offset,
|
||
|
|
&label, sizeof (std::uint32_t));
|
||
|
|
}
|
||
|
|
response->push_back (point_out);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
response->height = 1;
|
||
|
|
response->width = response->size ();
|
||
|
|
|
||
|
|
if (!nonmax_)
|
||
|
|
{
|
||
|
|
output = *response;
|
||
|
|
for (std::size_t i = 0; i < response->size (); ++i)
|
||
|
|
keypoints_indices_->indices.push_back (i);
|
||
|
|
// we don not change the denseness
|
||
|
|
output.is_dense = input_->is_dense;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
output.clear ();
|
||
|
|
output.reserve (response->size());
|
||
|
|
|
||
|
|
for (pcl::index_t idx = 0; idx < static_cast<pcl::index_t> (response->size ()); ++idx)
|
||
|
|
{
|
||
|
|
const PointOutT& point_in = response->points [idx];
|
||
|
|
const NormalT& normal_in = normals_->points [idx];
|
||
|
|
//const float intensity = (*response)[idx].intensity;
|
||
|
|
const float intensity = intensity_out_ ((*response)[idx]);
|
||
|
|
if (!isFinite (point_in) || !isFinite (normal_in) || (intensity == 0))
|
||
|
|
continue;
|
||
|
|
pcl::Indices nn_indices;
|
||
|
|
std::vector<float> nn_dists;
|
||
|
|
tree_->radiusSearch (idx, search_radius_, nn_indices, nn_dists);
|
||
|
|
bool is_minima = true;
|
||
|
|
for (const auto& nn_index : nn_indices)
|
||
|
|
{
|
||
|
|
// if (intensity > (*response)[nn_index].intensity)
|
||
|
|
if (intensity > intensity_out_ ((*response)[nn_index]))
|
||
|
|
{
|
||
|
|
is_minima = false;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (is_minima)
|
||
|
|
{
|
||
|
|
output.push_back ((*response)[idx]);
|
||
|
|
keypoints_indices_->indices.push_back (idx);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
output.height = 1;
|
||
|
|
output.width = output.size();
|
||
|
|
output.is_dense = true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#define PCL_INSTANTIATE_SUSAN(T,U,N) template class PCL_EXPORTS pcl::SUSANKeypoint<T,U,N>;
|
||
|
|
#endif // #ifndef PCL_HARRIS_KEYPOINT_3D_IMPL_H_
|
||
|
|
|