KernelCollectionPCA.cpp
Go to the documentation of this file.
1 // (C) Copyright Renaud Detry 2007-2015.
2 // Distributed under the GNU General Public License and under the
3 // BSD 3-Clause License (See accompanying file LICENSE.txt).
4 
5 /** @file */
6 
9 
10 namespace nuklei
11 {
12 
13  kernel::se3
15  {
16  NUKLEI_TRACE_BEGIN();
17 #ifdef NUKLEI_USE_CGAL
18  using namespace cgal_pca_types;
19  std::list<Point_3> points;
20  for (const_iterator i = begin(); i != end(); ++i)
21  {
22  Vector3 loc = i->getLoc();
23  points.push_back(Point_3(loc[0], loc[1], loc[2]));
24  }
25 
26  Plane_3 plane;
27  Point_3 centroid;
28 #if CGAL_VERSION_NR >= 1030400000
29  CGAL::linear_least_squares_fitting_3(points.begin(),points.end(), plane, centroid, CGAL::Dimension_tag<0>());
30 #else
31  CGAL::linear_least_squares_fitting_3(points.begin(),points.end(), plane, centroid);
32 #endif
33  Matrix3 m;
34  m.SetColumn(0, Vector3(plane.base1()[0], plane.base1()[1], plane.base1()[2]));
35  m.SetColumn(1, Vector3(plane.base2()[0], plane.base2()[1], plane.base2()[2]));
36  m.SetColumn(2, Vector3(plane.orthogonal_vector()[0], plane.orthogonal_vector()[1], plane.orthogonal_vector()[2]));
37  la::normalized(m);
38 
39  kernel::se3 k;
40  k.loc_ = Vector3(centroid[0], centroid[1], centroid[2]);
41  k.ori_ = la::quaternionCopy(m);
42  k.loc_h_ = 0;
43  for (const_iterator i = begin(); i != end(); ++i)
44  {
45  coord_t d = dist<groupS::r3>::d(k.loc_, i->getLoc());
46  if (d > k.loc_h_) k.loc_h_ = d;
47  }
48 
49  PlaneDescriptor pd;
50  k.setDescriptor(pd);
51 
52  return k;
53 #else
54  NUKLEI_THROW("This function requires CGAL. See http://renaud-detry.net/nuklei/group__install.html");
55 #endif
56  NUKLEI_TRACE_END();
57  }
58 
60  KernelCollection::ransacPlaneFit(coord_t inlinerThreshold, unsigned nSeeds) const
61  {
62  NUKLEI_TRACE_BEGIN();
63 #ifdef NUKLEI_USE_CGAL
64  using namespace cgal_pca_types;
65 
66  if (size() < 3)
67  NUKLEI_THROW("Only " << size() << " points in KernelCollection. " <<
68  "Need at least 3 for plane fitting.");
69 
70  Plane_3 bestPlane(Point_3(1,0,0), Point_3(0,1,0), Point_3(0,0,0));
71 
72  int bestPlaneInliners = 0;
73  for (unsigned r = 0; r < nSeeds; ++r)
74  {
75  std::vector<Point_3> randomPoints;
76  for (int i = 0; i < 3; ++i)
77  {
78  Vector3 loc = at(Random::uniformInt(size())).getLoc();
79  randomPoints.push_back(Point_3(loc[0], loc[1], loc[2]));
80  }
81  Plane_3 plane(randomPoints.at(0),
82  randomPoints.at(1),
83  randomPoints.at(2));
84  if (plane.is_degenerate()) continue;
85 
86  int inliners = 0;
87  for (const_iterator i = begin(); i != end(); ++i)
88  {
89  Vector3 loc = i->getLoc();
90  Point_3 proj = plane.projection(Point_3(loc[0], loc[1], loc[2]));
91  coord_t d = dist<groupS::r3>::d(Vector3(proj[0], proj[1], proj[2]),
92  loc);
93  if (d < inlinerThreshold) inliners++;
94  }
95 
96  if (inliners > bestPlaneInliners)
97  {
98  bestPlaneInliners = inliners;
99  bestPlane = plane;
100  }
101  }
102 
103  NUKLEI_ASSERT(bestPlaneInliners > 0)
104 
105  KernelCollection kc;
106  for (const_iterator i = begin(); i != end(); ++i)
107  {
108  Vector3 loc = i->getLoc();
109  Point_3 proj = bestPlane.projection(Point_3(loc[0], loc[1], loc[2]));
110  coord_t d = dist<groupS::r3>::d(Vector3(proj[0], proj[1], proj[2]),
111  loc);
112  if (d < inlinerThreshold) kc.add(*i);
113  }
114 
115  return kc.linearLeastSquarePlaneFit();
116 #else
117  NUKLEI_THROW("This function requires CGAL. See http://renaud-detry.net/nuklei/group__install.html");
118 #endif
119  NUKLEI_TRACE_END();
120  }
121 
122  namespace la
123  {
124 // Vector3 project(const Plane3& plane, const Vector3& point)
125 // {
126 // NUKLEI_TRACE_BEGIN();
127 //#ifdef NUKLEI_USE_CGAL
128 // //fixme: this is easy to do without CGAL.
129 // // so do it without CGAL.
130 // using namespace cgal_pca_types;
131 //
132 // Plane_3 cplane(plane.Normal.X(), plane.Normal.Y(), plane.Normal.Z(), -plane.Constant);
133 // Point_3 proj = cplane.projection(Point_3(point[0], point[1], point[2]));
134 // return Vector3(proj[0], proj[1], proj[2]);
135 //#else
136 // NUKLEI_THROW("This function requires CGAL. See http://renaud-detry.net/nuklei/group__install.html");
137 //#endif
138 // NUKLEI_TRACE_END();
139 // }
140  }
141 }
142 
143 
Quaternion ori_
Kernel orientation.
Definition: Kernel.h:482
kernel::se3 linearLeastSquarePlaneFit() const
Fits a plane to the positions of the kernels contained in *this.
kernel::se3 ransacPlaneFit(coord_t inlinerThreshold, unsigned nSeeds=100) const
Fits a plane to the positions of the kernels contained in *this.
void add(const kernel::base &f)
Adds a copy of f.
Public namespace.
Definition: Color.cpp:9
Container::const_iterator const_iterator
KernelCollection iterator.
Definition: Kernel.h:404
This class acts as a vector-like container for kernels. It also provides methods related to kernel de...
Vector3 loc_
Kernel location.
Definition: Kernel.h:480
Definition: Descriptor.h:307
Container::reference at(Container::size_type n)
Returns the kernel at index n.
#define NUKLEI_ASSERT(expression)
Throws an Error if expression is not true.
Definition: Common.h:113
static unsigned long int uniformInt(unsigned long int n)
This function returns a random integer from 0 to n-1 inclusive.
Definition: Random.cpp:195
double coord_t
Type for point coordinates.
Definition: Definitions.h:25
Container::iterator end()
Returns an iterator pointing to the last kernel.
Container::iterator begin()
Returns an iterator pointing to the first kernel.
coord_t loc_h_
Location bandwidth.
Definition: Kernel.h:484
Definition: GenericKernel.h:73
Container::size_type size() const
Returns the number of kernels.
#define NUKLEI_THROW(x)
Throws an Error.
Definition: Common.h:94
© Copyright 2007-2013 Renaud Detry.
Distributed under the terms of the GNU General Public License (GPL).
(See accompanying file LICENSE.txt or copy at http://www.gnu.org/copyleft/gpl.html.)
Revised Sun Sep 13 2020 19:10:06.