00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "FMatrixPlanar.h"
00009
00010 #include <vcl_cassert.h>
00011 #include <vcl_iostream.h>
00012 #include <vcl_cmath.h>
00013 #include <vnl/vnl_matrix.h>
00014 #include <vnl/vnl_double_3.h>
00015
00016 #include <vnl/algo/vnl_svd.h>
00017 #include <vnl/vnl_math.h>
00018 #include <vnl/algo/vnl_symmetric_eigensystem.h>
00019
00020 #include <mvl/FMatrix.h>
00021
00022
00023
00024
00025
00026 FMatrixPlanar::FMatrixPlanar()
00027 {
00028 rank2_flag_ = true;
00029 }
00030
00031
00032
00033
00034
00035 FMatrixPlanar::FMatrixPlanar(const double* f_matrix)
00036 {
00037 rank2_flag_ = true;
00038 set(f_matrix);
00039 }
00040
00041
00042
00043
00044
00045 FMatrixPlanar::FMatrixPlanar(const vnl_matrix<double>& f_matrix)
00046 {
00047 rank2_flag_ = true;
00048 set(f_matrix.data_block());
00049 }
00050
00051
00052
00053
00054
00055
00056 FMatrixPlanar::~FMatrixPlanar()
00057 {
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067 bool FMatrixPlanar::set (const double* f_matrix )
00068 {
00069 vnl_matrix<double> temp(f_matrix,3,3);
00070 return set(temp);
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 bool
00083 FMatrixPlanar::set (const vnl_matrix<double>& f_matrix )
00084 {
00085 int row_index, col_index;
00086
00087 #ifdef PARANOID
00088
00089
00090
00091
00092 bool planar = true;
00093 vnl_svd<double> svd(f_matrix,1e-8);
00094 if (svd.rank()!=2)
00095 {
00096 planar = false;
00097 vcl_cerr << "WARNING in FMatrixPlanar::set\n"
00098 << "F matrix not rank 2: svd = " << svd.W() << vcl_endl;
00099 }
00100 else
00101 {
00102 vnl_svd<double> svd(f_matrix + f_matrix.transpose(),1e-8);
00103 if (svd.rank()!=2)
00104 {
00105 planar = false;
00106 vcl_cerr << "WARNING in FMatrixPlanar::set\n"
00107 << "Symmetric part matrix not rank 2: svd = " << svd.W() << '\n';
00108 }
00109 }
00110
00111 if (!planar)
00112 {
00113 vcl_cerr << "WARNING: F matrix not planar so cannot allocate to FMatrixPlanar\n" ;
00114 return FALSE;
00115 }
00116
00117 #endif
00118
00119 for (row_index = 0; row_index < 3; row_index++)
00120 for (col_index = 0; col_index < 3; col_index++)
00121 {
00122 f_matrix_. put (row_index, col_index,f_matrix.get(row_index,col_index));
00123 ft_matrix_. put (col_index, row_index,f_matrix.get(row_index,col_index));
00124 }
00125
00126
00127
00128 this->set_rank2_flag(true);
00129
00130 return true;
00131 }
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 void FMatrixPlanar::init(const FMatrix& F)
00146 {
00147
00148
00149
00150
00151
00152
00153 vgl_homg_point_2d<double> e1,e2;
00154 F.get_epipoles(e1,e2);
00155
00156 vnl_symmetric_eigensystem<double> symm_eig(F.get_matrix()+F.get_matrix().transpose());
00157
00158 double eig0 = symm_eig.D(0,0);
00159 double eig1 = symm_eig.D(2,2);
00160
00161 vnl_double_3 v0 = symm_eig.get_eigenvector(0);
00162 vnl_double_3 v1 = symm_eig.get_eigenvector(2);
00163
00164 vnl_double_3 f1, f2;
00165
00166 if (eig0 > 0 && eig1 < 0) {
00167 f1 = vcl_sqrt(eig0)*v0 + vcl_sqrt(-eig1)*v1;
00168 f2 = vcl_sqrt(eig0)*v0 - vcl_sqrt(-eig1)*v1;
00169 }
00170 else if (eig0 < 0 && eig1 > 0) {
00171 f1 = vcl_sqrt(eig1)*v1 + vcl_sqrt(-eig0)*v0;
00172 f2 = vcl_sqrt(eig1)*v1 - vcl_sqrt(-eig0)*v0;
00173 }
00174 else {
00175 vcl_cerr << "ERROR in FMatrix::init\n"
00176 << "EXITING...\n";
00177 assert(false);
00178 }
00179
00180 #define dot_n(a,b) (a.x()*b(0)/a.w()+a.y()*b(1)/a.w()+b(2))
00181 vnl_double_3 ls;
00182 if (vcl_fabs(dot_n(e1,f1))+
00183 vcl_fabs(dot_n(e2,f1)) >
00184 vcl_fabs(dot_n(e1,f2))+
00185 vcl_fabs(dot_n(e2,f2)) )
00186 ls = f1;
00187 else
00188 ls = f2;
00189 #undef dot_n
00190
00191 ls.normalize();
00192
00193 double ls_thi = vcl_acos(ls[2]);
00194 if (ls_thi < 0) ls_thi += vnl_math::pi;
00195
00196 double ls_theta;
00197 if (ls[1] >= 0)
00198 ls_theta = vcl_acos(ls[0]/vcl_sin(ls_thi));
00199 else
00200 ls_theta = -vcl_acos(ls[0]/vcl_sin(ls_thi));
00201
00202 double ls1 = vcl_cos(ls_theta)*vcl_sin(ls_thi);
00203 double ls2 = vcl_sin(ls_theta)*vcl_sin(ls_thi);
00204 double ls3 = vcl_cos(ls_thi);
00205
00206 double list1[9] = {0,-1.0,e1.y()/e1.w(),
00207 1,0,-e1.x()/e1.w(),
00208 -e1.y()/e1.w(),e1.x()/e1.w(),0};
00209 double list2[9] = {0,-ls3,ls2,ls3,0,-ls1,-ls2,ls1,0};
00210 double list3[9] = {0,-1.0,e2.y()/e2.w(),
00211 1,0,-e2.x()/e2.w(),
00212 -e2.y()/e2.w(),e2.x()/e2.w(),0};
00213
00214 vnl_matrix<double> mat1(3,3,9,list1),mat2(3,3,9,list2),mat3(3,3,9,list3);
00215
00216 vnl_matrix<double> fmat = mat1*mat2*mat3;
00217
00218 fmat /= fmat.fro_norm();
00219
00220
00221 set(fmat);
00222 }