00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00043
00044 #define SHOW_RECONSTRUCTION
00045
00046 #include <QVApplication>
00047 #include <QTime>
00048 #include <qvsfm.h>
00049 #include <sfmviewer.h>
00050
00051 #ifndef QVSSBA_AVAILABLE
00052 #undef TEST_sSBA
00053 #endif
00054
00055 #ifdef QVSSBA_AVAILABLE
00056 #include <qvros.h>
00057 #endif
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 void onlineGEACostErrorSimplification(const int numCameras, QVDirectedGraph< QVector<QPointFMatching> > &pointLists,
00078 const int k_param = 10,
00079 const int s_param = 10)
00080 {
00081 QVector< QMap<int, int> > sortedUnusedCorrespondences(numCameras);
00082
00083
00084 QVDirectedGraph< QVector<QPointFMatching> > newPointLists;
00085 foreach(QPoint link, pointLists.keys())
00086 {
00087 const int sourceView = link.x(), destView = link.y();
00088
00089 const QVector<QPointFMatching> &pointList = pointLists[ link ];
00090 if (ABS(sourceView - destView) <= s_param)
00091 newPointLists [ QPoint(sourceView, destView) ] = pointList;
00092 else
00093 sortedUnusedCorrespondences [ sourceView ].insertMulti(-pointList.count(), destView);
00094 }
00095
00096
00097 for(int sourceView = 0; sourceView < numCameras; sourceView++)
00098 foreach(int destView, sortedUnusedCorrespondences[sourceView].values().mid(0, k_param))
00099 newPointLists[ QPoint(sourceView,destView) ] = pointLists[ QPoint(sourceView,destView) ];
00100
00101 pointLists = newPointLists;
00102 }
00103
00104 int links = 0;
00105
00106
00107 int dull_time_gea = 0;
00108 void GEAOptimization( const QList<QVCameraPose> initialCameraPoses,
00109 const QList<QHash<int, QPointF> > pointProjections,
00110 const int iterations,
00111 const double lambda,
00112 const bool dynamicLambda,
00113 const int k_param,
00114 const int s_param,
00115 QList<QV3DPointF> &refinedPoints3D,
00116 QList<QVCameraPose> &refinedCameras,
00117 int &time_GEA = dull_time_gea,
00118 const TGEA_decomposition_method decomposition_method = GEA_CHOLESKY_DECOMPOSITION,
00119 const TQVSparseSolve_Method solveMethod = DEFAULT_TQVSPARSESOLVE_METHOD,
00120 const int secondLevelIterations = 10
00121 )
00122 {
00123
00124
00125
00126 #ifdef MKL_AVAILABLE
00127 cold_start_mkl_initialization();
00128 #endif
00129
00130 QTime time, totalTime;
00131
00132
00133
00134
00135
00136 time.start();
00137 QVDirectedGraph< QVector<QPointFMatching> > pointLists = getPointMatchingsListsVec( pointProjections, initialCameraPoses.count() );
00138 int gea_time_pointlists = time.elapsed();
00139
00140 totalTime.start();
00141
00142 onlineGEACostErrorSimplification(initialCameraPoses.count(), pointLists, k_param, s_param);
00143
00144 std::cout << "Number of terms in the GEA cost error = " << pointLists.count() << std::endl;
00145
00146
00147 int countLink = 0;
00148 QVector<QPointFMatching> temp;
00149 foreach(temp, pointLists)
00150 if (temp.count() >= 9)
00151 countLink++;
00152
00153
00154
00155 links = countLink;
00156
00157
00158 time.start();
00159 const QVDirectedGraph<QVMatrix> reducedMatricesgraph = getReducedMatrices(pointLists, false, decomposition_method, true, 1e-6);
00160 int gea_time_RMM = time.elapsed();
00161
00162
00163 refinedCameras = globalEpipolarAdjustment(iterations, initialCameraPoses, reducedMatricesgraph, lambda, dynamicLambda, solveMethod, secondLevelIterations);
00164
00165
00166 time.start();
00167 refinedPoints3D = linear3DPointsTriangulation(refinedCameras, pointProjections);
00168 const int gea_time_LT = time.elapsed();
00169 const int totalTime_GEA = totalTime.elapsed();
00170
00171
00172 std::cout << "[GEA] Time point matchings lists: " << gea_time_pointlists
00173 << " ms\tRMM: " << gea_time_RMM
00174 << " ms\tEvaluation: " << gea_time_eval
00175 << " ms\tSolve: " << gea_time_solve
00176 << " ms\tLT: " << gea_time_LT
00177 << " ms" << std::endl;
00178 std::cout << "[GEA] Time total (RMM + Evaluation + Solve + LT) =\t" << totalTime_GEA << " ms." << std::endl;
00179
00180 time_GEA = totalTime_GEA;
00181 }
00182
00183
00184 void printReconstructionStats( const QList<QVCameraPose> &cameraPoses,
00185 const QList<QV3DPointF> &points3D,
00186 const QList< QHash< int, QPointF> > &pointsProjections)
00187 {
00188 const int numCameras = cameraPoses.count(), numPoints = points3D.count();
00189 int numProjections = 0;
00190 QHash< int, QPointF> temp;
00191 foreach(temp, pointsProjections)
00192 numProjections += temp.count();
00193
00194 std::cout << "[main] Readed " << numPoints << " points, "
00195 << numCameras << " cameras, "
00196 << numProjections << " projections, "
00197 << double(numProjections)/double(numCameras) << " projections/camera, "
00198 << double(numProjections)/double(numPoints) << " projections/point."
00199 << std::endl;
00200 }
00201
00202 int main(int argc, char *argv[])
00203 {
00204 #ifdef SHOW_RECONSTRUCTION
00205 QVApplication app(argc, argv, "Example application for QVision.", true);
00206 #else
00207 QVApplication app(argc, argv, "Example application for QVision.", false);
00208 #endif
00209
00210
00211 if (app.getNumberOfArguments() < 2)
00212 {
00213 std::cout << "Usage: " << std::endl << "\t" << argv[0] << " <data_set_path> [iterations] [lambda] [k param] [s param]"
00214 << std::endl << std::endl;
00215 exit(0);
00216 }
00217
00218 const QString path = app.getArgument(1);
00219
00220
00221 bool iters_OK = true, lambda_gea_OK = true, k_param_OK = true, s_param_OK = true;
00222
00223 const int iters = (app.getNumberOfArguments() < 3)? 1 : app.getArgument(2).toInt(&iters_OK);
00224 const double lambda_gea = (app.getNumberOfArguments() < 4)? 1.0 : app.getArgument(3).toDouble(&lambda_gea_OK);
00225 const double k_param = (app.getNumberOfArguments() < 5)? 10000000 : app.getArgument(4).toInt(&k_param_OK);
00226 const double s_param = (app.getNumberOfArguments() < 6)? 10000000 : app.getArgument(5).toInt(&s_param_OK);
00227
00228 if (not iters_OK)
00229 {
00230 std::cout << "[main] Error reading number of iterations." << std::endl;
00231 exit(0);
00232 }
00233 else
00234 std::cout << "[main] Number of iterations = " << iters << std::endl;
00235
00236 if (not lambda_gea_OK)
00237 {
00238 std::cout << "[main] Error reading lambda for GEA optimization" << std::endl;
00239 exit(0);
00240 }
00241 else
00242 std::cout << "[main] Lambda for GEA = " << lambda_gea << std::endl;
00243
00244 if (not k_param_OK)
00245 {
00246 std::cout << "[main] Error reading 'k' param for GEA cost error simplification" << std::endl;
00247 exit(0);
00248 }
00249 else
00250 std::cout << "[main] Value for 'k' parameter = " << k_param << std::endl;
00251
00252 if (not s_param_OK)
00253 {
00254 std::cout << "[main] Error reading 's' param for GEA cost error simplification" << std::endl;
00255 exit(0);
00256 }
00257 else
00258 std::cout << "[main] Value for 's' parameter = " << s_param << std::endl;
00259
00260
00261 QList<QV3DPointF> points3D;
00262 QList<QVCameraPose> cameraPoses;
00263 QList<QVMatrix> cameraCalibrations;
00264 QList< QHash< int, QPointF> > pointsProjections;
00265
00266 if( not readSfMReconstruction(path, cameraCalibrations, cameraPoses, points3D, pointsProjections) )
00267 {
00268 std::cout << "[main] Error: could not read SfM reconstruction from path '" << qPrintable(path) << "'." << std::endl;
00269 return 0;
00270 }
00271
00272
00273 const QList< QHash< int, QPointF> > calibratedPointsProjections = correctIntrinsics(cameraCalibrations, pointsProjections);
00274
00275
00276 if (testCheirality(cameraPoses, calibratedPointsProjections))
00277 invertCheirality(cameraPoses, points3D);
00278
00279
00280 std::cout << "[main] Reconstruction loaded."<< std::endl;
00281 printReconstructionStats(cameraPoses, points3D, calibratedPointsProjections);
00282
00283
00284
00285
00286 #define REDUCED_MATRIX_DECOMPOSITION GEA_CHOLESKY_DECOMPOSITION // Use Cholesky decomposition.
00287
00288
00289
00290
00291
00292 #define SPARSE_SOLVE_METHOD QV_BJPCG // Block-Jacobi preconditioned conjugate gradient
00293
00294
00295 int time_GEA;
00296 QList<QV3DPointF> points3D_GEA;
00297 QList<QVCameraPose> cameraPoses_GEA;
00298 GEAOptimization(cameraPoses, calibratedPointsProjections, iters, lambda_gea, false, k_param, s_param, points3D_GEA, cameraPoses_GEA,
00299 time_GEA, REDUCED_MATRIX_DECOMPOSITION, SPARSE_SOLVE_METHOD, 30);
00300
00301 QHash< int, QPointF> temp;
00302 int count = 0;
00303 foreach(temp, pointsProjections)
00304 count += temp.count();
00305 std::cout << "Number of views = " << cameraPoses.count() << std::endl;
00306 std::cout << "Number of points = " << points3D.count() << std::endl;
00307 std::cout << "Number of projections = " << count << std::endl;
00308
00309
00310 std::cout << "[main] Initial error\t" << 1000.0 * reconstructionError(cameraPoses, points3D, calibratedPointsProjections) << std::endl;
00311 std::cout << "[main] GEA error/time\t" << 1000.0 * reconstructionError(cameraPoses_GEA, points3D_GEA, calibratedPointsProjections) << "\t" << double(time_GEA) / 1000.0 << " s" << std::endl;
00312
00313 #ifdef SHOW_RECONSTRUCTION
00314 SfMViewer originalMap(cameraPoses, points3D, "Original reconstruction");
00315 SfMViewer geaOptimizedMap(cameraPoses_GEA, points3D_GEA, "Reconstruction optimized with GEA");
00316 return app.exec();
00317 #endif // SHOW_RECONSTRUCTION
00318
00319 exit(0);
00320 }
00321