19 #include <vgl/vgl_homg_point_2d.h>
20 #include <vgl/vgl_homg_point_3d.h>
21 #include <vgl/vgl_distance.h>
22 #include <mvl/PMatrix.h>
23 #include <mvl/PMatrixComputeLinear.h>
24 #include <mvl/HomgNorm2D.h>
25 #include <mvl/PMatrixDecompCR.h>
26 #include <vnl/vnl_least_squares_function.h>
27 #include <vnl/algo/vnl_levenberg_marquardt.h>
30 #include "SimpleOpt.h"
42 {
OPT_SKEW, _T(
"--no-skew"), SO_NONE },
44 {
OPT_SQUARE, _T(
"--square-pixels"), SO_NONE },
48 {
OPT_VERB, _T(
"--verbose"), SO_NONE },
51 {
OPT_OUT, _T(
"-o"), SO_REQ_SEP },
62 #include "p_compute.help"
71 std::vector<vgl_homg_point_3d<double> > & points_world) :
79 void f(
const vnl_vector<double>& x, vnl_vector<double>& fx);
95 p0(0,0) = x[0]; p0(0,1) = x[1]; p0(0,2) = x[2]; p0(0,3) = x[3];
96 p0(1,0) = x[4]; p0(1,1) = x[5]; p0(1,2) = x[6]; p0(1,3) = x[7];
97 p0(2,0) = x[8]; p0(2,1) = x[9]; p0(2,2) = x[10]; p0(2,3) = x[11];
98 double no = sqrt(p0(2,0)*p0(2,0)+p0(2,1)*p0(2,1)+p0(2,2)*p0(2,2));
113 PMatrixDecompCR decomp(P);
114 vnl_double_3x3 K = decomp.C;
130 p0(0,0) = x[0]; p0(0,1) = x[1]; p0(0,2) = x[2]; p0(0,3) = x[3];
131 p0(1,0) = x[4]; p0(1,1) = x[5]; p0(1,2) = x[6]; p0(1,3) = x[7];
132 p0(2,0) = x[8]; p0(2,1) = x[9]; p0(2,2) = x[10]; p0(2,3) = x[11];
133 double no = sqrt(p0(2,0)*p0(2,0)+p0(2,1)*p0(2,1)+p0(2,2)*p0(2,2));
136 PMatrixDecompCR decomp(P);
137 vnl_double_3x3 K = decomp.C;
138 double d = K(0,1)*K(0,1);
139 d += (K(0,0)-K(1,1))*(K(0,0)-K(1,1));
148 std::vector<vgl_homg_point_3d<double> > & points_world) :
154 void f(
const vnl_vector<double>& x, vnl_vector<double>& fx);
173 p0(0,0) = x[0]; p0(0,1) = x[1]; p0(0,2) = x[2]; p0(0,3) = x[3];
174 p0(1,0) = x[4]; p0(1,1) = x[5]; p0(1,2) = x[6]; p0(1,3) = x[7];
175 p0(2,0) = x[8]; p0(2,1) = x[9]; p0(2,2) = x[10]; p0(2,3) = x[11];
176 double no = sqrt(p0(2,0)*p0(2,0)+p0(2,1)*p0(2,1)+p0(2,2)*p0(2,2));
191 vnl_double_3x4 pmat2 =
hk_*p0*
hK_;
192 no = sqrt(pmat2(2,0)*pmat2(2,0)+pmat2(2,1)*pmat2(2,1)+pmat2(2,2)*pmat2(2,2));
195 PMatrixDecompCR decomp(P2);
196 vnl_double_3x3 K = decomp.C;
209 p0(0,0) = x[0]; p0(0,1) = x[1]; p0(0,2) = x[2]; p0(0,3) = x[3];
210 p0(1,0) = x[4]; p0(1,1) = x[5]; p0(1,2) = x[6]; p0(1,3) = x[7];
211 p0(2,0) = x[8]; p0(2,1) = x[9]; p0(2,2) = x[10]; p0(2,3) = x[11];
216 PMatrixDecompCR decomp(P);
217 vnl_double_3x3 K = decomp.C;
218 double d = (K(0,0)-
K_(0,0))*(K(0,0)-
K_(0,0));
219 d += (K(0,1)-
K_(0,1))*(K(0,1)-
K_(0,1));
220 d += (K(0,2)-
K_(0,2))*(K(0,2)-
K_(0,2));
221 d += (K(1,1)-
K_(1,1))*(K(1,1)-
K_(1,1));
222 d += (K(1,2)-
K_(1,2))*(K(1,2)-
K_(1,2));
231 std::vector<vgl_homg_point_3d<double> > & points_world) :
236 void f(
const vnl_vector<double>& x, vnl_vector<double>& fx);
245 p0(0,0) = x[0]; p0(0,1) = x[1]; p0(0,2) = x[2]; p0(0,3) = x[3];
246 p0(1,0) = x[4]; p0(1,1) = x[5]; p0(1,2) = x[6]; p0(1,3) = x[7];
247 p0(2,0) = x[8]; p0(2,1) = x[9]; p0(2,2) = x[10]; p0(2,3) = x[11];
251 vgl_homg_point_2d<double> center(u0,v0);
255 double k0 = 1.-k1-k2-k3;
260 double r= vgl_distance(center,im);
261 double L = k0+k1*r+k2*r*r+k3*r*r*r;
264 double un = u0+L*(u-u0);
265 double vn = v0+L*(
v-v0);
266 fx[i*2] = un-im.x()/im.w();
267 fx[i*2+1] = vn-im.y()/im.w();
281 bool nonlinear =
false;
282 bool homogeneous =
false;
283 bool squarepixels =
false;
287 std::string out_code(
"p");
288 std::string internal_file;
290 double k0, k1, k2, k3;
294 if (args.LastError() == SO_SUCCESS)
301 internal_file = args.OptionArg();
306 else if (args.OptionId() ==
OPT_SKEW)
310 else if (args.OptionId() ==
OPT_VERB)
314 else if (args.OptionId() ==
OPT_OUT)
315 out_code = args.OptionArg();
320 std::cerr <<
"Invalid argument: " << args.OptionText() << std::endl;
321 return error(args.LastError());
326 if (args.FileCount() != 0)
return error(-2);
327 if (radial|| squarepixels|| noskew|| (internal_file !=
"")) nonlinear =
true;
329 if (internal_file !=
"")
331 std::ifstream
in(internal_file.c_str());
334 std::cerr <<
"Cannot open file '" << internal_file <<
"'" << std::endl;
337 K0 =
new vnl_double_3x3;
340 if ((nx!=3)||(ny!=3))
342 std::cerr <<
"Internal orientation matrix has wrong dimension: " << nx <<
"x" << ny <<
" and should be 3x3" << std::endl;
348 std::vector<vgl_homg_point_2d<double> > points_image;
349 std::vector<vgl_homg_point_3d<double> > points_world;
351 while (std::cin.good()) {
358 points_image.push_back(vgl_homg_point_2d<double>(x,y,t));
359 std::cin >> x >> y >> z;
362 points_world.push_back(vgl_homg_point_3d<double>(x,y,z,t));
367 int npts = points_image.size();
369 double um = 0;
double vm = 0;
370 double xm = 0;
double ym = 0;
double zm = 0;
371 for (
int i=0; i< npts; i++)
373 um += points_image[i].x();
374 vm += points_image[i].y();
375 xm += points_world[i].x();
376 ym += points_world[i].y();
377 zm += points_world[i].z();
379 um /= npts; vm /= npts;
380 xm /= npts;
ym /= npts; zm /= npts;
382 a_point im0(um,vm,0.);
383 a_point wo0(
xm,
ym,zm);
386 for (
int i=0; i< npts; i++)
388 a_point im(points_image[i].x(),points_image[i].y(),0.);
389 double di = dist(im,im0);
391 a_point wo(points_world[i].x(),points_world[i].y(),points_world[i].z());
392 double dw = dist(wo,wo0);
395 dim = sqrt(dim)/npts;
396 dwm = sqrt(dwm)/npts;
398 std::vector<vgl_homg_point_2d<double> > points_image_n;
399 std::vector<vgl_homg_point_3d<double> > points_world_n;
400 for (
int i=0; i< npts; i++)
402 double u = (points_image[i].x()-um)/dim;
403 double v = (points_image[i].y()-vm)/dim;
404 double x = (points_world[i].x()-
xm)/dwm;
405 double y = (points_world[i].y()-
ym)/dwm;
406 double z = (points_world[i].z()-zm)/dwm;
407 points_image_n.push_back(vgl_homg_point_2d<double>(u,
v,1.0));
408 points_world_n.push_back(vgl_homg_point_3d<double>(x,y,z,1.0));
411 vnl_double_3x3 hk(0.);
412 hk.fill_diagonal(dim);
416 vnl_double_4x4 hK(0.);
417 hK.fill_diagonal(1./dwm);
424 auto P =
new PMatrix;
426 auto pmat =
new vnl_double_3x4;
427 PMatrixComputeLinear computor;
428 if (!computor.compute(points_image_n, points_world_n,P))
430 std::cerr <<
"Error" << std::endl;
438 vnl_double_3x4 pmat2 = hk*(*pmat)*hK;
439 double no = sqrt(pmat2(2,0)*pmat2(2,0)+pmat2(2,1)*pmat2(2,1)+pmat2(2,2)*pmat2(2,2));
443 for (
int i=0; i<npts; i++)
445 vgl_homg_point_2d<double>
pt = P2.project(points_world[i]);
446 double d = vgl_distance(
pt,points_image[i]);
449 std::cerr <<
"Matrix P before optimisation:" << std::endl;
450 std::cerr << P2 << std::endl;
451 std::cerr <<
"RMS error before optimisation: " << sqrt(m/points_world.size()) << std::endl;
453 vnl_vector<double> x;
462 else if (internal_file !=
"")
466 for (
int i = 0; i< 3; i++)
468 for (
int j = 0; j< 4; j++)
476 x[12] = 0; x[13] = 0;
477 x[14] = 0; x[15] = 0; x[16] = 0;
479 vnl_levenberg_marquardt levmarq(*f);
480 if ((!radial)&&((squarepixels)||(noskew)))
486 for (
int j=0;j<5; j++)
494 }
else if (internal_file !=
"")
502 for (
int j=0;j<5; j++)
515 std::cerr <<
"Levenberg Marquardt" << std::endl
516 <<
"min: " << levmarq.get_end_error() <<
" at " << x << std::endl
517 <<
"iterations: " << levmarq.get_num_iterations() <<
" "
518 <<
"evaluations: " << levmarq.get_num_evaluations() << std::endl;
519 levmarq.diagnose_outcome();
522 p0(0,0) = x[0]; p0(0,1) = x[1]; p0(0,2) = x[2]; p0(0,3) = x[3];
523 p0(1,0) = x[4]; p0(1,1) = x[5]; p0(1,2) = x[6]; p0(1,3) = x[7];
524 p0(2,0) = x[8]; p0(2,1) = x[9]; p0(2,2) = x[10]; p0(2,3) = x[11];
532 k3 = x[16]/dim/dim/dim;
533 k0 = 1.-k1*dim-k2*dim*dim-k3*dim*dim*dim;
534 std::cerr << k0 << std::endl;
535 std::cout <<
"-xc=" << cu0 <<
" -yc=" << cv0 <<
" -k1=" << k1 <<
" -k2=" << k2 <<
" -k3=" << k3 << std::endl;
540 vnl_double_3x4 pmat2 = hk*(*pmat)*hK;
541 double no = sqrt(pmat2(2,0)*pmat2(2,0)+pmat2(2,1)*pmat2(2,1)+pmat2(2,2)*pmat2(2,2));
545 vgl_homg_point_2d<double> center;
548 for (
int i=0; i<points_world.size(); i++)
551 vgl_homg_point_2d<double>
pt = P2.project(points_world[i]);
554 double r= vgl_distance(center,
pt);
555 double L = 1+k1*r+k2*r*r+k3*r*r*r;
556 double u = points_image[i].x();
557 double v = points_image[i].y();
558 double un = cu0+L*(u-cu0);
559 double vn = cv0+L*(
v-cv0);
560 vgl_homg_point_2d<double> im2(un,vn,1.);
561 d = vgl_distance(
pt,im2);
564 d = vgl_distance(
pt,points_image[i]);
568 std::cerr <<
"RMS error: " << sqrt(m/points_world.size()) << std::endl;
571 PMatrixDecompCR decomp(P2);
572 std::cout <<
"3 3" << std::endl;
573 std::cout << decomp.C << std::endl;;
574 }
else if (out_code==
"e")
576 PMatrixDecompCR decomp(P2);
577 std::cout <<
"3 4" << std::endl;
578 std::cout << decomp.Po << std::endl;
582 std::cout <<
"3 4\n";
583 std::cout << P2 << std::endl;
camera solver with radial distorsions
void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
std::vector< vgl_homg_point_3d< double > > & points_world_
std::vector< vgl_homg_point_2d< double > > & points_image_
a_camera2_function(std::vector< vgl_homg_point_2d< double > > &points_image, std::vector< vgl_homg_point_3d< double > > &points_world)
camera solver with internal calibration
void set_w(const double w)
a_camera_function_internal(std::vector< vgl_homg_point_2d< double > > &points_image, std::vector< vgl_homg_point_3d< double > > &points_world)
std::vector< vgl_homg_point_3d< double > > & points_world_
double get_constraint(const vnl_vector< double > &x)
void set_K(const vnl_double_3x3 &K)
void set_hk(const vnl_double_3x3 &K)
std::vector< vgl_homg_point_2d< double > > & points_image_
void set_hK(const vnl_double_4x4 &K)
void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
std::vector< vgl_homg_point_2d< double > > & points_image_
void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
double get_constraint(const vnl_vector< double > &x)
void set_constraints(const bool sp, const bool sk)
std::vector< vgl_homg_point_3d< double > > & points_world_
void set_w(const double w)
a_camera_function(std::vector< vgl_homg_point_2d< double > > &points_image, std::vector< vgl_homg_point_3d< double > > &points_world)
double v(const uint32_t step, const uint32_t n)
CSimpleOpt::SOption g_rgOptions[]
int main(int argc, char **argv)