2 #ifndef vgl_fit_quadric_3d_hxx_ 3 #define vgl_fit_quadric_3d_hxx_ 8 #include <vnl/vnl_math.h> 11 #include <vnl/algo/vnl_svd.h> 12 #include <vnl/vnl_matrix.h> 14 # include <vcl_msvc_warnings.h> 18 #include <vnl/algo/vnl_levenberg_marquardt.h> 19 #include <vnl/algo/vnl_generalized_eigensystem.h> 20 #include <vnl/algo/vnl_real_eigensystem.h> 21 #include <vnl/algo/vnl_symmetric_eigensystem.h> 22 #include <vnl/vnl_least_squares_function.h> 29 for(
typename std::vector<
vgl_point_3d<T> >::iterator pit = points.begin();
30 pit != points.end(); ++pit)
54 std::vector<vgl_point_3d<T> > ret;
55 const unsigned n = static_cast<unsigned>(points_.size());
56 for (
unsigned i=0; i<n; i++){
66 size_t n = points_.size();
70 *errstream <<
"Insufficient number of points to fit quadric " << n << std::endl;
76 *errstream <<
"there is a problem with norm transform\n";
80 vnl_matrix<double> M(10,10, 0.0), N(10,10, 0.0);
81 for (
size_t i=0; i<n; i++) {
87 vnl_matrix<double> p(10, 1), dx(10,1,0.0), dy(10,1,0.0), dz(10,1,0.0);
88 double x = static_cast<double>(hp.
x()), y = static_cast<double>(hp.
y()),
89 z = static_cast<double>(hp.
z()), w = static_cast<double>(hp.
w());
90 p[0][0]= x*x; p[1][0]=y*y; p[2][0]=z*z; p[3][0]=x*y; p[4][0]=x*z;
91 p[5][0]= y*z; p[6][0]=x*w; p[7][0]=y*w; p[8][0]=z*w; p[9][0]=w*w;
92 dx[0][0] = 2.0*x; dx[3][0] = y; dx[4][0] = z; dx[6][0]=w;
93 dy[1][0] = 2.0*y; dy[3][0] = x; dy[5][0] = z; dy[7][0]=w;
94 dz[2][0] = 2.0*z; dz[4][0] = x; dz[5][0] = y; dz[8][0]=w;
95 M += p*(p.transpose());
96 N += (dx*(dx.transpose()) + dy*(dy.transpose()) + dz*(dz.transpose()));
105 vnl_generalized_eigensystem gev(M, N);
111 for(
size_t r = 0; r<10; ++r)
112 q[r] = static_cast<T>((gev.V)[r][0]);
115 if(
debug) std::cout <<
"q\n" << q << std::endl;
118 quadric_Taubin_.set(q[0],q[1],q[2],q[3],q[4],q[5],q[6],q[7],q[8],q[9]);
119 std::vector<std::vector<T> > qq = quadric_Taubin_.coef_matrix();
120 vnl_matrix<T> Q(4,4);
121 for(
size_t r = 0; r<4; ++r)
122 for(
size_t c = 0; c<4; ++c)
125 vnl_matrix<T> Qorig(4, 4);
126 Qorig = Tr.transpose() * Q * Tr;
127 for(
size_t r = 0; r<4; ++r)
128 for(
size_t c = 0; c<4; ++c)
129 qq[r][c] = Qorig[r][c];
131 quadric_Taubin_.set(qq);
132 if(
debug) std::cout << quadric_Taubin_.type_by_number(quadric_Taubin_.type()) <<std::endl;
136 for (
unsigned i=0; i<n; i++) {
137 T d = quadric_Taubin_.sampson_dist(points_[i]);
140 return static_cast<T>(dsum/n);
145 size_t n = points_.size();
149 *errstream <<
"Insufficient number of points to fit quadric " << n << std::endl;
155 *errstream <<
"there is a problem with norm transform\n";
159 vnl_matrix<double> M(10,10, 0.0), N(10,10, 0.0);
160 for (
size_t i=0; i<n; i++) {
166 vnl_matrix<double> p(10, 1);
167 double x = static_cast<double>(hp.
x()), y = static_cast<double>(hp.
y()),
168 z = static_cast<double>(hp.
z()), w = static_cast<double>(hp.
w());
169 p[0][0]= x*x; p[1][0]=y*y; p[2][0]=z*z; p[3][0]=x*y; p[4][0]=x*z;
170 p[5][0]= y*z; p[6][0]=x*w; p[7][0]=y*w; p[8][0]=z*w; p[9][0]=w*w;
171 M += p*(p.transpose());
176 for(
size_t i = 0; i<10; ++i)
194 N[0][0]= -1.0; N[0][1]= 1.0; N[0][2]= 1.0;
195 N[1][0]= 1.0; N[1][1]= -1.0; N[1][2]= 1.0;
196 N[2][0]= 1.0; N[2][1]= 1.0; N[2][2]= -1.0;
197 N[3][3]= -1.0; N[4][4]= -1.0; N[5][5]= -1.0;
206 vnl_generalized_eigensystem geign(N, M);
209 size_t min_index = 10;
210 vnl_matrix<double> q(10,1);
211 vnl_diag_matrix<double> D = geign.D;
212 double min_error = std::numeric_limits<double>::max();
213 for(
size_t i = 0; i<5; ++i){
214 for(
size_t r = 0; r<10; ++r)
215 q[r][0] = static_cast<T>((geign.V)[r][i])/sqrt(fabs(D[i]));
217 quadric_Allaire_.set(q[0][0],q[1][0],q[2][0],q[3][0],q[4][0],q[5][0],q[6][0],q[7][0],q[8][0],q[9][0]);
220 vnl_matrix<double> neu = q.transpose() * M * q;
221 vnl_matrix<double> den = q.transpose() * N * q;
222 double e = fabs(neu[0][0])/fabs(den[0][0]);
223 if(
debug) std::cout <<
"Error =" << e <<
"for q[" << i <<
"]\n" << q << std::endl;
229 for(
size_t r = 0; r<10; ++r)
230 q[r][0] = static_cast<T>((geign.V)[r][9])/sqrt(fabs(D[9]));
232 quadric_Allaire_.set(q[0][0],q[1][0],q[2][0],q[3][0],q[4][0],q[5][0],q[6][0],q[7][0],q[8][0],q[9][0]);
234 vnl_matrix<double> neu = q.transpose() * M * q;
235 vnl_matrix<double> den = q.transpose() * N * q;
236 double e = fabs(neu[0][0])/fabs(den[0][0]);
237 if(
debug) std::cout <<
"Error =" << e <<
" for q[" << 9 <<
"]\n" << q << std::endl;
244 std::cout <<
"failed to find ellipsoid" << std::endl;
247 if(
debug) std::cout <<
"Best ellipsoid is " << min_index << std::endl;
248 for(
size_t r = 0; r<10; ++r)
249 q[r][0] = static_cast<T>((geign.V)[r][min_index])/sqrt(fabs(D[min_index]));
252 quadric_Allaire_.set(q[0][0],q[1][0],q[2][0],q[3][0],q[4][0],q[5][0],q[6][0],q[7][0],q[8][0],q[9][0]);
253 std::vector<std::vector<T> > qq = quadric_Allaire_.coef_matrix();
254 vnl_matrix<T> Q(4,4);
255 for(
size_t r = 0; r<4; ++r)
256 for(
size_t c = 0; c<4; ++c)
259 vnl_matrix<T> Qorig(4, 4);
260 Qorig = Tr.transpose() * Q * Tr;
261 for(
size_t r = 0; r<4; ++r)
262 for(
size_t c = 0; c<4; ++c)
263 qq[r][c] = Qorig[r][c];
265 quadric_Allaire_.set(qq);
266 std::cout << quadric_Allaire_.type_by_number(quadric_Allaire_.type()) <<std::endl;
270 for (
unsigned i=0; i<n; i++) {
271 T d = quadric_Allaire_.sampson_dist(points_[i]);
274 return static_cast<T>(dsum/n);
278 size_t n = points_.size();
282 *errstream <<
"Insufficient number of points to fit quadric " << n << std::endl;
288 *errstream <<
"there is a problem with norm transform\n";
292 vnl_matrix<double> M(10,10, 0.0), N(10,10, 0.0);
293 for (
size_t i=0; i<n; i++) {
299 vnl_matrix<double> p(10, 1);
300 double x = static_cast<double>(hp.
x()), y = static_cast<double>(hp.
y()),
301 z = static_cast<double>(hp.
z()), w = static_cast<double>(hp.
w());
302 p[0][0]= x*x; p[1][0]=y*y; p[2][0]=z*z; p[3][0]=x*y; p[4][0]=x*z;
303 p[5][0]= y*z; p[6][0]=x*w; p[7][0]=y*w; p[8][0]=z*w; p[9][0]=w*w;
304 M += p*(p.transpose());
309 for(
size_t i = 0; i<10; ++i)
329 N[0][0]= 0.0; N[0][1]= 0.5; N[0][2]= 0.5;
330 N[1][0]= 0.5; N[1][1]= 0.0; N[1][2]= 0.5;
331 N[2][0]= 0.5; N[2][1]= 0.5; N[2][2]= 0.0;
332 N[3][3]= -0.25; N[4][4]= -0.25; N[5][5]= -0.25;
341 vnl_generalized_eigensystem geign(N, M);
342 if(
debug) std::cout << geign.D << std::endl;
343 if(
debug) std::cout << geign.V << std::endl;
346 size_t min_index = 10;
347 vnl_matrix<double> q(10,1);
348 vnl_diag_matrix<double> D = geign.D;
349 double min_error = std::numeric_limits<double>::max();
350 for(
size_t i = 0; i<5; ++i){
351 for(
size_t r = 0; r<10; ++r)
352 q[r][0] = (geign.V)[r][i]/sqrt(fabs(D[i]));
354 quadric_Allaire_.set(q[0][0],q[1][0],q[2][0],q[3][0],q[4][0],q[5][0],q[6][0],q[7][0],q[8][0],q[9][0]);
355 vnl_matrix<double> neu = q.transpose() * M * q;
356 vnl_matrix<double> den = q.transpose() * N * q;
357 double e = fabs(neu[0][0])/fabs(den[0][0]);
358 if(
debug) std::cout <<
"Error =" << e <<
"for q[" << i <<
"]\n" << q << std::endl;
359 if(
debug) std::cout <<
"Type "<< quadric_Allaire_.type_by_number(quadric_Allaire_.type()) <<std::endl;
366 std::cout <<
"failed to find saddle shape" << std::endl;
369 if(
debug) std::cout <<
"Best saddle shape is " << min_index << std::endl;
370 for(
size_t r = 0; r<10; ++r)
371 q[r][0] =(geign.V)[r][min_index]/sqrt(fabs(D[min_index]));
374 quadric_Allaire_.set(q[0][0],q[1][0],q[2][0],q[3][0],q[4][0],q[5][0],q[6][0],q[7][0],q[8][0],q[9][0]);
375 std::vector<std::vector<T> > qq = quadric_Allaire_.coef_matrix();
376 vnl_matrix<T> Q(4,4);
377 for(
size_t r = 0; r<4; ++r)
378 for(
size_t c = 0; c<4; ++c)
381 vnl_matrix<T> Qorig(4, 4);
382 Qorig = Tr.transpose() * Q * Tr;
383 for(
size_t r = 0; r<4; ++r)
384 for(
size_t c = 0; c<4; ++c)
385 qq[r][c] = Qorig[r][c];
387 quadric_Allaire_.set(qq);
388 std::cout << quadric_Allaire_.type_by_number(quadric_Allaire_.type()) <<std::endl;
392 for (
unsigned i=0; i<n; i++) {
393 T d = quadric_Allaire_.sampson_dist(points_[i]);
396 return static_cast<T>(dsum/n);
400 #undef VGL_FIT_QUADRIC_3D_INSTANTIATE 401 #define VGL_FIT_QUADRIC_3D_INSTANTIATE(T) \ 402 template class vgl_fit_quadric_3d<T > 404 #endif // vgl_fit_quadric_3d_hxx_
void clear()
clear internal data.
Fits a quadric surface to a set of 3D points.
std::vector< vgl_point_3d< T > > get_points() const
Represents a homogeneous 3D point.
vgl_fit_quadric_3d()=default
bool compute_from_points(std::vector< vgl_homg_point_3d< T > > const &points)
compute the normalizing transform.
T fit_ellipsoid_linear_Allaire(std::ostream *outstream=nullptr)
fit an ellipsoid using the linear Allaire method.
T fit_saddle_shaped_quadric_linear_Allaire(std::ostream *outstream=nullptr)
fit a quadric class from the set{ hyperboloid_of_one_sheets,.
void add_point(vgl_point_3d< T > const &p)
add a point to point set.
vnl_matrix_fixed< T, 4, 4 > const & get_matrix() const
Return the 4x4 homography matrix.
T fit_linear_Taubin(std::ostream *outstream=nullptr)
fit a general quadric to the stored points using the linear Taubin method.
Set of distance functions.
The similarity transform that normalizes a 3-d point set.