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