00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "FMatrixSkew.h"
00009 #include <vcl_iostream.h>
00010 #include <vcl_cmath.h>
00011 #include <vnl/vnl_matrix.h>
00012 #include <mvl/HomgLine2D.h>
00013 #include <mvl/HomgOperator2D.h>
00014 #include <mvl/HomgPoint2D.h>
00015 #include <mvl/PMatrix.h>
00016
00017
00018
00019
00020
00021 FMatrixSkew::FMatrixSkew()
00022 {
00023 rank2_flag_ = true;
00024 }
00025
00026
00027
00028
00029
00030 FMatrixSkew::FMatrixSkew(const double* f_matrix)
00031 {
00032 rank2_flag_ = true;
00033 set(f_matrix);
00034 }
00035
00036
00037
00038
00039
00040 FMatrixSkew::FMatrixSkew(const vnl_matrix<double>& f_matrix)
00041 {
00042 rank2_flag_ = true;
00043 set(f_matrix.data_block());
00044 }
00045
00046
00047
00048
00049
00050
00051 FMatrixSkew::~FMatrixSkew()
00052 {
00053 }
00054
00055
00056
00057
00058
00059
00060
00061 bool
00062 FMatrixSkew::get_epipoles(vgl_homg_point_2d<double>& epipole1,
00063 vgl_homg_point_2d<double>& epipole2) const
00064 {
00065
00066 epipole1.set( f_matrix_.get(1,2),
00067 -f_matrix_.get(0,2),
00068 f_matrix_.get(0,1));
00069 epipole2.set( f_matrix_.get(1,2),
00070 -f_matrix_.get(0,2),
00071 f_matrix_.get(0,1));
00072 return true;
00073 }
00074
00075
00076
00077
00078
00079
00080
00081 bool
00082 FMatrixSkew::get_epipoles(HomgPoint2D *epipole1_ptr, HomgPoint2D *epipole2_ptr) const
00083 {
00084
00085 epipole1_ptr->set( f_matrix_.get(1,2),
00086 -f_matrix_.get(0,2),
00087 f_matrix_.get(0,1));
00088 epipole2_ptr->set( f_matrix_.get(1,2),
00089 -f_matrix_.get(0,2),
00090 f_matrix_.get(0,1));
00091 return true;
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 void
00101 FMatrixSkew::decompose_to_skew_rank3(vnl_matrix<double> *skew_matrix_ptr,
00102 vnl_matrix<double> *rank3_matrix_ptr) const
00103 {
00104 *skew_matrix_ptr = this->get_matrix().as_ref();
00105 rank3_matrix_ptr->fill(0.0);
00106 rank3_matrix_ptr->fill_diagonal(1.0);
00107 }
00108
00109
00110
00111
00112
00113 inline void
00114 FMatrixSkew::set_rank2_using_svd (void)
00115 {
00116 }
00117
00118
00119
00120
00121
00122 inline FMatrixSkew
00123 FMatrixSkew::get_rank2_truncated()
00124 {
00125 return *this;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 void
00139 FMatrixSkew::find_nearest_perfect_match(vgl_homg_point_2d<double> const& point1,
00140 vgl_homg_point_2d<double> const& point2,
00141 vgl_homg_point_2d<double>& perfect_point1,
00142 vgl_homg_point_2d<double>& perfect_point2) const
00143 {
00144
00145 vgl_homg_point_2d<double> e1,e2;
00146 get_epipoles(e1,e2);
00147
00148
00149 double u1 = point1.x()/point1.w() - e1.x()/e1.w();
00150 double v1 = point1.y()/point1.w() - e1.y()/e1.w();
00151 double u2 = point2.x()/point2.w() - e2.x()/e2.w();
00152 double v2 = point2.y()/point2.w() - e2.y()/e2.w();
00153
00154
00155 double a_qd = (u1*v1 + u2*v2);
00156 double b_qd = u1*u1 + u2*u2 - v1*v1 - v2*v2;
00157 double c_qd = -(u1*v1 + u2*v2);
00158
00159
00160 double temp = b_qd * b_qd - 4 * a_qd * c_qd;
00161
00162 if (temp < 0)
00163 {
00164 vcl_cerr << "Error in FMatrixSkew::find_nearest_perfect_match\n"
00165 << "Imaginary solution obtained\n"
00166 << "No solution returned\n";
00167 return;
00168 }
00169
00170 double ttheta1 = (-b_qd + vcl_sqrt(temp))/(2*a_qd);
00171 double ttheta2 = (-b_qd - vcl_sqrt(temp))/(2*a_qd);
00172
00173 double theta1 = vcl_atan(ttheta1);
00174 double theta2 = vcl_atan(ttheta2);
00175
00176 double ctheta1 = vcl_cos(theta1), stheta1 = vcl_sin(theta1);
00177 double ctheta2 = vcl_cos(theta2), stheta2 = vcl_sin(theta2);
00178
00179 double dist11 = stheta1*u1 - ctheta1*v1;
00180 double dist12 = stheta1*u2 - ctheta1*v2;
00181 double dist21 = stheta2*u1 - ctheta2*v1;
00182 double dist22 = stheta2*u2 - ctheta2*v2;
00183
00184
00185 if (vcl_fabs(dist11) + vcl_fabs(dist12) > vcl_fabs(dist21) + vcl_fabs(dist22))
00186 {
00187 stheta1 = stheta2;
00188 ctheta1 = ctheta2;
00189 dist11 = dist21;
00190 dist12 = dist22;
00191 }
00192
00193
00194 perfect_point1.set(u1-dist11*stheta1+e1.x()/e1.w(),
00195 v1+dist11*ctheta1+e1.y()/e1.w(),1);
00196 perfect_point2.set(u2-dist12*stheta1+e2.x()/e2.w(),
00197 v2+dist12*ctheta1+e2.y()/e2.w(),1);
00198 }
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 void
00210 FMatrixSkew::find_nearest_perfect_match(const HomgPoint2D& point1,
00211 const HomgPoint2D& point2,
00212 HomgPoint2D *perfect_point1_ptr,
00213 HomgPoint2D *perfect_point2_ptr) const
00214 {
00215
00216 HomgPoint2D e1,e2;
00217 get_epipoles(&e1,&e2);
00218
00219
00220 double u1 = point1.x()/point1.w() - e1.x()/e1.w();
00221 double v1 = point1.y()/point1.w() - e1.y()/e1.w();
00222 double u2 = point2.x()/point2.w() - e2.x()/e2.w();
00223 double v2 = point2.y()/point2.w() - e2.y()/e2.w();
00224
00225
00226 double a_qd = (u1*v1 + u2*v2);
00227 double b_qd = u1*u1 + u2*u2 - v1*v1 - v2*v2;
00228 double c_qd = -(u1*v1 + u2*v2);
00229
00230
00231 double temp = b_qd * b_qd - 4 * a_qd * c_qd;
00232
00233 if (temp < 0)
00234 {
00235 vcl_cerr << "Error in FMatrixSkew::find_nearest_perfect_match\n"
00236 << "Imaginary solution obtained\n"
00237 << "No solution returned\n";
00238 return;
00239 }
00240
00241 double ttheta1 = (-b_qd + vcl_sqrt(temp))/(2*a_qd);
00242 double ttheta2 = (-b_qd - vcl_sqrt(temp))/(2*a_qd);
00243
00244 double theta1 = vcl_atan(ttheta1);
00245 double theta2 = vcl_atan(ttheta2);
00246
00247 double ctheta1 = vcl_cos(theta1), stheta1 = vcl_sin(theta1);
00248 double ctheta2 = vcl_cos(theta2), stheta2 = vcl_sin(theta2);
00249
00250 double dist11 = stheta1*u1 - ctheta1*v1;
00251 double dist12 = stheta1*u2 - ctheta1*v2;
00252 double dist21 = stheta2*u1 - ctheta2*v1;
00253 double dist22 = stheta2*u2 - ctheta2*v2;
00254
00255
00256 if (vcl_fabs(dist11) + vcl_fabs(dist12) > vcl_fabs(dist21) + vcl_fabs(dist22))
00257 {
00258 stheta1 = stheta2;
00259 ctheta1 = ctheta2;
00260 dist11 = dist21;
00261 dist12 = dist22;
00262 }
00263
00264
00265 perfect_point1_ptr->set(u1-dist11*stheta1+e1.x()/e1.w(),
00266 v1+dist11*ctheta1+e1.y()/e1.w(),1);
00267 perfect_point2_ptr->set(u2-dist12*stheta1+e2.x()/e2.w(),
00268 v2+dist12*ctheta1+e2.y()/e2.w(),1);
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 bool FMatrixSkew::set (const double* f_matrix )
00281 {
00282 int row_index, col_index;
00283
00284
00285 const double tolerance=0.0;
00286
00287
00288
00289 if ((f_matrix[1] + f_matrix[3] > tolerance) |
00290 (f_matrix[2] + f_matrix[6] > tolerance) |
00291 (f_matrix[5] + f_matrix[7] > tolerance) |
00292 (f_matrix[0] > tolerance) |
00293 (f_matrix[4] > tolerance) |
00294 (f_matrix[8] > tolerance) )
00295 {
00296 vcl_cerr << "WARNING: F matrix not skew symmetric so cannot allocate to FMatrixSkew\n" ;
00297 return false;
00298 }
00299
00300 for (row_index = 0; row_index < 3; row_index++)
00301 for (col_index = 0; col_index < 3; col_index++)
00302 {
00303 double v = *f_matrix++;
00304 f_matrix_. put (row_index, col_index,v);
00305 ft_matrix_. put (col_index, row_index,v);
00306 }
00307
00308
00309
00310 FMatrix::set_rank2_flag(true);
00311
00312 return true;
00313 }
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 inline bool
00325 FMatrixSkew::set (const vnl_matrix<double>& f_matrix )
00326 {
00327 return set(f_matrix.data_block());
00328 }
00329
00330
00331
00332
00333
00334
00335 inline bool
00336 FMatrixSkew::get_rank2_flag (void) const
00337 {
00338 return true;
00339 }
00340
00341
00342
00343
00344
00345 inline void
00346 FMatrixSkew::set_rank2_flag (bool)
00347 {
00348 FMatrix::set_rank2_flag(true);
00349 }