Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
intensity_gradient.hpp
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Point Cloud Library (PCL) - www.pointclouds.org
00005  *  Copyright (c) 2010-2011, Willow Garage, Inc.
00006  *
00007  *  All rights reserved.
00008  *
00009  *  Redistribution and use in source and binary forms, with or without
00010  *  modification, are permitted provided that the following conditions
00011  *  are met:
00012  *
00013  *   * Redistributions of source code must retain the above copyright
00014  *     notice, this list of conditions and the following disclaimer.
00015  *   * Redistributions in binary form must reproduce the above
00016  *     copyright notice, this list of conditions and the following
00017  *     disclaimer in the documentation and/or other materials provided
00018  *     with the distribution.
00019  *   * Neither the name of Willow Garage, Inc. nor the names of its
00020  *     contributors may be used to endorse or promote products derived
00021  *     from this software without specific prior written permission.
00022  *
00023  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00024  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00025  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00026  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00027  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00028  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00029  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00030  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00031  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00032  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00033  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00034  *  POSSIBILITY OF SUCH DAMAGE.
00035  *
00036  * $Id: intensity_gradient.hpp 4702 2012-02-23 09:39:33Z gedikli $
00037  *
00038  */
00039 
00040 #ifndef PCL_FEATURES_IMPL_INTENSITY_GRADIENT_H_
00041 #define PCL_FEATURES_IMPL_INTENSITY_GRADIENT_H_
00042 
00043 #include "pcl/features/intensity_gradient.h"
00044 
00046 template <typename PointInT, typename PointNT, typename PointOutT> void
00047 pcl::IntensityGradientEstimation <PointInT, PointNT, PointOutT>::computePointIntensityGradient (
00048   const pcl::PointCloud <PointInT> &cloud, const std::vector <int> &indices,
00049   const Eigen::Vector3f &point, float mean_intensity, const Eigen::Vector3f &normal, Eigen::Vector3f &gradient)
00050 {
00051   if (indices.size () < 3)
00052   {
00053     gradient[0] = gradient[1] = gradient[2] = std::numeric_limits<float>::quiet_NaN ();
00054     return;
00055   }
00056 
00057   Eigen::Matrix3f A = Eigen::Matrix3f::Zero ();
00058   Eigen::Vector3f b = Eigen::Vector3f::Zero ();
00059 
00060   for (size_t i_point = 0; i_point < indices.size (); ++i_point)
00061   {
00062     PointInT p = cloud.points[indices[i_point]];
00063     if (!pcl_isfinite (p.x) ||
00064         !pcl_isfinite (p.y) ||
00065         !pcl_isfinite (p.z) ||
00066         !pcl_isfinite (p.intensity))
00067       continue;
00068 
00069     p.x -= point[0];
00070     p.y -= point[1];
00071     p.z -= point[2];
00072     p.intensity -= mean_intensity;
00073 
00074     A (0, 0) += p.x * p.x;
00075     A (0, 1) += p.x * p.y;
00076     A (0, 2) += p.x * p.z;
00077 
00078     A (1, 1) += p.y * p.y;
00079     A (1, 2) += p.y * p.z;
00080 
00081     A (2, 2) += p.z * p.z;
00082 
00083     b[0] += p.x * p.intensity;
00084     b[1] += p.y * p.intensity;
00085     b[2] += p.z * p.intensity;
00086   }
00087   // Fill in the lower triangle of A
00088   A (1, 0) = A (0, 1);
00089   A (2, 0) = A (0, 2);
00090   A (2, 1) = A (1, 2);
00091 
00092 //*
00093   Eigen::Vector3f x = A.colPivHouseholderQr ().solve (b);
00094 /*/
00095 
00096   Eigen::Vector3f eigen_values;
00097   Eigen::Matrix3f eigen_vectors;
00098   eigen33 (A, eigen_vectors, eigen_values);
00099 
00100   b = eigen_vectors.transpose () * b;
00101 
00102   if ( eigen_values (0) != 0)
00103     b (0) /= eigen_values (0);
00104   else
00105     b (0) = 0;
00106 
00107   if ( eigen_values (1) != 0)
00108     b (1) /= eigen_values (1);
00109   else
00110     b (1) = 0;
00111 
00112   if ( eigen_values (2) != 0)
00113     b (2) /= eigen_values (2);
00114   else
00115     b (2) = 0;
00116 
00117 
00118   Eigen::Vector3f x = eigen_vectors * b;
00119 
00120 //  if (A.col (0).squaredNorm () != 0)
00121 //    x [0] /= A.col (0).squaredNorm ();
00122 //  b -= x [0] * A.col (0);
00123 //
00124 //
00125 //  if (A.col (1).squaredNorm ()  != 0)
00126 //    x [1] /= A.col (1).squaredNorm ();
00127 //  b -= x[1] * A.col (1);
00128 //
00129 //  x [2] = b.dot (A.col (2));
00130 //  if (A.col (2).squaredNorm () != 0)
00131 //    x[2] /= A.col (2).squaredNorm ();
00132   // Fit a hyperplane to the data
00133 
00134 //*/
00135 //  std::cout << A << "\n*\n" << bb << "\n=\n" << x << "\nvs.\n" << x2 << "\n\n";
00136 //  std::cout << A * x << "\nvs.\n" << A * x2 << "\n\n------\n";
00137   // Project the gradient vector, x, onto the tangent plane
00138   gradient = (Eigen::Matrix3f::Identity () - normal*normal.transpose ()) * x;
00139 }
00140 
00142 template <typename PointInT, typename PointNT, typename PointOutT> void
00143 pcl::IntensityGradientEstimation<PointInT, PointNT, PointOutT>::computeFeature (PointCloudOut &output)
00144 {
00145   // Allocate enough space to hold the results
00146   // \note This resize is irrelevant for a radiusSearch ().
00147   std::vector<int> nn_indices (k_);
00148   std::vector<float> nn_dists (k_);
00149 
00150   output.is_dense = true;
00151   // Iterating over the entire index vector
00152   for (size_t idx = 0; idx < indices_->size (); ++idx)
00153   {
00154     PointOutT &p_out = output.points[idx];
00155 
00156     if (!this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists))
00157     {
00158       p_out.gradient[0] = p_out.gradient[1] = p_out.gradient[2] = std::numeric_limits<float>::quiet_NaN ();
00159       output.is_dense = false;
00160       continue;
00161     }
00162 
00163     Eigen::Vector4f centroid;
00164     compute3DCentroid (*surface_, nn_indices, centroid);
00165 
00166     float mean_intensity = 0;
00167     unsigned valid_neighbor_count = 0;
00168     for (size_t nIdx = 0; nIdx < nn_indices.size (); ++nIdx)
00169     {
00170       const PointInT& p = (*surface_)[nn_indices[nIdx]];
00171       if (!pcl_isfinite (p.intensity))
00172         continue;
00173 
00174       mean_intensity += p.intensity;
00175       ++valid_neighbor_count;
00176     }
00177 
00178     mean_intensity /= (float)valid_neighbor_count;
00179 
00180     Eigen::Vector3f normal = Eigen::Vector3f::Map (normals_->points[idx].normal);
00181     Eigen::Vector3f gradient;
00182     computePointIntensityGradient (*surface_, nn_indices, centroid.head<3> (), mean_intensity, normal, gradient);
00183 
00184     p_out.gradient[0] = gradient[0];
00185     p_out.gradient[1] = gradient[1];
00186     p_out.gradient[2] = gradient[2];
00187   }
00188 }
00189 
00191 template <typename PointInT, typename PointNT> void
00192 pcl::IntensityGradientEstimation<PointInT, PointNT, Eigen::MatrixXf>::computeFeatureEigen (pcl::PointCloud<Eigen::MatrixXf> &output)
00193 {
00194   // Resize the output dataset
00195   output.points.resize (indices_->size (), 3);
00196 
00197   // Allocate enough space to hold the results
00198   // \note This resize is irrelevant for a radiusSearch ().
00199   std::vector<int> nn_indices (k_);
00200   std::vector<float> nn_dists (k_);
00201 
00202   output.is_dense = true;
00203   // Iterating over the entire index vector
00204   for (size_t idx = 0; idx < indices_->size (); ++idx)
00205   {
00206     if (this->searchForNeighbors ((*indices_)[idx], search_parameter_, nn_indices, nn_dists) == 0)
00207     {
00208       output.points.row (idx).setConstant (std::numeric_limits<float>::quiet_NaN ());
00209       output.is_dense = false;
00210       continue;
00211     }
00212 
00213     Eigen::Vector4f centroid;
00214     compute3DCentroid (*surface_, nn_indices, centroid);
00215 
00216     float mean_intensity = 0;
00217     unsigned valid_neighbor_count = 0;
00218     for (size_t nIdx = 0; nIdx < nn_indices.size (); ++nIdx)
00219     {
00220       const PointInT& p = (*surface_)[nn_indices[nIdx]];
00221       if (!pcl_isfinite (p.intensity))
00222         continue;
00223 
00224       mean_intensity += p.intensity;
00225       ++valid_neighbor_count;
00226     }
00227 
00228     mean_intensity /= (float)valid_neighbor_count;
00229 
00230     Eigen::Vector3f normal = Eigen::Vector3f::Map (normals_->points[idx].normal);
00231     Eigen::Vector3f gradient;
00232     this->computePointIntensityGradient (*surface_, nn_indices, centroid.head<3> (), mean_intensity, normal, gradient);
00233 
00234     output.points (idx, 0) = gradient[0];
00235     output.points (idx, 1) = gradient[1];
00236     output.points (idx, 2) = gradient[2];
00237   }
00238 }
00239 
00240 
00241 #define PCL_INSTANTIATE_IntensityGradientEstimation(InT,NT,OutT) template class PCL_EXPORTS pcl::IntensityGradientEstimation<InT,NT,OutT>;
00242 
00243 #endif    // PCL_FEATURES_IMPL_INTENSITY_GRADIENT_H_