Point Cloud Library (PCL)  1.7.0
pca.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Point Cloud Library (PCL) - www.pointclouds.org
5  * Copyright (c) 2010-2011, Willow Garage, Inc.
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of the copyright holder(s) nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * $Id$
37  */
38 
39 #ifndef PCL_PCA_H
40 #define PCL_PCA_H
41 
42 #include <pcl/pcl_base.h>
43 #include <pcl/pcl_macros.h>
44 
45 namespace pcl
46 {
47  /** Principal Component analysis (PCA) class.\n
48  * Principal components are extracted by singular values decomposition on the
49  * covariance matrix of the centered input cloud. Available data after pca computation
50  * are the mean of the input data, the eigenvalues (in descending order) and
51  * corresponding eigenvectors.\n
52  * Other methods allow projection in the eigenspace, reconstruction from eigenspace and
53  * update of the eigenspace with a new datum (according Matej Artec, Matjaz Jogan and
54  * Ales Leonardis: "Incremental PCA for On-line Visual Learning and Recognition").
55  *
56  * \author Nizar Sallem
57  * \ingroup common
58  */
59  template <typename PointT>
60  class PCA : public pcl::PCLBase <PointT>
61  {
62  public:
64  typedef typename Base::PointCloud PointCloud;
69 
70  using Base::input_;
71  using Base::indices_;
72  using Base::initCompute;
73  using Base::setInputCloud;
74 
75  /** Updating method flag */
76  enum FLAG
77  {
78  /** keep the new basis vectors if possible */
80  /** preserve subspace dimension */
82  };
83 
84  /** \brief Default Constructor
85  * \param basis_only flag to compute only the PCA basis
86  */
87  PCA (bool basis_only = false)
88  : Base ()
89  , compute_done_ (false)
90  , basis_only_ (basis_only)
91  , eigenvectors_ ()
92  , coefficients_ ()
93  , mean_ ()
94  , eigenvalues_ ()
95  {}
96 
97  /** \brief Constructor with direct computation
98  * X input m*n matrix (ie n vectors of R(m))
99  * basis_only flag to compute only the PCA basis
100  */
101  PCL_DEPRECATED (PCA (const pcl::PointCloud<PointT>& X, bool basis_only = false),
102  "Use PCA (bool basis_only); setInputCloud (X.makeShared ()); instead");
103 
104  /** Copy Constructor
105  * \param[in] pca PCA object
106  */
107  PCA (PCA const & pca)
108  : Base (pca)
109  , compute_done_ (pca.compute_done_)
110  , basis_only_ (pca.basis_only_)
111  , eigenvectors_ (pca.eigenvectors_)
112  , coefficients_ (pca.coefficients_)
113  , mean_ (pca.mean_)
114  , eigenvalues_ (pca.eigenvalues_)
115  {}
116 
117  /** Assignment operator
118  * \param[in] pca PCA object
119  */
120  inline PCA&
121  operator= (PCA const & pca)
122  {
123  eigenvectors_ = pca.eigenvectors;
124  coefficients_ = pca.coefficients;
125  eigenvalues_ = pca.eigenvalues;
126  mean_ = pca.mean;
127  return (*this);
128  }
129 
130  /** \brief Provide a pointer to the input dataset
131  * \param cloud the const boost shared pointer to a PointCloud message
132  */
133  inline void
135  {
136  Base::setInputCloud (cloud);
137  compute_done_ = false;
138  }
139 
140  /** \brief Mean accessor
141  * \throw InitFailedException
142  */
143  inline Eigen::Vector4f&
145  {
146  if (!compute_done_)
147  initCompute ();
148  if (!compute_done_)
149  PCL_THROW_EXCEPTION (InitFailedException,
150  "[pcl::PCA::getMean] PCA initCompute failed");
151  return (mean_);
152  }
153 
154  /** Eigen Vectors accessor
155  * \throw InitFailedException
156  */
157  inline Eigen::Matrix3f&
159  {
160  if (!compute_done_)
161  initCompute ();
162  if (!compute_done_)
163  PCL_THROW_EXCEPTION (InitFailedException,
164  "[pcl::PCA::getEigenVectors] PCA initCompute failed");
165  return (eigenvectors_);
166  }
167 
168  /** Eigen Values accessor
169  * \throw InitFailedException
170  */
171  inline Eigen::Vector3f&
173  {
174  if (!compute_done_)
175  initCompute ();
176  if (!compute_done_)
177  PCL_THROW_EXCEPTION (InitFailedException,
178  "[pcl::PCA::getEigenVectors] PCA getEigenValues failed");
179  return (eigenvalues_);
180  }
181 
182  /** Coefficients accessor
183  * \throw InitFailedException
184  */
185  inline Eigen::MatrixXf&
187  {
188  if (!compute_done_)
189  initCompute ();
190  if (!compute_done_)
191  PCL_THROW_EXCEPTION (InitFailedException,
192  "[pcl::PCA::getEigenVectors] PCA getCoefficients failed");
193  return (coefficients_);
194  }
195 
196  /** update PCA with a new point
197  * \param[in] input input point
198  * \param[in] flag update flag
199  * \throw InitFailedException
200  */
201  inline void
202  update (const PointT& input, FLAG flag = preserve);
203 
204  /** Project point on the eigenspace.
205  * \param[in] input point from original dataset
206  * \param[out] projection the point in eigen vectors space
207  * \throw InitFailedException
208  */
209  inline void
210  project (const PointT& input, PointT& projection);
211 
212  /** Project cloud on the eigenspace.
213  * \param[in] input cloud from original dataset
214  * \param[out] projection the cloud in eigen vectors space
215  * \throw InitFailedException
216  */
217  inline void
218  project (const PointCloud& input, PointCloud& projection);
219 
220  /** Reconstruct point from its projection
221  * \param[in] projection point from eigenvector space
222  * \param[out] input reconstructed point
223  * \throw InitFailedException
224  */
225  inline void
226  reconstruct (const PointT& projection, PointT& input);
227 
228  /** Reconstruct cloud from its projection
229  * \param[in] projection cloud from eigenvector space
230  * \param[out] input reconstructed cloud
231  * \throw InitFailedException
232  */
233  inline void
234  reconstruct (const PointCloud& projection, PointCloud& input);
235 
236  private:
237  inline bool
238  initCompute ();
239 
240  bool compute_done_;
241  bool basis_only_;
242  Eigen::Matrix3f eigenvectors_;
243  Eigen::MatrixXf coefficients_;
244  Eigen::Vector4f mean_;
245  Eigen::Vector3f eigenvalues_;
246  }; // class PCA
247 } // namespace pcl
248 
249 #include <pcl/common/impl/pca.hpp>
250 
251 #endif // PCL_PCA_H
252