changeReferenceSystem.cpp
Go to the documentation of this file.
00001 
00034 #include <iostream>
00035 #include <fstream>
00036 #include <opencv/cv.h>
00037 #include <opencv/highgui.h>
00038 #include <string>
00039 #include <vector>
00040 
00041 #include "Mask.h"
00042 
00043 #include "DUtils.h"
00044 #include "DUtilsCV.h"
00045 #include "DVision.h"
00046 
00047 typedef DVision::PixelPointFile::PixelPoint PixelPoint;
00048 typedef DVision::PMVS::PatchFile PatchFile;
00049 typedef DVision::PMVS::PatchFile::Patch Patch;
00050 typedef DVision::PMVS::CameraFile CameraFile;
00051 typedef DVision::PMVS::CameraFile::Camera Camera;
00052 typedef DVision::PMVS::PLYFile PLYFile;
00053 typedef DVision::PMVS::PLYFile::PLYPoint PLYPoint;
00054 
00055 using namespace std;
00056 using namespace DUtils;
00057 
00058 // ----------------------------------------------------------------------------
00059 
00066 cv::Mat calculateTransformation(const vector<PLYPoint> &plypoints);
00067 
00074 void transformPoints(vector<PLYPoint> &plypoints, 
00075   vector<Patch> &sparse_points, const cv::Mat &oTw);
00076 
00085 void transformPoint(double &x, double &y, double &z, double s, const cv::Mat &oTw);
00086 
00093 void transformCameras(vector<Camera> &cameras, const cv::Mat &oTw);
00094 
00095 // ----------------------------------------------------------------------------
00096 
00097 void test(const Camera &camera, const PLYPoint &p)
00098 {
00099   cv::Mat X = (cv::Mat_<double>(4,1) << p.x, p.y, p.z, 1.);
00100   cv::Mat x = camera.P * X;
00101   x.at<double>(0,0) /= x.at<double>(2,0);
00102   x.at<double>(1,0) /= x.at<double>(2,0);
00103 
00104   cout << "(" << p.x << " " << p.y << " " << p.z << ") --> ";
00105   cout << x.at<double>(0,0) << ", " << x.at<double>(1,0) << endl;
00106 }
00107 
00108 // ----------------------------------------------------------------------------
00109 
00110 int main(int argc, char *argv[])
00111 {
00112   if(argc < 7)
00113   {
00114     cout << "Usage: " << argv[0] << " <camera file> <ply file> <patch file>"
00115       " <camera out dir> <out ply file> <out patch file>" << endl;
00116       return 1;
00117   }
00118   
00119   string camera_file = argv[1];
00120   string ply_file = argv[2];
00121   string patch_file = argv[3];
00122   string camera_out_dir = argv[4];
00123   string ply_out_file = argv[5];
00124   string patch_out_file = argv[6];
00125 
00126   try 
00127   {
00128 
00129     cout << "Reading data..." << endl;
00130 
00131     vector<PLYPoint> plypoints;
00132     PLYFile::readFile(ply_file, plypoints);
00133     
00134     cout << "-- " << plypoints.size() << " PLY points read" << endl;
00135     
00136     vector<Patch> patches;
00137     PatchFile::readFile(patch_file, patches);
00138     
00139     cout << "-- " << patches.size() << " patches read" << endl;
00140     
00141     vector<Camera> cameras;
00142     CameraFile::readFile(camera_file, cameras);
00143     
00144     cout << "-- " << cameras.size() << " cameras read" << endl;
00145 
00146     cout << "Changing reference system..." << endl;
00147 
00148   #if 0
00149       test(cameras[0], plypoints[10]);
00150       test(cameras[0], plypoints[20]);
00151       test(cameras[0], plypoints[30]);
00152   #endif
00153     
00154     cv::Mat oTw = calculateTransformation(plypoints); 
00155     cout << "." << flush;
00156     transformPoints(plypoints, patches, oTw);
00157     cout << "." << flush;
00158     transformCameras(cameras, oTw);
00159     cout << "." << endl;
00160     
00161   #if 0
00162       test(cameras[0], plypoints[10]);
00163       test(cameras[0], plypoints[20]);
00164       test(cameras[0], plypoints[30]);
00165   #endif
00166     
00167     cout << "Saving..." << endl;
00168     PLYFile::saveFile(ply_out_file, plypoints);
00169     PatchFile::saveFile(patch_out_file, patches);
00170     CameraFile::saveFile(camera_out_dir, cameras);
00171   
00172   }catch(std::string ex)
00173   {
00174     std::cout << ex << std::endl;
00175     return 1;
00176   }
00177   
00178   return 0;
00179 }
00180 
00181 // ----------------------------------------------------------------------------
00182 
00183 cv::Mat calculateTransformation(const vector<PLYPoint> &plypoints)
00184 {
00185   // the object reference will be the centroid of the point cloud.
00186   // the new axes will be oriented according to the principal axis of the cloud
00187   if(plypoints.empty()) return cv::Mat::eye(4, 4, CV_64F);
00188   
00189   cv::Mat samples(plypoints.size(), 3, CV_64FC1);
00190   
00191   cv::Mat centroid(1, 3, CV_64FC1);
00192   centroid = 0.0;  
00193   
00194   /*
00195   double minx, maxx, miny, maxy, minz, maxz;
00196   minx = maxx = plypoints[0].x;
00197   miny = maxy = plypoints[0].y;
00198   minz = maxz = plypoints[0].z;
00199   */
00200   
00201   for(unsigned int i = 0; i < plypoints.size(); ++i)
00202   {
00203     samples.at<double>(i, 0) = plypoints[i].x;
00204     samples.at<double>(i, 1) = plypoints[i].y;
00205     samples.at<double>(i, 2) = plypoints[i].z;
00206     
00207     /*
00208     if(plypoints[i].x < minx) minx = plypoints[i].x;
00209     else if(plypoints[i].x > maxx) maxx = plypoints[i].x;
00210     
00211     if(plypoints[i].y < miny) miny = plypoints[i].y;
00212     else if(plypoints[i].y > maxy) maxy = plypoints[i].y;
00213     
00214     if(plypoints[i].z < minz) minz = plypoints[i].z;
00215     else if(plypoints[i].z > maxz) maxz = plypoints[i].z;
00216     */
00217     
00218     centroid += samples.rowRange(i,i+1);
00219   }
00220   centroid /= plypoints.size();
00221 
00222   /*
00223   centroid.ptr<double>()[0] = (maxx + minx)/2.0;
00224   centroid.ptr<double>()[1] = (maxy + miny)/2.0;
00225   centroid.ptr<double>()[2] = (maxz + minz)/2.0;
00226   */
00227   
00228   cv::Mat cov, mean;
00229   cv::calcCovarMatrix(samples, cov, mean, CV_COVAR_NORMAL | CV_COVAR_ROWS);
00230     
00231   cv::Mat eigenvalues, eigenvectors;
00232   cv::eigen(cov, eigenvalues, eigenvectors); // descending order
00233   // eigenvectors are normalized
00234   
00235   // rotation to set old x, y, z axes to new principal directions, in 
00236   // descending order
00237   
00238   // 1) rotation to align old X with new X
00239   // oX = [1 0 0 0]';
00240   const cv::Mat xX = eigenvectors.colRange(0,1); // first eigenvector == new X axis
00241   
00242   // rotation vector
00243   cv::Mat V = (cv::Mat_<double>(3,1) 
00244     << 0.0, -xX.at<double>(2,0), xX.at<double>(1,0) ); // V = cross(oX, xX)
00245   V /= cv::norm(V);
00246   
00247   // rotation angle
00248   double alpha = acos(xX.at<double>(0,0)); // xX[0] == dot(oX, xX) / norm(oX) / norm(xX)
00249 
00250   // rotate the old system with RotV and get the intermediate Y axis
00251   // oY = [0 1 0 0]';
00252   cv::Mat RotV = DUtilsCV::Transformations::rotvec(V, alpha);
00253   cv::Mat auxY = RotV.colRange(1,2).rowRange(0,3); // == RotV * oY
00254   
00255   // 2) rotation to align auxY with new Y
00256   const cv::Mat xY = eigenvectors.colRange(1,2);
00257   double beta = acos( auxY.dot(xY) );
00258 
00259   // calculate beta sign
00260   V = auxY.cross(xY);
00261   V /= norm(V);
00262   if(V.dot(xX) < 0) beta = -beta;
00263   
00264   cv::Mat RotX = DUtilsCV::Transformations::rotx(beta);
00265 
00266   // 3) get final transformation
00267   cv::Mat wTo = RotV * RotX;
00268 
00269   // 4) merge with the translation to the centroid (or some center)
00270   wTo.at<double>(0, 3) = centroid.ptr<double>()[0];
00271   wTo.at<double>(1, 3) = centroid.ptr<double>()[1];
00272   wTo.at<double>(2, 3) = centroid.ptr<double>()[2];
00273   
00274   return DUtilsCV::Transformations::inv(wTo); // == oTw
00275 }
00276 
00277 // ----------------------------------------------------------------------------
00278 
00279 void transformPoints(vector<PLYPoint> &plypoints, 
00280   vector<Patch> &patches,
00281   const cv::Mat &oTw)
00282 {  
00283   vector<PLYPoint>::iterator pit;
00284   for(pit = plypoints.begin(); pit != plypoints.end(); ++pit)
00285   {
00286     transformPoint(pit->x, pit->y, pit->z, 1., oTw);
00287     transformPoint(pit->nx, pit->ny, pit->nz, 0., oTw);
00288   }
00289 
00290   vector<Patch>::iterator bit;
00291   for(bit = patches.begin(); bit != patches.end(); ++bit)
00292   {
00293     transformPoint(bit->x, bit->y, bit->z, bit->s, oTw);
00294     transformPoint(bit->nx, bit->ny, bit->nz, bit->ns, oTw);
00295   }
00296 }
00297 
00298 // ---------------------------------------------------------------------------
00299 
00300 void transformPoint(double &x, double &y, double &z, double s, const cv::Mat &oTw)
00301 {
00302   cv::Mat wP = (cv::Mat_<double>(4,1) << x, y, z, s);
00303   cv::Mat oP = oTw * wP;
00304   
00305   if(s != 0.)
00306   {
00307     x = oP.at<double>(0,0) / oP.at<double>(3,0);
00308     y = oP.at<double>(1,0) / oP.at<double>(3,0);
00309     z = oP.at<double>(2,0) / oP.at<double>(3,0);
00310   }else
00311   {
00312     x = oP.at<double>(0,0);
00313     y = oP.at<double>(1,0);
00314     z = oP.at<double>(2,0);
00315   }
00316 }
00317 
00318 // ---------------------------------------------------------------------------
00319 
00320 void transformCameras(vector<Camera> &cameras, const cv::Mat &oTw)
00321 {  
00322   const cv::Mat wTo = DUtilsCV::Transformations::inv(oTw);
00323     
00324   for(unsigned int i = 0; i < cameras.size(); ++i)
00325   {
00326     // For PMVS Cameras
00327     cv::Mat K, R, t; // 3x3, 3x3, 4x1
00328     cv::decomposeProjectionMatrix(cameras[i].P, K, R, t);
00329     // opencv 2.1: t is not correct 
00330  
00331     assert(R.type() == CV_64F);
00332     assert(t.type() == CV_64F);
00333     
00334     cv::Mat Rt = K.inv() * cameras[i].P;
00335     cv::Mat cvTw = (cv::Mat_<double>(4,4) <<
00336       Rt.at<double>(0,0), Rt.at<double>(0,1), Rt.at<double>(0,2), Rt.at<double>(0,3),
00337       Rt.at<double>(1,0), Rt.at<double>(1,1), Rt.at<double>(1,2), Rt.at<double>(1,3), 
00338       Rt.at<double>(2,0), Rt.at<double>(2,1), Rt.at<double>(2,2), Rt.at<double>(2,3), 
00339       0, 0, 0, 1); 
00340 
00341     cv::Mat cvTo = cvTw * wTo;
00342 
00343     cvTo.at<double>(0,3) /= cvTo.at<double>(3,3);
00344     cvTo.at<double>(1,3) /= cvTo.at<double>(3,3);
00345     cvTo.at<double>(2,3) /= cvTo.at<double>(3,3);
00346 
00347     cameras[i].P = K * cvTo.rowRange(0,3);
00348     
00349 
00350     /*
00351     // For Bundle Cameras
00352     cv::Mat R, t;
00353     R = cameras[i].R;
00354     t = cameras[i].t;
00355     
00356     cv::Mat cvTw = ( cv::Mat_<double>(4, 4) <<
00357       R.at<double>(0,0), R.at<double>(0,1), R.at<double>(0,2), t.at<double>(0,0),
00358       R.at<double>(1,0), R.at<double>(1,1), R.at<double>(1,2), t.at<double>(1,0),
00359       R.at<double>(2,0), R.at<double>(2,1), R.at<double>(2,2), t.at<double>(2,0),
00360                     0.0,               0.0,               0.0, t.at<double>(3,0));
00361 
00362     cv::Mat cvTo = cvTw * wTo;
00363 
00364     cvTo.at<double>(0,3) /= cvTo.at<double>(3,3);
00365     cvTo.at<double>(1,3) /= cvTo.at<double>(3,3);
00366     cvTo.at<double>(2,3) /= cvTo.at<double>(3,3);
00367 
00368     cameras[i].R = cvTo.rowRange(0, 3).colRange(0, 3);
00369     cameras[i].t = cvTo.rowRange(0, 3).colRange(3, 4);
00370     */
00371   }
00372 }
00373 
00374 // ---------------------------------------------------------------------------
00375 
00376 


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:30:49