00001
00002 #include "vgl_h_matrix_2d_optimize_lmq.h"
00003
00004
00005
00006 #include <vcl_iostream.h>
00007 #include <vcl_cmath.h>
00008 #include <vcl_cassert.h>
00009 #include <vnl/vnl_inverse.h>
00010 #include <vnl/algo/vnl_levenberg_marquardt.h>
00011 #include <vgl/algo/vgl_norm_trans_2d.h>
00012
00013
00014 vgl_h_matrix_2d_optimize_lmq::
00015 vgl_h_matrix_2d_optimize_lmq(vgl_h_matrix_2d<double> const& initial_h)
00016 : vgl_h_matrix_2d_optimize(initial_h)
00017 {
00018 }
00019
00020
00021 bool vgl_h_matrix_2d_optimize_lmq::
00022 optimize_h(vcl_vector<vgl_homg_point_2d<double> > const& points1,
00023 vcl_vector<vgl_homg_point_2d<double> > const& points2,
00024 vgl_h_matrix_2d<double> const& h_initial,
00025 vgl_h_matrix_2d<double>& h_optimized)
00026 {
00027 projection_lsqf lsq(points1, points2);
00028 vnl_vector<double> hv(9);
00029 vnl_matrix_fixed<double,3,3> m = h_initial.get_matrix();
00030 unsigned i = 0;
00031 for (unsigned r=0; r<3; ++r)
00032 for (unsigned c=0; c<3; ++c, ++i)
00033 hv[i] = m[r][c];
00034 vnl_levenberg_marquardt lm(lsq);
00035 lm.set_verbose(verbose_);
00036 lm.set_trace(trace_);
00037 lm.set_x_tolerance(htol_);
00038 lm.set_f_tolerance(ftol_);
00039 lm.set_g_tolerance(gtol_);
00040 bool success = lm.minimize(hv);
00041 if (verbose_)
00042 {
00043 lm.diagnose_outcome(vcl_cout);
00044 }
00045
00046 if (success)
00047 h_optimized.set(hv.data_block());
00048 else
00049 h_optimized = h_initial;
00050 return success;
00051 }
00052
00053 bool vgl_h_matrix_2d_optimize_lmq::
00054 optimize_p(vcl_vector<vgl_homg_point_2d<double> > const& points1,
00055 vcl_vector<vgl_homg_point_2d<double> > const& points2,
00056 vgl_h_matrix_2d<double>& H)
00057 {
00058
00059 assert(points1.size() == points2.size());
00060 int n = points1.size();
00061 assert(n>4);
00062
00063
00064 vgl_norm_trans_2d<double> tr1, tr2;
00065 if (!tr1.compute_from_points(points1))
00066 return false;
00067 if (!tr2.compute_from_points(points2))
00068 return false;
00069
00070 vcl_vector<vgl_homg_point_2d<double> > tpoints1, tpoints2;
00071 for (int i=0; i<n; ++i)
00072 {
00073 tpoints1.push_back(tr1(points1[i]));
00074 tpoints2.push_back(tr2(points2[i]));
00075 }
00076
00077
00078
00079
00080
00081
00082
00083 vgl_h_matrix_2d<double> tr1_inv = tr1.get_inverse();
00084 vgl_h_matrix_2d<double> initial_h_norm = tr2*initial_h_*tr1_inv;
00085
00086
00087 vgl_h_matrix_2d<double> hopt;
00088 if (!optimize_h(tpoints1, tpoints2, initial_h_norm, hopt))
00089 return false;
00090
00091
00092
00093
00094
00095
00096
00097
00098 vgl_h_matrix_2d<double> tr2_inv = tr2.get_inverse();
00099 H = tr2_inv*hopt*tr1;
00100 return true;
00101 }
00102
00103 bool vgl_h_matrix_2d_optimize_lmq::
00104 optimize_l(vcl_vector<vgl_homg_line_2d<double> > const& lines1,
00105 vcl_vector<vgl_homg_line_2d<double> > const& lines2,
00106 vgl_h_matrix_2d<double>& H)
00107 {
00108
00109 assert(lines1.size() == lines2.size());
00110 assert(lines1.size() > 4);
00111
00112
00113
00114 vgl_norm_trans_2d<double> tr1, tr2;
00115 if (!tr1.compute_from_lines(lines1))
00116 return false;
00117 if (!tr2.compute_from_lines(lines2))
00118 return false;
00119 vcl_vector<vgl_homg_point_2d<double> > tlines1, tlines2;
00120 for (vcl_vector<vgl_homg_line_2d<double> >::const_iterator
00121 lit = lines1.begin(); lit != lines1.end(); lit++)
00122 {
00123
00124 vgl_homg_line_2d<double> l = tr1(*lit);
00125
00126 vgl_homg_point_2d<double> p(l.a(), l.b(), l.c());
00127 tlines1.push_back(p);
00128 }
00129 for (vcl_vector<vgl_homg_line_2d<double> >::const_iterator
00130 lit = lines2.begin(); lit != lines2.end(); lit++)
00131 {
00132
00133 vgl_homg_line_2d<double> l = tr2(*lit);
00134
00135 vgl_homg_point_2d<double> p(l.a(), l.b(), l.c());
00136 tlines2.push_back(p);
00137 }
00138
00139
00140
00141
00142
00143
00144 vgl_h_matrix_2d<double> h_initial_line, h_line_opt, initial_h_norm;
00145 vgl_h_matrix_2d<double> tr1_inv = tr1.get_inverse();
00146 initial_h_norm = tr2*initial_h_*tr1_inv;
00147
00148 vnl_matrix_fixed<double, 3, 3> const & Mp_init =
00149 initial_h_norm.get_matrix();
00150 vnl_matrix_fixed<double, 3, 3> Ml_init = vnl_inverse_transpose(Mp_init);
00151 h_initial_line.set(Ml_init);
00152
00153
00154 if (!this->optimize_h(tlines1, tlines2, h_initial_line, h_line_opt))
00155 return false;
00156
00157
00158 vgl_h_matrix_2d<double> h_point_opt;
00159 vnl_matrix_fixed<double, 3, 3> const & Ml_opt = h_line_opt.get_matrix();
00160 vnl_matrix_fixed<double, 3, 3> Mp_opt = vnl_inverse_transpose(Ml_opt);
00161 h_point_opt.set(Mp_opt);
00162
00163
00164
00165
00166
00167
00168
00169
00170 vgl_h_matrix_2d<double> tr2inv = tr2.get_inverse();
00171 H = tr2inv*h_point_opt*tr1;
00172 return true;
00173 }
00174
00175 bool vgl_h_matrix_2d_optimize_lmq::
00176 optimize_pl(vcl_vector<vgl_homg_point_2d<double> > const& points1,
00177 vcl_vector<vgl_homg_point_2d<double> > const& points2,
00178 vcl_vector<vgl_homg_line_2d<double> > const& lines1,
00179 vcl_vector<vgl_homg_line_2d<double> > const& lines2,
00180 vgl_h_matrix_2d<double>& H)
00181 {
00182
00183 assert(points1.size() == points2.size());
00184 int np = points1.size();
00185
00186 assert(lines1.size() == lines2.size());
00187 int nl = lines1.size();
00188
00189 assert((np+nl)>4);
00190
00191 vgl_norm_trans_2d<double> tr1, tr2;
00192 if (!tr1.compute_from_points_and_lines(points1,lines1))
00193 return false;
00194 if (!tr2.compute_from_points_and_lines(points2,lines2))
00195 return false;
00196 vcl_vector<vgl_homg_point_2d<double> > tpoints1, tpoints2;
00197 for (int i=0; i<np; ++i)
00198 {
00199 tpoints1.push_back(tr1(points1[i]));
00200 tpoints2.push_back(tr2(points2[i]));
00201 }
00202 for (int i=0; i<nl; ++i)
00203 {
00204 double a=lines1[i].a(), b=lines1[i].b(), c=lines1[i].c(), d=vcl_sqrt(a*a+b*b);
00205 tpoints1.push_back(tr1(vgl_homg_point_2d<double>(-a*c,-b*c,d)));
00206 a=lines2[i].a(), b=lines2[i].b(), c=lines2[i].c(), d = vcl_sqrt(a*a+b*b);
00207 tpoints2.push_back(tr2(vgl_homg_point_2d<double>(-a*c,-b*c,d)));
00208 }
00209
00210 vgl_h_matrix_2d<double> tr1_inv = tr1.get_inverse();
00211 vgl_h_matrix_2d<double> initial_h_norm = tr2*initial_h_*tr1_inv;
00212
00213
00214 vgl_h_matrix_2d<double> hopt;
00215 if (!optimize_h(tpoints1, tpoints2, initial_h_norm, hopt))
00216 return false;
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 vgl_h_matrix_2d<double> tr2_inv = tr2.get_inverse();
00227 H = tr2_inv*hopt*tr1;
00228 return true;
00229 }