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
00186
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
00196
00197
00198
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
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 centroid += samples.rowRange(i,i+1);
00219 }
00220 centroid /= plypoints.size();
00221
00222
00223
00224
00225
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);
00233
00234
00235
00236
00237
00238
00239
00240 const cv::Mat xX = eigenvectors.colRange(0,1);
00241
00242
00243 cv::Mat V = (cv::Mat_<double>(3,1)
00244 << 0.0, -xX.at<double>(2,0), xX.at<double>(1,0) );
00245 V /= cv::norm(V);
00246
00247
00248 double alpha = acos(xX.at<double>(0,0));
00249
00250
00251
00252 cv::Mat RotV = DUtilsCV::Transformations::rotvec(V, alpha);
00253 cv::Mat auxY = RotV.colRange(1,2).rowRange(0,3);
00254
00255
00256 const cv::Mat xY = eigenvectors.colRange(1,2);
00257 double beta = acos( auxY.dot(xY) );
00258
00259
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
00267 cv::Mat wTo = RotV * RotX;
00268
00269
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);
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
00327 cv::Mat K, R, t;
00328 cv::decomposeProjectionMatrix(cameras[i].P, K, R, t);
00329
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
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 }
00372 }
00373
00374
00375
00376