18 #include <mvl/HMatrix2D.h>
19 #include <mvl/HMatrix2DComputeLinear.h>
20 #include <vnl/vnl_least_squares_function.h>
21 #include <vnl/algo/vnl_levenberg_marquardt.h>
22 #include <vgl/vgl_distance.h>
24 #include "SimpleOpt.h"
32 {
OPT_HOMG, _T(
"--homogeneous"), SO_NONE },
34 {
OPT_VERB, _T(
"--verbose"), SO_NONE },
44 #include "h_compute.help"
53 std::vector<vgl_homg_point_2d<double> > & points_im2) :
58 void f(
const vnl_vector<double>& x, vnl_vector<double>& fx);
70 no += h(i,0)*h(i,0)+h(i,1)*h(i,1)+h(i,2)*h(i,2);
77 h0(0,0) = x[0]; h0(0,1) = x[1]; h0(0,2) = x[2];
78 h0(1,0) = x[3]; h0(1,1) = x[4]; h0(1,2) = x[5];
79 h0(2,0) = x[6]; h0(2,1) = x[7]; h0(2,2) = x[8];
85 vgl_homg_point_2d<double> pt_project = H.transform_to_plane2(
points_im1_[i]);
87 fx[i*2] = pt_project.x()/pt_project.w()-pt_true.x();
88 fx[i*2+1] = pt_project.y()/pt_project.w()-pt_true.y();
91 double dist = vgl_distance(pt_project,pt_true);
99 int main(
int argc,
char**argv)
102 bool nonlinear =
false;
103 bool homogeneous =
false;
107 if (args.LastError() == SO_SUCCESS)
113 else if (args.OptionId() ==
OPT_HOMG)
115 else if (args.OptionId() ==
OPT_VERB)
121 std::cerr <<
"Invalid argument: " << args.OptionText() << std::endl;
122 return error(args.LastError());
127 if (args.FileCount() != 0)
return error(-2);
130 std::vector<HomgPoint2D > points1;
131 std::vector<HomgPoint2D > points2;
132 while (std::cin.good())
138 points1.push_back(HomgPoint2D(x,y,w));
142 points2.push_back(HomgPoint2D(x,y,w));
145 if (nonlinear && points1.size()<5)
147 std::cerr <<
"option nonlinear is only active when the number of points is higher than 4" << std::endl;
151 int npts = points1.size();
153 double um1 = 0;
double vm1 = 0;
154 double um2 = 0;
double vm2 = 0;
155 for (
int i=0; i< npts; i++)
157 um1 += points1[i].x();
158 vm1 += points1[i].y();
159 um2 += points2[i].x();
160 vm2 += points2[i].y();
162 um1 /= npts; vm1 /= npts;
163 um2 /= npts; vm2 /= npts;
165 a_point im10(um1,vm1,0.);
166 a_point im20(um2,vm2,0.);
169 for (
int i=0; i< npts; i++)
171 a_point im1(points1[i].x(),points1[i].y(),0.);
172 double di = dist(im1,im10);
174 a_point im2(points2[i].x(),points2[i].y(),0.);
178 di1m = sqrt(di1m/npts);
179 di2m = sqrt(di2m/npts);
181 std::vector<vgl_homg_point_2d<double> > points_im1;
182 std::vector<vgl_homg_point_2d<double> > points_im2;
183 for (
int i=0; i< npts; i++)
185 double u1 = (points1[i].x()-um1)/di1m;
186 double v1 = (points1[i].y()-vm1)/di1m;
187 points_im1.push_back(vgl_homg_point_2d<double>(u1,v1,1.0));
188 points1[i].set(points_im1[i].x(),points_im1[i].y(),points_im1[i].w());
189 double u2 = (points2[i].x()-um2)/di2m;
190 double v2 = (points2[i].y()-vm2)/di2m;
191 points_im2.push_back(vgl_homg_point_2d<double>(u2,v2,1.0));
192 points2[i].set(points_im2[i].x(),points_im2[i].y(),points_im2[i].w());
195 vnl_double_3x3 hk1(0.);
196 hk1.fill_diagonal(1./di1m);
197 hk1(0,2) = -um1/di1m;
198 hk1(1,2) = -vm1/di1m;
200 vnl_double_3x3 hk2(0.);
201 hk2.fill_diagonal(di2m);
208 HMatrix2DComputeLinear computor;
209 HMatrix2D h = computor.compute(points1, points2);
211 vnl_double_3x3 h0 = h.get_matrix();
215 vnl_vector<double> x(9);
217 for (
int i = 0; i< 3; i++)
219 for (
int j = 0; j< 3; j++)
227 vnl_levenberg_marquardt levmarq(f);
229 std::cerr <<
"Errors (in the unit of ur, vr, wr)" << std::endl;
232 std::cerr << std::endl;
233 h0(0,0) = x[0]; h0(0,1) = x[1]; h0(0,2) = x[2];
234 h0(1,0) = x[3]; h0(1,1) = x[4]; h0(1,2) = x[5];
235 h0(2,0) = x[6]; h0(2,1) = x[7]; h0(2,2) = x[8];
238 std::cerr <<
"Levenberg Marquardt" << std::endl
239 <<
"min: " << levmarq.get_end_error() <<
" at " << x <<
" (" << levmarq.get_end_error()*di1m*sqrt(2.) <<
" in the unit of ur, vr, wr)" << std::endl
240 <<
"iterations: " << levmarq.get_num_iterations() <<
" "
241 <<
"evaluations: " << levmarq.get_num_evaluations() << std::endl;
242 levmarq.diagnose_outcome();
246 vnl_double_3x3 hmat2 = hk2*h0*hk1;
249 std::cout <<
"3 3" << std::endl;
250 std::cout << hmat2 << std::endl;
std::vector< vgl_homg_point_2d< double > > & points_im2_
void scale1(const double s)
a_homography_function(std::vector< vgl_homg_point_2d< double > > &points_im1, std::vector< vgl_homg_point_2d< double > > &points_im2)
std::vector< vgl_homg_point_2d< double > > & points_im1_
void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
CSimpleOpt::SOption g_rgOptions[]
int main(int argc, char **argv)
void normalise_h(vnl_double_3x3 &h)