cgv
Loading...
Searching...
No Matches
plane.h
1#pragma once
2#include <cgv/math/vec.h>
3#include <cgv/math/point_operations.h>
4#include <cgv/math/eig.h>
5#include <algorithm>
6
7namespace cgv{
8 namespace math{
9
17template <typename T>
18T plane_val(const vec<T>& plane,const vec<T>& x)
19{
20
21 assert(plane.size()-1 == x.size());
22
23 T val=0;
24 for(unsigned i = 0;i< x.size(); i++)
25 val += plane(i)*x(i);
26
27 return val+plane(plane.size()-1);
28}
29
31template <typename T>
32vec<T> plane_val(const vec<T>& plane,const mat<T>& xs)
33{
34
35 assert(plane.size()-1 == xs.nrows());
36
37 vec<T> vals(xs.ncols());
38 for(unsigned i = 0;i< xs.ncols(); i++)
39 vals(i) = plane_val(plane,xs.col(i));
40
41
42 return vals;
43}
44
45
46//construct implicit plane from 3 points
47template <typename T>
48vec<T> plane_fit(const vec<T>& p1,const vec<T>& p2,const vec<T>& p3)
49{
50 vec<T> plane(4);
51 double l_nml;
52
53 vec<T> nml = cross(normalize(p2-p1),normalize(p3-p1));
54 l_nml = length(nml);
55 assert(l_nml != 0);
56
57 nml/=l_nml;
58 plane.set(nml(0),nml(1),nml(2),-dot(p1,nml));
59 return plane;
60}
61
62//fit implicit plane into multiple points (total least squares)
63template <typename T>
64vec<T> tls_plane_fit(const mat<T>& points)
65{
66 vec<T> plane(4);
67 mat<T> covmat,v;
68 diag_mat<T> d;
69 vec<T> mean;
70
71 covmat_and_mean(points,covmat, mean);
72 eig_sym(covmat,v,d);
73
74// T l_nml;
75
76 vec<T> nml = normalize(v.col(2));
77
78 plane.set(nml(0),nml(1),nml(2),-dot(mean,nml));
79 return plane;
80}
81
82
83
84
91template <typename T>
92vec<T> ransac_plane_fit(const mat<T>& points,const T p_out=0.8, const T d_max=0.001, const T p_surety = 0.99, bool msac=true)
93{
94 assert(points.nrows == 3);
95 vec<T> plane(4);
96
97 vec<unsigned int> ind;
98 vec<T> p1,p2,p3,dists(points.ncols());
100 unsigned n = points.ncols;
101 unsigned max_iter = num_ransac_iterations(3,p_out,psurety);
102 unsigned num_inlier = (unsigned)::ceil((1-p_out)*points.ncols());
103
104 T error = std::numeric_limits<T>::max();
105
106 for(unsigned i = 0; i < max_iter; i++)
107 {
108 //random sample
109 do
110 {
111 rg.uniform_nchoosek(n,3,ind);
112 p1 = points.col(ind(0));
113 p2 = points.col(ind(1));
114 p3 = points.col(ind(2));
115 }
116 while(fabs(length(cross(q2-q1,q3-q1)))<0.001);
117
118 //fit
119 vec<T> pl = plane_fit(p1,p2,p3);
120
121 //consensus
122 int n_inlier=0;
123 T e = 0;
124
125 for(unsigned i = 0; i < points.ncols(); i++)
126 {
127 dists(i) = std::abs(plane_val(pl,points.col(i)));
128 if(dists(i) < d_max)
129 {
130 n_inlier++;
131 if(msac)
132 e += dists(i);
133 }
134 else
135 {
136 e += dmax;
137 }
138 }
139
140 //local reoptimize
141 if(loransac && n_inlier > 3)
142 {
143 mat<T> inliers(3,n_inlier);
144 int j=0;
145 n_inlier=0;
146 for(unsigned i = 0; i < points.ncols(); i++)
147 {
148 if(dists(i) < d_max)
149 {
150 n_inlier++;
151 inliers.set_col(j,points.col(i));
152 j++;
153 }
154 }
155 pl = plane_fit(inliers)
156
157 //recompute error
158 for(unsigned i = 0; i < points.ncols(); i++)
159 {
160 dists(i) = std::abs(plane_val(pl,points.col(i)));
161 if(dists(i) < d_max)
162 {
163
164 if(msac)
165 e += dists(i);
166 }
167 else
168 {
169 e += dmax;
170 }
171 }
172 }
173
174 //remember best plane
175 if(error > e)
176 {
177 error = e;
178 plane = pl;
179 }
180
181 if(n_inlier >= num_inlier)
182 {
183 p_out = (T)1-(T)n_inlier/(T)points.ncols();
184 max_iter = num_ransac_iterations(3,p_out,psurety);
185 }
186 }
187 return plane;
188}
189
190
191
192
193
194
195
196
197 }
198}
199
the cgv namespace
Definition print.h:11
High quality random number generator, which is a little bit slower than typical random number generat...
Definition random.h:27
void uniform_nchoosek(unsigned n, unsigned k, vec< unsigned > &indices)
creates a vector of k unique indices drawn from 0 to n-1
Definition random.h:506