MEPP2 Project
point_cloud_normal_wpca.hpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2019 University of Lyon and CNRS (France).
2 // All rights reserved.
3 //
4 // This file is part of MEPP2; you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as
6 // published by the Free Software Foundation; either version 3 of
7 // the License, or (at your option) any later version.
8 //
9 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
10 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11 
12 // -------------------------------------------------------------------------------------
13 // Iterative weighted PCA for robust and edge-aware normal vector estimation
14 //--------------------------------------------------------------------------------------
15 // Julia Sanchez, Florence Denis, David Coeurjolly, Florent dupont, Laurent Trassoudaine, Paul Checchin
16 // Liris (Lyon), Institut Pascal (Clermont Ferrand)
17 // Région Auvergne Rhône Alpes ARC6
18 // Private use for reviewers only
19 // --------------------------------------------------------------------------------------
20 
21 
22 #include <stdio.h>
23 #include <iostream>
24 #include <fstream>
25 //#include <omp.h> // Open mp disabled to avoid dependency
26 
27 #include "core.h"
28 #include "cloud.h"
29 
30 namespace FEVV {
31  namespace Filters {
32 
33  template< typename PointCloud,
34  typename PointMap,
35  typename NormalMap,
36  typename GeometryTraits = FEVV::Geometry_traits< PointCloud >
37  >
38  void compute_weighted_pca(const PointCloud& pointCloud,
39  const PointMap& pointMap,
40  NormalMap& normalMap,
41  int n_neight,
42  float noise,
43  float curvature,
44  const GeometryTraits &gt){
45 
48  RawCloud c;
49  int cloud_size = static_cast<int>(num_vertices(pointCloud));
50  auto iterator_pair = vertices(pointCloud);
51  auto vi = iterator_pair.first;
52  auto vi_end = iterator_pair.second;
53 
54  if(n_neight > cloud_size)
55  throw std::invalid_argument("compute_weighted_pca() -> n_neight parameter value bigger than the point cloud's number of point.");
56 
57  c.pointcloud_ = new Eigen::Matrix<float, Eigen::Dynamic, 3>(cloud_size+1, 3);
58 
59  vi = iterator_pair.first;
60  int i = 0;
61  for(; vi != vi_end; ++vi){
62  auto p = get(pointMap, *vi);
63  c.pointcloud_->row(i)[0] = gt.get_x(p);
64  c.pointcloud_->row(i)[1] = gt.get_y(p);
65  c.pointcloud_->row(i)[2] = gt.get_z(p);
66  ++i;
67  }
68 
70  c.buildTree();
71  float res = c.getResolution();
72  std::cout<<"cloud resolution : "<<res<<std::endl<<std::endl;
73 
74  Eigen::Matrix<float, Eigen::Dynamic, 3>* pc = c.getPC();
75  flann::Index<flann::L2<float>>* tree = c.getTree();
76 
77  //int n = 0;
78  //int inv = 0;
79  int nan = 0;
80  noise = std::max(noise, noise_min);
81 
82  std::cout<<"estimated noise="<<noise<<std::endl<<std::endl;
83  std::cout<<"minimum curvature radius tolerated="<<curvature<<std::endl<<std::endl;
84  std::cout<<"division factor="<<div_fact<<std::endl<<std::endl;
85 
86  std::vector<Eigen::Vector3f> normals(cloud_size);
87  std::vector<Eigen::Vector3f> points(cloud_size);
88  std::vector<int> onEdge(cloud_size);
89 
90  std::cout<<"------------------------------Computing normals------------------------------"<<std::endl<<std::endl;
91 
92  std::cout<<"Avancement : "<<std::endl;
93  auto t_tot1 = std::chrono::high_resolution_clock::now();
94 
95  // #pragma omp parallel for schedule(dynamic) num_threads(omp_get_max_threads()) shared(onEdge, pc, tree, noise, n_neigh, curvature, normals, points) // comment if one thread used
96  for (int i = 0; i < cloud_size; ++i)
97  {
98  CApp app(pc, tree, i, noise);
99  Eigen::Vector3f point_ref = app.getPoint();
101  app.selectNeighborsKnn(n_neight);
102 
103  if(!(i%1000))
104  std::cout<<((float)i/(float)cloud_size) * 100<<"%"<<std::endl;
105  app.init1();
106 
107  if( app.isOnEdge() ) // when the mean projection error is greater than the noise-------------------------------------------------------------------------------------------------------
108  {
109  onEdge[i] = 1;
110 
111  //Compute first solution n_1------------------------------------------------------------------------------------------------------
112  bool first = true;
113  app.Optimize(first);
114  app.OptimizePos(first, thresh_weight);
115 
116  //Compute second solution n_2------------------------------------------------------------------------------------------------------
117  app.reinitPoint();
118  app.init2();
119  first = false;
120  if(app.SuspectedOnEdge_)
121  {
122  app.Optimize(first);
123  app.OptimizePos(first, thresh_weight);
124  }
125 
126  //save result ------------------------------------------------------------------------------------------------------
127 
128  if( !app.isNan())
129  {
130  normals[i] = app.finalNormal_;
131  points[i] = app.finalPos_;
132  }
133  else
134  {
135  normals[i]={0,0,0};
136  points[i] = {0,0,0};
137  std::cout<<"nan normal or point :"<<i<<std::endl;
138  ++nan;
139  }
140  }
141  else
142  {
143  onEdge[i] = 0;
144 
145  if( !app.isNan())
146  {
147  normals[i] = app.finalNormal_;
148  points[i] = app.finalPos_;
149  }
150  else
151  {
152  std::cout<<"nan normal or point :"<<i<<std::endl;
153  ++nan;
154  }
155  }
156 
157  points[i] = point_ref;
158 
159  if(normals[i].dot(points[i])>0)
160  normals[i]=-normals[i];
161  }
162 
163  auto t_tot2 = std::chrono::high_resolution_clock::now();
164  typedef typename boost::property_traits< NormalMap >::value_type Normal;
165 
166  vi = iterator_pair.first;
167  for(size_t i = 0; i < normals.size(); ++i){
168  Normal normal(normals[i][0], normals[i][1], normals[i][2]);
169  put(normalMap, *vi, normal);
170  ++vi;
171  }
172 
173  std::cout<<"total time to get normals :" <<std::chrono::duration_cast<std::chrono::milliseconds>(t_tot2-t_tot1).count()<<" milliseconds"<<std::endl<<std::endl;
174  }
175 
176  template< typename PointCloud,
177  typename PointMap,
178  typename NormalMap,
179  typename GeometryTraits = FEVV::Geometry_traits< PointCloud >
180  >
181  void compute_weighted_pca(const PointCloud& pointCloud,
182  const PointMap& pointMap,
183  NormalMap& normalMap,
184  int n_neight,
185  float noise,
186  float curvature)
187  {
188  GeometryTraits gt(pointCloud);
189  compute_weighted_pca(pointCloud, pointMap, normalMap, n_neight, noise, curvature, gt);
190  }
191 
192  }
193 }
FEVV::DataStructures::AIF::vertices
std::pair< typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_iterator, typename boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertex_iterator > vertices(const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns the iterator range of the vertices of the mesh.
Definition: Graph_traits_aif.h:172
FEVV::DataStructures::AIF::num_vertices
boost::graph_traits< FEVV::DataStructures::AIF::AIFMesh >::vertices_size_type num_vertices(const FEVV::DataStructures::AIF::AIFMesh &sm)
Returns an upper bound of the number of vertices of the mesh.
Definition: Graph_traits_aif.h:191
CApp::isOnEdge
bool isOnEdge()
Definition: core.inl:196
cloud.h
CApp::OptimizePos
void OptimizePos(bool first, float thresh_weigh)
Definition: core.inl:284
RawCloud::getTree
flann::Index< flann::L2< float > > * getTree()
Definition: cloud.h:51
CApp::Optimize
void Optimize(bool first)
Definition: core.inl:235
CApp::init2
void init2()
Definition: core.inl:167
FEVV::Geometry_traits
Refer to Geometry_traits_documentation_dummy for further documentation on provided types and algorith...
Definition: Geometry_traits.h:162
RawCloud::pointcloud_
Eigen::Matrix< float, Eigen::Dynamic, 3 > * pointcloud_
Definition: cloud.h:55
CApp::isNan
bool isNan()
Definition: core.inl:416
RawCloud::getResolution
float getResolution()
Definition: cloud.inl:119
FEVV::Filters::compute_weighted_pca
void compute_weighted_pca(const PointCloud &pointCloud, const PointMap &pointMap, NormalMap &normalMap, int n_neight, float noise, float curvature, const GeometryTraits &gt)
Definition: point_cloud_normal_wpca.hpp:38
FEVV::get
FEVV::PCLPointCloudPointMap::value_type get(const FEVV::PCLPointCloudPointMap &pm, FEVV::PCLPointCloudPointMap::key_type key)
Specialization of get(point_map, key) for PCLPointCloud.
Definition: Graph_properties_pcl_point_cloud.h:117
RawCloud::buildTree
void buildTree()
Definition: cloud.inl:95
FEVV
Interfaces for plugins These interfaces will be used for different plugins.
Definition: Assert.h:16
CApp::SuspectedOnEdge_
bool SuspectedOnEdge_
Definition: core.h:200
CApp::finalPos_
Eigen::Vector3f finalPos_
Definition: core.h:197
RawCloud::getPC
Eigen::Matrix< float, Eigen::Dynamic, 3 > * getPC()
Definition: cloud.h:50
noise_min
const float noise_min
Definition: core.h:59
CApp::getPoint
Eigen::Vector3f getPoint()
Definition: core.h:167
CApp::reinitPoint
void reinitPoint()
Definition: core.inl:391
FEVV::put
void put(FEVV::PCLPointCloudPointMap &pm, FEVV::PCLPointCloudPointMap::key_type key, const FEVV::PCLPointCloudPointMap::value_type &value)
Specialization of put(point_map, key, value) for PCLPointCloud.
Definition: Graph_properties_pcl_point_cloud.h:126
thresh_weight
const float thresh_weight
Definition: core.h:62
core.h
CApp::selectNeighborsKnn
void selectNeighborsKnn(int N)
Definition: core.inl:28
CApp
Definition: core.h:65
CApp::finalNormal_
Eigen::Vector3f finalNormal_
Definition: core.h:196
RawCloud
Definition: cloud.h:45
CApp::init1
void init1()
Definition: core.inl:118
CApp::setParams
void setParams(float divFact, float curvature)
Definition: core.h:161
curvature
void curvature(FEVV::DataStructures::AIF::AIFMesh *mesh)
Definition: test_curvature_filter_aif.cpp:26
div_fact
const float div_fact
Definition: core.h:48