NormalEstimationValueClass.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Fraunhofer FKIE
00003  *
00004  * Authors: Torsten Fiolka, Bastian Gaspers
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions are met:
00008  *
00009  * * Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * * Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * * Neither the name of the Fraunhofer FKIE nor the names of its
00015  *   contributors may be used to endorse or promote products derived from
00016  *   this software without specific prior written permission.
00017  *
00018  * This file is part of the StructureColoring ROS package.
00019  *
00020  * The StructureColoring ROS package is free software:
00021  * you can redistribute it and/or modify it under the terms of the
00022  * GNU Lesser General Public License as published by the Free
00023  * Software Foundation, either version 3 of the License, or
00024  * (at your option) any later version.
00025  *
00026  * The StructureColoring ROS package is distributed in the hope that it will be useful,
00027  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00028  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00029  * GNU Lesser General Public License for more details.
00030  *
00031  * You should have received a copy of the GNU Lesser General Public License
00032  * along with The StructureColoring ROS package.
00033  * If not, see <http://www.gnu.org/licenses/>.
00034  */
00035 
00036 #ifndef NORMAL_ESTIMATION_VALUE_CLASS_H_
00037 #define NORMAL_ESTIMATION_VALUE_CLASS_H_
00038 
00039 #include <Eigen/Core>
00040 #include <Eigen/Eigen>
00041 #include <octreelib/spatialaggregate/octree.h>
00042 #include <octreelib/algorithm/downsample.h>
00043 #include <pcl/point_types.h>
00044 #include <pcl/point_cloud.h>
00045 #include <pcl/common/vector_average.h>
00046 #include <limits.h>
00047 
00048 class NormalEstimationValueClass {
00049 public:
00050         typedef Eigen::Matrix3f Mat3;
00051         typedef Eigen::Vector3f Vec3;
00052 
00053         Mat3 summedSquares;
00054         Vec3 summedPos;
00055         Vec3 meanPos;
00056 
00057         Vec3 normal;
00058         float curv;
00059         float curv2;
00060         bool stable;
00061         bool segmented;
00062         unsigned int id;
00063         unsigned int numPoints;
00064         bool nodeQuerried;
00065 
00066         NormalEstimationValueClass(const unsigned int) :
00067                 id(std::numeric_limits<unsigned int>::max()) {
00068                 clear();
00069         }
00070 
00071         NormalEstimationValueClass() :
00072                 id(std::numeric_limits<unsigned int>::max()) {
00073                 clear();
00074         }
00075 
00076         void clear() {
00077                 summedSquares.setZero();
00078                 summedPos.setZero();
00079                 meanPos.setZero();
00080                 normal.setZero();
00081                 numPoints = 0;
00082                 curv = -1.f;
00083                 curv2 = -1.f;
00084                 segmented = false;
00085                 stable = false;
00086                 nodeQuerried = false;
00087         }
00088 
00089         NormalEstimationValueClass& operator+(const NormalEstimationValueClass& rhs) {
00090                 summedSquares += rhs.summedSquares;
00091                 summedPos += rhs.summedPos;
00092                 numPoints += rhs.numPoints;
00093                 if (rhs.id < id)
00094                         id = rhs.id;
00095                 return *this;
00096         }
00097 
00098         NormalEstimationValueClass& operator+=(const NormalEstimationValueClass& rhs) {
00099                 summedSquares += rhs.summedSquares;
00100                 summedPos += rhs.summedPos;
00101                 numPoints += rhs.numPoints;
00102                 if (rhs.id < id)
00103                         id = rhs.id;
00104                 return *this;
00105         }
00106 };
00107 
00109 template<typename CoordType, typename ValueType>
00110 bool calculateNormal(spatialaggregate::OcTreeNode<CoordType, ValueType>* treenode, const Eigen::Vector3f& viewPort,
00111                 const int& minimumPointsForNormal, const float& curv_threshold, const float& curv2_threshold,
00112                 const float& minPrincipleVariance) {
00113         int count = treenode->value_.numPoints;
00114         Eigen::Vector3f summedPos(treenode->value_.summedPos);
00115         summedPos *= 1.f / (float) count;
00116         treenode->value_.meanPos = summedPos;
00117         if (count < minimumPointsForNormal) {
00118                 return false;
00119         }
00120 
00121         Eigen::Matrix3f summedSquares(treenode->value_.summedSquares);
00122         summedSquares *= 1.f / (float) count;
00123         summedSquares -= summedPos * summedPos.transpose();
00124 
00125         //Eigen::Matrix<float, 3, 1> eigen_values;
00126         //Eigen::Matrix<float, 3, 3> eigen_vectors;
00127         //pcl::eigen33(summedSquares, eigen_vectors, eigen_values);
00128         Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> es;
00129         es.compute(summedSquares);
00130         const Eigen::Matrix<float, 3, 1>& eigen_values = es.eigenvalues();
00131         const Eigen::Matrix<float, 3, 3>& eigen_vectors = es.eigenvectors();
00132 
00133         treenode->value_.curv = eigen_values(0, 0) / eigen_values(2, 0);//(eigen_values(0, 0) + eigen_values(1, 0) + eigen_values(2, 0));
00134         if(eigen_values(0, 0) > eigen_values(2, 0)) std::cout << "ERROR while calculating curv: eigenvalues were not sorted ascendingly" << std::endl;
00135         treenode->value_.curv2 = eigen_values(1, 0) / eigen_values(2, 0);
00136         treenode->value_.normal = eigen_vectors.col(0);
00137         if (eigen_vectors.col(0).dot((summedPos / treenode->value_.numPoints) - viewPort) > 0)
00138                 treenode->value_.normal = -treenode->value_.normal;
00139         if ((treenode->value_.curv > curv_threshold) || (treenode->value_.curv2 < curv2_threshold)
00140                         || (eigen_values(2, 0) < minPrincipleVariance)) {
00141                 treenode->value_.stable = false;
00142                 return false;
00143         }
00144         treenode->value_.stable = true;
00145         return true;
00146 }
00147 
00148 template<typename CoordType, typename ValueType>
00149 void calculateNormalsOnOctreeLayer(std::vector<spatialaggregate::OcTreeNode<CoordType, ValueType>*>& layer,
00150                 Eigen::Vector3f viewPort, int minimumPointsForNormal) {
00151         for (unsigned int i = 0; i < layer.size(); i++) {
00152                 if (!(layer[i]->value_.stable)) {
00153                         layer[i]->value_.stable = calculateNormal(layer[i], layer[i]->value_.normal, viewPort,
00154                                         minimumPointsForNormal);
00155                 }
00156         }
00157 }
00158 
00159 #endif /* NORMAL_ESTIMATION_VALUE_CLASS_H_ */
00160 


structure_coloring_fkie
Author(s): Bastian Gaspers
autogenerated on Sun Jan 5 2014 11:38:09