PlanePatch.h
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2013, Fraunhofer FKIE
00003  *
00004  * Authors: 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 _PlanePatch_h_
00037 #define _PlanePatch_h_
00038 
00039 #include "pcl/point_types.h"
00040 #include "pcl/point_cloud.h"
00041 #include <structureColoring/grids/GridMap.h>
00042 #include <structureColoring/structures/Plane3D.h>
00043 #include <vector>
00044 #include <cmath>
00045 #include <opencv2/core/core.hpp>
00046 #include <opencv2/imgproc/imgproc.hpp>
00047 #include <Eigen/Dense>
00048 #include <Eigen/QR>
00049 #include <Eigen/StdVector>
00050 #include <boost/shared_ptr.hpp>
00051 #include <stdexcept>
00052 #include <list>
00053 
00054 class PlanePatch{
00055 public:
00056         typedef boost::shared_ptr<PlanePatch> PlanePatchPtr;
00057         typedef boost::shared_ptr<const PlanePatch> PlanePatchConstPtr;
00058         typedef std::list<PlanePatchPtr> PlanePatches;
00059 
00060         typedef std::vector<int> PointIndices;
00061         typedef pcl::PointXYZ PointT;
00062         typedef pcl::PointXYZRGB ColoredPointT;
00063         typedef pcl::PointXYZI IntensityPointT;
00064         typedef pcl::PointCloud<PointT> PointCloud;
00065         typedef pcl::PointCloud<ColoredPointT> ColoredPointCloud;
00066         typedef pcl::PointCloud<IntensityPointT> IntensityPointCloud;
00067         typedef std::pair<unsigned int, unsigned int> Pair2ui;
00068         typedef Eigen::Vector3f Vec3;
00069         typedef std::vector<Vec3, Eigen::aligned_allocator<Vec3> > Points;
00070         typedef boost::shared_ptr<GridMap> GridMapPtr;
00071         typedef boost::shared_ptr<const GridMap> GridMapConstPtr;
00072 
00073         template<typename PointCloudType>
00074         PlanePatch(const Eigen::Vector3f& normal, const float distance, const PointIndices& inliers,
00075                         const PointCloudType& pointCloud, const float distanceThreshold = -1.f);
00076 
00077         template<typename PointCloudType>
00078         PlanePatch(const PointIndices& inliers, const PointCloudType& pointCloud, const float distanceThreshold);
00079 
00080         PlanePatch(const Vec3& normal, const float distance, const float distanceThreshold, const Points& brVertices,
00081                         const float texWidthRatio, const float texHeightRatio, const cv::Mat& heightMap, const cv::Mat& textureMap);
00082 
00083         PlanePatch();
00084 
00085 //      virtual ~PlanePatch();
00086 
00087 //setter:
00088         template<typename PointCloudType>
00089         void addPoints(const PointIndices& pointIndices, const PointCloudType& pointCloud);
00090 
00091         float& xMin() { return mXMin; }
00092         float& yMin() { return mYMin; }
00093         float& xMax() { return mXMax; }
00094         float& yMax() { return mYMax; }
00095 
00096         GridMapPtr grid() { return mGrid; }
00097         void setGrid(GridMap* newGridMapPtr){ mGrid.reset(newGridMapPtr); }
00098 
00099         void setId(size_t id) { mPlaneId = id; }
00100 
00101 //getter:
00102         const Points& getBRVertices() const { return mBRVertices; }
00103         const Points& getBBVertices() const { return mBBVertices;}
00104 
00105         const cv::Mat& getTextureMap() const {
00106                 assert(mTextureMap.cols != 0 && mTextureMap.rows != 0);
00107                 return mTextureMap;
00108         }
00109         const cv::Mat& getHeightMap() const {
00110                 assert(mHeightMap.cols != 0 && mHeightMap.rows != 0);
00111                 return mHeightMap;
00112         }
00113         const cv::Mat& getNormalMap() const {
00114                 assert(mNormalMap.cols != 0 && mNormalMap.rows != 0);
00115                 return mNormalMap;
00116         }
00117         float getTextureWidthRatio() const { return mTextureWidthRatio; }
00118         float getTextureHeightRatio() const { return mTextureHeightRatio; }
00119 
00120         const Vec3& getPlaneCoG() const { return mCoG; }
00121         const Plane3D& getPlane3D() const { return mPlane; }
00122 
00123         void getLimitsXY(float& xMin, float& xMax, float& yMin, float& yMax) const;
00124         const float& xMin() const { return mXMin; }
00125         const float& yMin() const { return mYMin; }
00126         const float& xMax() const { return mXMax; }
00127         const float& yMax() const { return mYMax; }
00128         float getArea() const { return (mXMax - mXMin) * (mYMax - mYMin); }
00129         const PointIndices& getInliers() const { return mInlierIndices; }
00130         float getDistanceThreshold() const { return mDistanceThreshold; }
00131 
00132         GridMapConstPtr grid() const { return mGrid; }
00133         bool hasGrid() const{ return mGrid; }
00134 
00135         size_t getId() const { return mPlaneId; }
00136 
00137 
00138         //helper functions
00139         bool checkPointConnection(const Vec3& p, const int connectionNeighbors) const;
00140 
00141         float distanceToOBB(const Vec3& p) const;
00142 
00143         void newGrid(const float cellSize);
00144 
00145         void computeOrientedBoundingBox();
00146         void computeBoundingRectangle();
00147 
00148         //compute texture etc.
00149         void computeTextureSize(float& texPixSize, unsigned int& wPot, unsigned int& hPot, const float texelSizeFactor);
00150         static void compute2PotTexSize(float& widthRatio, float& heightRatio, unsigned int& wPot, unsigned int& hPot,
00151                         const unsigned int width, const unsigned int height);
00152         void computeRGBTextureMap(const ColoredPointCloud& pointCloud, const float texelSizeFactor = 2.f,
00153                         const unsigned int dilateIterations = 0);
00154         void computeIntensityTextureMap(const IntensityPointCloud& pointCloud, const float texelSizeFactor = 2.f,
00155                         const unsigned int dilateIterations = 0);
00156         void computeAlphaMap(const PointCloud& pointCloud, const float texelSizeFactor = 2.f,
00157                         const unsigned int dilateIterations = 0);
00158 
00159         template<typename PointCloudType>
00160         void computeHeightMap(const float texturePixelSize, const PointCloudType& pointCloud,
00161                         const unsigned int dilateIterations);
00162 
00163         void computeNormalMap();
00164 
00165         // private copy constructor: (we do not copy PlanePatches)
00166 private:
00167         PlanePatch(const PlanePatch&) :
00168                 mPlane(){
00169                 throw std::runtime_error("Copy Constructor not implemented");
00170         }
00171 private:
00172         PlanePatch& operator=(const PlanePatch&) {
00173                 throw std::runtime_error("operator= not implemented");
00174         }
00175 
00176 private:
00177         template<typename PointCloudType>
00178         void initializeTransformationsWithoutPCA(const PointCloudType& pointCloud);
00179 
00180         template<typename PointCloudType>
00181         void initializeTransformationsWithPCA(const PointCloudType& pointCloud);
00182 
00183         template<typename PointCloudType>
00184         void initializeWithoutPCA(const PointCloudType& pointcloud);
00185 
00186         template<typename PointCloudType>
00187         void initializeWithPCA(const PointCloudType& pointCloud);
00188 
00189         template<typename PointCloudType>
00190         void calculateMinMax(const PointCloudType& pointCloud);
00191 
00192 
00193         template<typename PointCloudType>
00194         void rotateToPrincipalAxis(Eigen::Matrix3f& m, const PointCloudType& pointCloud, const Vec3& greatestEigenVector =
00195                         Vec3::Zero()) const;
00196 
00197         //member variables
00198         Plane3D mPlane;
00199         Vec3 mCoG;
00200         float mXMin, mXMax, mYMin, mYMax, mZMin, mZMax; // dimensions in plane coordinate system
00201         PointIndices mInlierIndices;
00202         Points mBRVertices;
00203         Points mBBVertices;
00204         GridMapPtr mGrid;
00205         cv::Mat mTextureMap;
00206         cv::Mat mHeightMap;
00207         cv::Mat mNormalMap;
00208         float mTextureWidthRatio, mTextureHeightRatio;
00209         float mDistanceThreshold;
00210         size_t mPlaneId;
00211 };
00212 
00213 /*****************************************************************************/
00214 
00215 class CompArea
00216 {
00217 public:
00218         bool operator()(PlanePatch::PlanePatchConstPtr pp1, PlanePatch::PlanePatchConstPtr pp2){
00219                 return pp2->getArea() < pp1->getArea();
00220         }
00221 };
00222 
00223 /*****************************************************************************/
00224 
00225 class CompPlanePtr
00226 {
00227 public:
00228         bool operator()(const PlanePatch::PlanePatchConstPtr pp1, const PlanePatch::PlanePatchConstPtr pp2) const {
00229                 return pp1.get() < pp2.get();
00230         }
00231 };
00232 
00233 /*****************************************************************************/
00234 
00235 class CompPlanePtrPair
00236 {
00237         typedef std::pair<PlanePatch::PlanePatchConstPtr, PlanePatch::PlanePatchConstPtr> PlaneConstPtrPair;
00238 public:
00239         bool operator()(const PlaneConstPtrPair ppp1, const PlaneConstPtrPair ppp2) const {
00240                 if (ppp1.first.get() != ppp2.first.get()) return ppp1.first.get() < ppp2.first.get();
00241                 return ppp1.second.get() < ppp2.second.get();
00242         }
00243 };
00244 
00245 /*****************************************************************************/
00246 
00247 template<typename PointCloudType>
00248 PlanePatch::PlanePatch(const Eigen::Vector3f& normal, const float distance, const PointIndices& inliers,
00249                 const PointCloudType& pointCloud, const float distanceThreshold)
00250         : mPlane(normal, distance), mInlierIndices(inliers),
00251           mDistanceThreshold(distanceThreshold) {
00252         assert(inliers.size()>= 3);
00253         initializeWithoutPCA(pointCloud);
00254 }
00255 
00256 /*****************************************************************************/
00257 
00258 template<typename PointCloudType>
00259 PlanePatch::PlanePatch(const PointIndices& inliers, const PointCloudType& pointCloud, const float distanceThreshold)
00260         : mInlierIndices(inliers),
00261           mDistanceThreshold(distanceThreshold) {
00262         assert(inliers.size()>= 3);
00263         initializeWithPCA(pointCloud);
00264 }
00265 
00266 /*****************************************************************************/
00267 
00268 template<typename PointCloudType>
00269 void PlanePatch::addPoints(const PointIndices& pointIndices, const PointCloudType& pointCloud) {
00270         mInlierIndices.reserve(mInlierIndices.size() + pointIndices.size());
00271         for (PointIndices::const_iterator pit = pointIndices.begin(); pit != pointIndices.end(); ++pit) {
00272                 mInlierIndices.push_back(*pit);
00273                 Vec3 tp = mPlane.transformToXYPlane(pointCloud.points[*pit].getVector3fMap());
00274                 if (tp.x() < mXMin) mXMin = tp.x();
00275                 if (tp.x() > mXMax) mXMax = tp.x();
00276                 if (tp.y() < mYMin) mYMin = tp.y();
00277                 if (tp.y() > mYMax) mYMax = tp.y();
00278         }
00279         computeOrientedBoundingBox();
00280         computeBoundingRectangle();
00281 }
00282 
00283 /*****************************************************************************/
00284 
00285 template<typename PointCloudType>
00286 void PlanePatch::computeHeightMap(const float texturePixelSize, const PointCloudType& pointCloud,
00287                 const unsigned int dilateIterations) {
00288         unsigned int hPot = mTextureMap.rows;
00289         unsigned int wPot = mTextureMap.cols;
00290         mHeightMap = cv::Mat::zeros(hPot, wPot, CV_32FC1);
00291         cv::Mat texCounter(cv::Mat::zeros(hPot, wPot, CV_8UC1));
00292         float distThresh = getDistanceThreshold();
00293         for (PointIndices::const_iterator point_it = mInlierIndices.begin(); point_it != mInlierIndices.end(); ++point_it) {
00294                 float distanceToPlane = mPlane.signedDistance(pointCloud.points[*point_it].getVector3fMap());
00295                 float distToMaxDistRatio = distanceToPlane / distThresh;
00296                 float normalizedRatio = 0.5 * distToMaxDistRatio;
00297                 Vec3 p = mPlane.transformToXYPlane(pointCloud.points[*point_it].getVector3fMap());
00298                 unsigned int x = fabs(p[0] - mXMin) / texturePixelSize;
00299                 unsigned int y = fabs(p[1] - mYMin) / texturePixelSize;
00300                 mHeightMap.at<float> (y, x) += normalizedRatio + 0.5f;
00301                 texCounter.at<char> (y, x) += 1;
00302         }
00303         for (unsigned int hind = 0; hind < hPot; ++hind) {
00304                 for (unsigned int wind = 0; wind < wPot; ++wind) {
00305                         char count = texCounter.at<char> (hind, wind);
00306                         if (count != 0) {
00307                                 mHeightMap.at<float> (hind, wind) /= count;
00308                         }
00309                 }
00310         }
00311 
00312         if (dilateIterations)
00313                 cv::dilate(mHeightMap, mHeightMap, cv::Mat(), cv::Point(-1, -1), dilateIterations);
00314         cv::GaussianBlur(mHeightMap, mHeightMap, cv::Size(3, 3), 2, 2);
00315         computeNormalMap();
00316 }
00317 
00318 /*****************************************************************************/
00319 
00320 template<typename PointCloudType>
00321 void PlanePatch::initializeTransformationsWithoutPCA(const PointCloudType& pointCloud) {
00322         mCoG = Eigen::Vector3f(0, 0, 0);
00323         for (PointIndices::const_iterator it = mInlierIndices.begin(); it != mInlierIndices.end(); ++it) {
00324                 mCoG += pointCloud.points[*it].getVector3fMap();
00325         }
00326         mCoG /= (float) mInlierIndices.size();
00327 }
00328 
00329 /*****************************************************************************/
00330 
00331 template<typename PointCloudType>
00332 void PlanePatch::initializeTransformationsWithPCA(const PointCloudType& pointCloud) {
00333         Points points;
00334         mCoG = Eigen::Vector3f(0, 0, 0);
00335         for (PointIndices::const_iterator it = mInlierIndices.begin(); it != mInlierIndices.end(); ++it) {
00336                 const Vec3& p = pointCloud.points[*it].getVector3fMap();
00337                 points.push_back(p);
00338                 mCoG += p;
00339         }
00340         mCoG /= (float) mInlierIndices.size();
00341 
00342         Eigen::Matrix3f cov(Eigen::Matrix3f::Zero());
00343         for (Points::const_iterator it = points.begin(); it != points.end(); ++it) {
00344                 Vec3 p = *it - mCoG;
00345                 cov += p * p.transpose();
00346         }
00347         Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> es;
00348         es.compute(cov);
00349         const Eigen::Matrix<float, 3, 3>& eigen_vectors = es.eigenvectors();
00350 
00351         mPlane = Plane3D(Vec3(eigen_vectors.col(0)), eigen_vectors.col(0).dot(mCoG));
00352 }
00353 
00354 /*****************************************************************************/
00355 
00356 template<typename PointCloudType>
00357 void PlanePatch::initializeWithoutPCA(const PointCloudType& pointCloud) {
00358         initializeTransformationsWithoutPCA(pointCloud);
00359         calculateMinMax(pointCloud);
00360         computeOrientedBoundingBox();
00361         computeBoundingRectangle();
00362 }
00363 
00364 /*****************************************************************************/
00365 
00366 template<typename PointCloudType>
00367 void PlanePatch::initializeWithPCA(const PointCloudType& pointCloud) {
00368         initializeTransformationsWithPCA(pointCloud);
00369         calculateMinMax(pointCloud);
00370         computeOrientedBoundingBox();
00371         computeBoundingRectangle();
00372 }
00373 
00374 /*****************************************************************************/
00375 
00376 template<typename PointCloudType>
00377 void PlanePatch::calculateMinMax(const PointCloudType& pointCloud) {
00378         mXMin = mYMin = mZMin = std::numeric_limits<float>::max();
00379         mXMax = mYMax = mZMax = -std::numeric_limits<float>::max();
00380 
00381         //transform from "normal" xyz-coordinates to plane-coordinate system
00382         //compute min/max of BB/BR in three dimensions
00383         for (PointIndices::const_iterator it = mInlierIndices.begin(); it != mInlierIndices.end(); ++it) {
00384                 const Eigen::Vector3f& p = mPlane.transformToXYPlane(pointCloud.points[*it].getVector3fMap());
00385                 if (p(0) < mXMin) {
00386                         mXMin = p(0);
00387                 }
00388                 if (p(0) > mXMax) {
00389                         mXMax = p(0);
00390                 }
00391                 if (p(1) < mYMin) {
00392                         mYMin = p(1);
00393                 }
00394                 if (p(1) > mYMax) {
00395                         mYMax = p(1);
00396                 }
00397                 if (p(2) < mZMin)
00398                         mZMin = p(2);
00399                 if (p(2) > mZMax)
00400                         mZMax = p(2);
00401         }
00402 }
00403 
00404 /*****************************************************************************/
00405 
00406 template<typename PointCloudType>
00407 void PlanePatch::rotateToPrincipalAxis(Eigen::Matrix3f& m, const PointCloudType& pointCloud, const Vec3& greatestEigenVector) const {
00408         Vec3 v(Vec3::Zero());
00409         if (greatestEigenVector == v) {
00410                 // use PCA to rotate the coordinate system of the plane, s.t. e1 coincides with the first principal axis
00411                 Eigen::Matrix3f cov(Eigen::Matrix3f::Zero());
00412                 for (PointIndices::const_iterator it = mInlierIndices.begin(); it != mInlierIndices.end(); ++it) {
00413                         Eigen::Vector3f p = getEigenVecFromPCL(pointCloud.points[*it]) - mCoG;
00414                         cov += p * p.transpose();
00415                 }
00416                 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> es;
00417                 es.compute(cov);
00418                 v = es.eigenvectors().col(2);
00419 
00420         } else
00421                 v = greatestEigenVector;
00422         Vec3 e1(1, 0, 0);
00423         e1 = m * e1;
00424         float rotAngle = acos(e1.dot(v));
00425         m = m * Eigen::AngleAxisf(-rotAngle, mPlane.getPlaneNormal());
00426 }
00427 
00428 #endif /*_PlanePatch_h_*/


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