00001
00002 #include "imesh_pca.h"
00003
00004
00005
00006 #include <imesh/imesh_fileio.h>
00007 #include <vnl/vnl_vector.h>
00008 #include <vnl/algo/vnl_svd.h>
00009 #include <vcl_fstream.h>
00010 #include <vcl_sstream.h>
00011 #include <vcl_cassert.h>
00012
00013 imesh_pca_mesh::imesh_pca_mesh(const vcl_vector<imesh_mesh>& meshes)
00014 : imesh_mesh(meshes[0]), mean_verts_(this->vertices().clone())
00015 {
00016 vnl_matrix<double> M = compute_mean(meshes);
00017 vnl_svd<double> A(M,-1e-8);
00018
00019
00020
00021 std_devs_ = vnl_vector<double>(A.W().diagonal().data_block(), A.rank());
00022 pc_.set_size(A.rank(),M.rows());
00023 A.U().transpose().extract(pc_);
00024
00025 params_.set_size(std_devs_.size());
00026 params_.fill(0.0);
00027 }
00028
00029
00030
00031 vnl_matrix<double>
00032 imesh_pca_mesh::compute_mean(const vcl_vector<imesh_mesh>& meshes)
00033 {
00034 const unsigned num_training = meshes.size();
00035 vnl_matrix<double> M(this->num_verts()*3,num_training);
00036 vnl_vector<double> mean(this->num_verts()*3,0.0);
00037
00038 for (unsigned int i=0; i<num_training; ++i)
00039 {
00040 assert(meshes[i].num_verts() == this->num_verts());
00041 const imesh_vertex_array<3>& verts = meshes[i].vertices<3>();
00042 for (unsigned v=0; v<verts.size(); ++v) {
00043 M(3*v,i) = verts[v][0];
00044 M(3*v+1,i) = verts[v][1];
00045 M(3*v+2,i) = verts[v][2];
00046 mean[3*v] += verts[v][0];
00047 mean[3*v+1] += verts[v][1];
00048 mean[3*v+2] += verts[v][2];
00049 }
00050 }
00051
00052 mean /= num_training;
00053
00054 for (unsigned int i=0; i<num_training; ++i)
00055 {
00056 M.set_column(i,M.get_column(i) - mean);
00057 imesh_vertex_array<3>& verts = this->vertices<3>();
00058 imesh_vertex_array<3>& mverts = this->mean_vertices<3>();
00059 for (unsigned v=0; v<verts.size(); ++v) {
00060 verts[v][0] = mverts[v][0] = mean[3*v];
00061 verts[v][1] = mverts[v][1] = mean[3*v+1];
00062 verts[v][2] = mverts[v][2] = mean[3*v+2];
00063 }
00064 }
00065
00066 return M;
00067 }
00068
00069
00070
00071 imesh_pca_mesh::imesh_pca_mesh(const imesh_mesh& mesh,
00072 const vnl_vector<double>& mean,
00073 const vnl_vector<double>& std_devs,
00074 const vnl_matrix<double>& pc)
00075 : imesh_mesh(mesh)
00076 {
00077 init(mean,std_devs,pc);
00078 }
00079
00080
00081
00082 imesh_pca_mesh::imesh_pca_mesh(const imesh_pca_mesh& other)
00083 : imesh_mesh(other),
00084 std_devs_(other.std_devs_),
00085 pc_(other.pc_),
00086 mean_verts_((other.mean_verts_.get()) ? other.mean_verts_->clone() : 0),
00087 params_(other.params_)
00088 {
00089 }
00090
00091
00092
00093 imesh_pca_mesh& imesh_pca_mesh::operator=(const imesh_pca_mesh& other)
00094 {
00095 if (this != &other) {
00096 this->imesh_mesh::operator=(other);
00097 std_devs_ = other.std_devs_;
00098 pc_ = other.pc_;
00099 mean_verts_ = vcl_auto_ptr<imesh_vertex_array_base>((other.mean_verts_.get()) ?
00100 other.mean_verts_->clone() : 0);
00101 params_ = other.params_;
00102 }
00103 return *this;
00104 }
00105
00106
00107
00108 imesh_pca_mesh::imesh_pca_mesh(const imesh_mesh& mesh)
00109 : imesh_mesh(mesh), mean_verts_(this->vertices().clone())
00110 {
00111 }
00112
00113
00114
00115
00116 void imesh_pca_mesh::init(const vnl_vector<double>& mean,
00117 const vnl_vector<double>& std_devs,
00118 const vnl_matrix<double>& pc)
00119 {
00120 std_devs_ = std_devs;
00121 pc_ = pc;
00122 mean_verts_.reset(new imesh_vertex_array<3>(this->num_verts()));
00123
00124 assert(this->num_verts()*3 == mean.size());
00125 assert(this->num_verts()*3 == pc.columns());
00126 assert(std_devs.size() == pc.rows());
00127
00128 imesh_vertex_array<3>& mverts = this->mean_vertices<3>();
00129 for (unsigned int i=0; i<mverts.size(); ++i)
00130 {
00131 mverts[i] = imesh_vertex<3>(mean[3*i],mean[3*i+1],mean[3*i+2]);
00132 }
00133 params_ = this->project(this->vertices());
00134 }
00135
00136
00137
00138 void imesh_pca_mesh::set_params(const vnl_vector<double>& p)
00139 {
00140 assert(params_.size() >= p.size());
00141 vnl_vector<double> sp(p.size(),0.0);
00142 unsigned int i=0;
00143 for (; i<p.size(); ++i){
00144 params_[i] = p[i];
00145 sp[i] = std_devs_[i]*p[i];
00146 }
00147
00148 for (; i<params_.size(); ++i)
00149 params_[i] = 0.0;
00150
00151 imesh_vertex_array<3>& verts = this->vertices<3>();
00152 const imesh_vertex_array<3>& mverts = this->mean_vertices<3>();
00153 for (unsigned i=0; i<verts.size(); ++i) {
00154 imesh_vertex<3>& v = verts[i];
00155 const imesh_vertex<3>& mv = mverts[i];
00156 v = mv;
00157 for (unsigned j=0; j<sp.size(); ++j) {
00158 v[0] += pc_(j,3*i) *sp[j];
00159 v[1] += pc_(j,3*i+1)*sp[j];
00160 v[2] += pc_(j,3*i+2)*sp[j];
00161 }
00162 }
00163 }
00164
00165
00166
00167
00168 void imesh_pca_mesh::set_param(unsigned int idx, double param)
00169 {
00170 double diff = std_devs_[idx]*(param - params_[idx]);
00171 params_[idx] = param;
00172
00173 imesh_vertex_array<3>& verts = this->vertices<3>();
00174 for (unsigned i=0; i<verts.size(); ++i) {
00175 imesh_vertex<3>& v = verts[i];
00176 v[0] += pc_(idx,3*i) *diff;
00177 v[1] += pc_(idx,3*i+1)*diff;
00178 v[2] += pc_(idx,3*i+2)*diff;
00179 }
00180 }
00181
00182
00183
00184
00185 void imesh_pca_mesh::set_mean()
00186 {
00187 params_.fill(0.0);
00188
00189 imesh_vertex_array<3>& verts = this->vertices<3>();
00190 const imesh_vertex_array<3>& mverts = this->mean_vertices<3>();
00191 for (unsigned v=0; v<verts.size(); ++v) {
00192 verts[v] = mverts[v];
00193 }
00194 }
00195
00196
00197
00198 vnl_vector<double>
00199 imesh_pca_mesh::project(const imesh_vertex_array_base& vertices) const
00200 {
00201 assert(dynamic_cast<const imesh_vertex_array<3>*>(&vertices));
00202 const imesh_vertex_array<3>& verts =
00203 static_cast<const imesh_vertex_array<3>&>(vertices);
00204
00205 const imesh_vertex_array<3>& mverts = this->mean_vertices<3>();
00206
00207 const unsigned int num_verts = this->num_verts();
00208 vnl_vector<double> vals(3*num_verts);
00209 for (unsigned int i=0; i<num_verts; ++i)
00210 {
00211 const imesh_vertex<3>& mv = mverts[i];
00212 const imesh_vertex<3>& v = verts[i];
00213 vals[3*i] = v[0] - mv[0];
00214 vals[3*i+1] = v[1] - mv[1];
00215 vals[3*i+2] = v[2] - mv[2];
00216 }
00217
00218 vnl_vector<double> p = pc_*vals;
00219 for (unsigned int i=0; i<p.size(); ++i)
00220 p[i] /= std_devs_[i];
00221 return p;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232 vcl_vector<vnl_matrix<double> >
00233 imesh_pca_image_jacobians(const vpgl_proj_camera<double>& camera,
00234 const imesh_pca_mesh& mesh)
00235 {
00236
00237 const imesh_vertex_array<3>& verts = mesh.vertices<3>();
00238 const unsigned int num_verts = mesh.num_verts();
00239 vcl_vector<vgl_point_3d<double> > pts(num_verts);
00240 for (unsigned int i=0; i<num_verts; ++i)
00241 pts[i] = verts[i];
00242
00243
00244 vcl_vector<vnl_matrix_fixed<double,2,3> > J = image_jacobians(camera,pts);
00245
00246
00247 const vnl_matrix<double>& pc = mesh.principal_comps();
00248 const vnl_vector<double>& std = mesh.std_devs();
00249
00250 vcl_vector<vnl_matrix<double> > img_jac(num_verts);
00251 for (unsigned int i=0; i<num_verts; ++i)
00252 {
00253 vnl_matrix<double> dir_3d(pc.rows(),3);
00254 pc.extract(dir_3d,0,3*i);
00255 for (unsigned int j=0; j<std.size(); ++j) {
00256 dir_3d(j,0) /= std[j];
00257 dir_3d(j,1) /= std[j];
00258 dir_3d(j,2) /= std[j];
00259 }
00260
00261 img_jac[i] = J[i]*dir_3d.transpose();
00262 }
00263
00264 return img_jac;
00265 }
00266
00267
00268
00269 imesh_pca_mesh imesh_read_pca(const vcl_string& mean_file,
00270 const vcl_string& pca_file)
00271 {
00272 imesh_mesh mean;
00273 vnl_vector<double> m,s;
00274 vnl_matrix<double> P;
00275 imesh_read(mean_file,mean);
00276 imesh_read_pca(pca_file,m,s,P);
00277 return imesh_pca_mesh(mean,m,s,P);
00278 }
00279
00280
00281
00282 bool imesh_read_pca(const vcl_string& pca_file,
00283 vnl_vector<double>& mean,
00284 vnl_vector<double>& std_devs,
00285 vnl_matrix<double>& pc)
00286 {
00287 vcl_ifstream ifs(pca_file.c_str());
00288 if (!ifs.is_open())
00289 return false;
00290
00291 vcl_vector<double> data;
00292 if (ifs.peek() == '#') {
00293 vcl_string s;
00294 ifs >> s;
00295 if (s == "#mag") {
00296 vcl_string line;
00297 vcl_getline(ifs,line);
00298 vcl_stringstream ss(line);
00299 double val;
00300 while (ss >> val) {
00301 data.push_back(val);
00302 }
00303 std_devs.set_size(data.size());
00304 for (unsigned i=0; i<std_devs.size(); ++i)
00305 std_devs[i] = data[i];
00306 }
00307 }
00308 vcl_string line;
00309 data.clear();
00310 vcl_vector<vcl_vector<double> > data_M;
00311 while (vcl_getline(ifs,line).good()) {
00312 vcl_stringstream ss(line);
00313 double val;
00314 ss >> val;
00315 data.push_back(val);
00316 vcl_vector<double> row;
00317 while (ss >> val) {
00318 row.push_back(val);
00319 }
00320 data_M.push_back(row);
00321 }
00322 mean.set_size(data.size());
00323 pc.set_size(data_M[0].size(),mean.size());
00324 for (unsigned i=0; i<mean.size(); ++i) {
00325 mean[i] = data[i];
00326 for (unsigned j=0; j<pc.rows(); ++j) {
00327 pc(j,i) = data_M[i][j];
00328 }
00329 }
00330
00331 return true;
00332 }
00333
00334
00335
00336 void imesh_write_pca(const vcl_string& mesh_file,
00337 const vcl_string& pca_file,
00338 const imesh_pca_mesh& pmesh)
00339 {
00340 const vnl_vector<double>& std_dev = pmesh.std_devs();
00341 const vnl_matrix<double>& pc = pmesh.principal_comps();
00342 const imesh_vertex_array<3>& mverts = pmesh.mean_vertices<3>();
00343 const unsigned int num_data = pc.columns();
00344 vnl_vector<double> mean(num_data);
00345 for (unsigned int i=0; i<num_data; ++i)
00346 mean[i] = mverts[i/3][i%3];
00347
00348 vcl_auto_ptr<imesh_vertex_array_base> verts(mverts.clone());
00349 vcl_auto_ptr<imesh_face_array_base> faces(pmesh.faces().clone());
00350 imesh_mesh mean_mesh(verts,faces);
00351
00352 imesh_write_pca(pca_file,mean,std_dev,pc);
00353 imesh_write_obj(mesh_file,mean_mesh);
00354 }
00355
00356
00357
00358 bool imesh_write_pca(const vcl_string& filename,
00359 const vnl_vector<double>& mean,
00360 const vnl_vector<double>& svals,
00361 const vnl_matrix<double>& vars)
00362 {
00363 const unsigned int num_comps = svals.size();
00364 const unsigned int num_data = mean.size();
00365 vcl_ofstream ofs(filename.c_str());
00366 ofs << "#mag";
00367 for (unsigned int i=0; i<num_comps; ++i)
00368 ofs << ' ' << svals[i];
00369 ofs << '\n';
00370 for (unsigned int j=0; j<num_data; ++j) {
00371 ofs << mean[j];
00372 for (unsigned int i=0; i<num_comps; ++i)
00373 ofs << ' ' << vars(i,j);
00374 ofs << '\n';
00375 }
00376
00377 ofs.close();
00378 return true;
00379 }