Point Cloud Library (PCL)  1.6.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
normal_based_signature.hpp
Go to the documentation of this file.
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, Alexandru-Eugen Ichim
5  * Willow Garage, Inc
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above
15  * copyright notice, this list of conditions and the following
16  * disclaimer in the documentation and/or other materials provided
17  * with the distribution.
18  * * Neither the name of Willow Garage, Inc. nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  *
35  * $Id: normal_based_signature.hpp 6144 2012-07-04 22:06:28Z rusu $
36  */
37 
38 #ifndef PCL_FEATURES_IMPL_NORMAL_BASED_SIGNATURE_H_
39 #define PCL_FEATURES_IMPL_NORMAL_BASED_SIGNATURE_H_
40 
42 
43 template <typename PointT, typename PointNT, typename PointFeature> void
45 {
46  // do a few checks before starting the computations
47 
48  PointFeature test_feature;
49  if (N_prime_ * M_prime_ != sizeof (test_feature.values) / sizeof (float))
50  {
51  PCL_ERROR ("NormalBasedSignatureEstimation: not using the proper signature size: %u vs %u\n", N_prime_ * M_prime_, sizeof (test_feature.values) / sizeof (float));
52  return;
53  }
54 
55  std::vector<int> k_indices;
56  std::vector<float> k_sqr_distances;
57 
58  tree_->setInputCloud (input_);
59  output.points.resize (indices_->size ());
60 
61  for (size_t index_i = 0; index_i < indices_->size (); ++index_i)
62  {
63  size_t point_i = (*indices_)[index_i];
64  Eigen::MatrixXf s_matrix (N_, M_);
65 
66  Eigen::Vector4f center_point = input_->points[point_i].getVector4fMap ();
67 
68  for (size_t k = 0; k < N_; ++k)
69  {
70  Eigen::VectorXf s_row (M_);
71 
72  for (size_t l = 0; l < M_; ++l)
73  {
74  Eigen::Vector4f normal = normals_->points[point_i].getNormalVector4fMap ();
75  Eigen::Vector4f normal_u = Eigen::Vector4f::Zero ();
76  Eigen::Vector4f normal_v = Eigen::Vector4f::Zero ();
77 
78  if (fabs (normal.x ()) > 0.0001f)
79  {
80  normal_u.x () = - normal.y () / normal.x ();
81  normal_u.y () = 1.0f;
82  normal_u.z () = 0.0f;
83  normal_u.normalize ();
84 
85  }
86  else if (fabs (normal.y ()) > 0.0001f)
87  {
88  normal_u.x () = 1.0f;
89  normal_u.y () = - normal.x () / normal.y ();
90  normal_u.z () = 0.0f;
91  normal_u.normalize ();
92  }
93  else
94  {
95  normal_u.x () = 0.0f;
96  normal_u.y () = 1.0f;
97  normal_u.z () = - normal.y () / normal.z ();
98  }
99  normal_v = normal.cross3 (normal_u);
100 
101  Eigen::Vector4f zeta_point = 2.0f * static_cast<float> (l + 1) * scale_h_ / static_cast<float> (M_) *
102  (cosf (2.0f * static_cast<float> (M_PI) * static_cast<float> ((k + 1) / N_)) * normal_u +
103  sinf (2.0f * static_cast<float> (M_PI) * static_cast<float> ((k + 1) / N_)) * normal_v);
104 
105  // Compute normal by using the neighbors
106  Eigen::Vector4f zeta_point_plus_center = zeta_point + center_point;
107  PointT zeta_point_pcl;
108  zeta_point_pcl.x = zeta_point_plus_center.x (); zeta_point_pcl.y = zeta_point_plus_center.y (); zeta_point_pcl.z = zeta_point_plus_center.z ();
109 
110  tree_->radiusSearch (zeta_point_pcl, search_radius_, k_indices, k_sqr_distances);
111 
112  // Do k nearest search if there are no neighbors nearby
113  if (k_indices.size () == 0)
114  {
115  k_indices.resize (5);
116  k_sqr_distances.resize (5);
117  tree_->nearestKSearch (zeta_point_pcl, 5, k_indices, k_sqr_distances);
118  }
119 
120  Eigen::Vector4f average_normal = Eigen::Vector4f::Zero ();
121 
122  float average_normalization_factor = 0.0f;
123 
124  // Normals weighted by 1/squared_distances
125  for (size_t nn_i = 0; nn_i < k_indices.size (); ++nn_i)
126  {
127  if (k_sqr_distances[nn_i] < 1e-7f)
128  {
129  average_normal = normals_->points[k_indices[nn_i]].getNormalVector4fMap ();
130  average_normalization_factor = 1.0f;
131  break;
132  }
133  average_normal += normals_->points[k_indices[nn_i]].getNormalVector4fMap () / k_sqr_distances[nn_i];
134  average_normalization_factor += 1.0f / k_sqr_distances[nn_i];
135  }
136  average_normal /= average_normalization_factor;
137  float s = zeta_point.dot (average_normal) / zeta_point.norm ();
138  s_row[l] = s;
139  }
140 
141  // do DCT on the s_matrix row-wise
142  Eigen::VectorXf dct_row (M_);
143  for (int m = 0; m < s_row.size (); ++m)
144  {
145  float Xk = 0.0f;
146  for (int n = 0; n < s_row.size (); ++n)
147  Xk += static_cast<float> (s_row[n] * cos (M_PI / (static_cast<double> (M_ * n) + 0.5) * static_cast<double> (k)));
148  dct_row[m] = Xk;
149  }
150  s_row = dct_row;
151  s_matrix.row (k) = dct_row;
152  }
153 
154  // do DFT on the s_matrix column-wise
155  Eigen::MatrixXf dft_matrix (N_, M_);
156  for (size_t column_i = 0; column_i < M_; ++column_i)
157  {
158  Eigen::VectorXf dft_col (N_);
159  for (size_t k = 0; k < N_; ++k)
160  {
161  float Xk_real = 0.0f, Xk_imag = 0.0f;
162  for (size_t n = 0; n < N_; ++n)
163  {
164  Xk_real += static_cast<float> (s_matrix (n, column_i) * cos (2.0f * M_PI / static_cast<double> (N_ * k * n)));
165  Xk_imag += static_cast<float> (s_matrix (n, column_i) * sin (2.0f * M_PI / static_cast<double> (N_ * k * n)));
166  }
167  dft_col[k] = sqrt (Xk_real*Xk_real + Xk_imag*Xk_imag);
168  }
169  dft_matrix.col (column_i) = dft_col;
170  }
171 
172  Eigen::MatrixXf final_matrix = dft_matrix.block (0, 0, N_prime_, M_prime_);
173 
174  PointFeature feature_point;
175  for (size_t i = 0; i < N_prime_; ++i)
176  for (size_t j = 0; j < M_prime_; ++j)
177  feature_point.values[i*M_prime_ + j] = final_matrix (i, j);
178 
179  output.points[index_i] = feature_point;
180  }
181 }
182 
183 
184 
185 #define PCL_INSTANTIATE_NormalBasedSignatureEstimation(T,NT,OutT) template class PCL_EXPORTS pcl::NormalBasedSignatureEstimation<T,NT,OutT>;
186 
187 
188 #endif /* PCL_FEATURES_IMPL_NORMAL_BASED_SIGNATURE_H_ */