@@ -283,6 +283,92 @@ std::vector<float> bni_pyramid(std::function<bool(QString s, int n)> progressed,
283
283
h = result.h ;
284
284
return result.heights ;
285
285
}
286
+ #include < Eigen/SparseCholesky>
287
+
288
+
289
+ Eigen::VectorXd bni_integrate_iterative (std::function<bool (QString s, int n)> progressed, Eigen::SparseMatrix<double> &A, Eigen::VectorXd &b, Eigen::SparseMatrix<double> W,
290
+ double k,
291
+ double tolerance, double solver_tolerance,
292
+ int max_iterations, int max_solver_iterations) {
293
+
294
+ int n = b.size ()/4 ;
295
+
296
+ Eigen::VectorXd z = Eigen::VectorXd::Zero (n);
297
+
298
+ Eigen::MatrixXd tmp = A*z - b;
299
+ double energy = (tmp.transpose () * W * tmp)(0 );
300
+ double start_energy = energy;
301
+ if (isnan (energy)) {
302
+ throw " Computational problems." ;
303
+ }
304
+
305
+ cout << " Energy : " << energy << endl;
306
+
307
+ vector<Triple> triples;
308
+ for (int i = 0 ; i < max_iterations; i++) {
309
+
310
+ Eigen::SparseMatrix<double > A_mat = A.transpose ()*W*A;
311
+ Eigen::VectorXd b_vec = A.transpose ()*W*b;
312
+
313
+ Eigen::ConjugateGradient<Eigen::SparseMatrix<double >> solver;
314
+
315
+ solver.compute (A_mat);
316
+ solver.setTolerance (solver_tolerance);
317
+ solver.setMaxIterations (max_solver_iterations);
318
+ z = solver.solveWithGuess (b_vec, z);
319
+ if (solver.info () != Eigen::Success) {
320
+ double finalResidual = solver.error ();
321
+ cerr << " Max iter reached with error: " << finalResidual << endl;
322
+ }
323
+
324
+ // Get the number of iterations
325
+ int numIterations = solver.iterations ();
326
+ std::cout << " Number of iterations: " << numIterations << " error: " << solver.error () << " tolerance: " << solver_tolerance << std::endl;
327
+
328
+
329
+ if (k == 0 )
330
+ break ;
331
+
332
+ Eigen::VectorXd wu = ((A.block (n, 0 , n, n)*z).array ().pow (2 ) -
333
+ (A.block (0 , 0 , n, n)*z).array ().pow (2 )).unaryExpr ([k](double x) { return sigmoid (x, k); });
334
+ Eigen::VectorXd wv = ((A.block (n*3 , 0 , n, n)*z).array ().pow (2 ) -
335
+ (A.block (n*2 , 0 , n, n)*z).array ().pow (2 )).unaryExpr ([k](double x) { return sigmoid (x, k); });
336
+
337
+ triples.clear ();
338
+ for (int i = 0 ; i < n; i++) {
339
+ triples.push_back (Triple (i, i, wu (i)));
340
+ triples.push_back (Triple (i+n, i+n, 1.0 - wu (i)));
341
+ triples.push_back (Triple (i+n*2 , i+n*2 , wv (i)));
342
+ triples.push_back (Triple (i+n*3 , i+n*3 , 1 - wv (i)));
343
+ }
344
+ W.setFromTriplets (triples.begin (), triples.end ());
345
+
346
+ double energy_old = energy;
347
+ tmp = A*z - b;
348
+ energy = (tmp.transpose () * W * tmp)(0 );
349
+ cout << " Energy: " << energy << endl;
350
+
351
+ double relative_energy = fabs (energy - energy_old) / energy_old;
352
+ double total_progress = fabs (energy - start_energy) / start_energy;
353
+ if (progressed) {
354
+ bool proceed = progressed (" Integrating normals..." , 100 *(1 - (log (relative_energy) - log (tolerance))/(log (total_progress) - log (tolerance))));
355
+ if (!proceed) break ;
356
+ }
357
+ if (relative_energy < tolerance)
358
+ break ;
359
+ }
360
+ return z;
361
+ }
362
+
363
+ Eigen::VectorXd bni_integrate_direct (Eigen::SparseMatrix<double > &A, Eigen::VectorXd &b, Eigen::SparseMatrix<double > &W) {
364
+ Eigen::SparseMatrix<double > A_mat = A.transpose ()*W*A;
365
+ Eigen::VectorXd b_vec = A.transpose ()*W*b;
366
+
367
+ Eigen::SimplicialLDLT<Eigen::SparseMatrix<double > > solver;
368
+ solver.compute (A_mat);
369
+ return solver.solve (b_vec);
370
+ }
371
+
286
372
287
373
void bni_integrate (std::function<bool (QString s, int n)> progressed, int w, int h, std::vector<float> &normalmap, std::vector<float> &heights,
288
374
double k,
@@ -361,77 +447,14 @@ void bni_integrate(std::function<bool(QString s, int n)> progressed, int w, int
361
447
triples.push_back (Triple (i, i, 0.5 ));
362
448
W.setFromTriplets (triples.begin (), triples.end ());
363
449
364
- Eigen::VectorXd z = Eigen::VectorXd::Zero (n);
365
- // for(int i = 0; i < n; i++)
366
- // z(i) = heights[i];
367
-
368
- Eigen::MatrixXd tmp = A*z - b;
369
- double energy = (tmp.transpose () * W * tmp)(0 );
370
- double start_energy = energy;
371
- if (isnan (energy)) {
372
- throw " Accidentaccio!" ;
373
- }
374
-
375
- cout << " Energy : " << energy << endl;
376
-
377
- for (int i = 0 ; i < max_iterations; i++) {
378
-
379
- Eigen::SparseMatrix<double > A_mat = A.transpose ()*W*A;
380
- Eigen::VectorXd b_vec = A.transpose ()*W*b;
381
-
382
- Eigen::ConjugateGradient<Eigen::SparseMatrix<double >> solver;
383
-
384
- // Eigen::LeastSquaresConjugateGradient<Eigen::SparseMatrix<double>> solver;
385
- // Eigen::BiCGSTAB<Eigen::SparseMatrix<double> > solver;
386
- solver.compute (A_mat);
387
- solver.setTolerance (solver_tolerance);
388
- solver.setMaxIterations (max_solver_iterations);
389
-
390
- z = solver.solveWithGuess (b_vec, z);
391
- if (solver.info () != Eigen::Success) {
392
- double finalResidual = solver.error ();
393
- cerr << " Max iter reached with error: " << finalResidual << endl;
394
- // return std::vector<double>();
395
- }
396
-
397
- // Get the number of iterations
398
- int numIterations = solver.iterations ();
399
- std::cout << " Number of iterations: " << numIterations << " error: " << solver.error () << " tolerance: " << solver_tolerance << std::endl;
400
-
450
+ Eigen::VectorXd z;
401
451
402
- if (k == 0 )
403
- break ;
452
+ if (k == 0.0 )
453
+ z = bni_integrate_direct (A, b, W);
454
+ else
455
+ z = bni_integrate_iterative (progressed, A, b, W, k, tolerance, solver_tolerance, max_iterations, max_solver_iterations);
404
456
405
- Eigen::VectorXd wu = ((A.block (n, 0 , n, n)*z).array ().pow (2 ) -
406
- (A.block (0 , 0 , n, n)*z).array ().pow (2 )).unaryExpr ([k](double x) { return sigmoid (x, k); });
407
- Eigen::VectorXd wv = ((A.block (n*3 , 0 , n, n)*z).array ().pow (2 ) -
408
- (A.block (n*2 , 0 , n, n)*z).array ().pow (2 )).unaryExpr ([k](double x) { return sigmoid (x, k); });
409
-
410
- triples.clear ();
411
- for (int i = 0 ; i < n; i++) {
412
- triples.push_back (Triple (i, i, wu (i)));
413
- triples.push_back (Triple (i+n, i+n, 1.0 - wu (i)));
414
- triples.push_back (Triple (i+n*2 , i+n*2 , wv (i)));
415
- triples.push_back (Triple (i+n*3 , i+n*3 , 1 - wv (i)));
416
- }
417
- W.setFromTriplets (triples.begin (), triples.end ());
418
-
419
- double energy_old = energy;
420
- tmp = A*z - b;
421
- energy = (tmp.transpose () * W * tmp)(0 );
422
- cout << " Energy: " << energy << endl;
423
-
424
- double relative_energy = fabs (energy - energy_old) / energy_old;
425
- double total_progress = fabs (energy - start_energy) / start_energy;
426
- if (progressed) {
427
- bool proceed = progressed (" Integrating normals..." , 100 *(1 - (log (relative_energy) - log (tolerance))/(log (total_progress) - log (tolerance))));
428
- if (!proceed) break ;
429
- }
430
- if (relative_energy < tolerance)
431
- break ;
432
- }
433
457
heights.resize (w*h);
434
458
for (int i = 0 ; i < w*h; i++)
435
459
heights[i] = z (i);
436
- // memcpy(&depthmap[0], z.data(), n*8);
437
460
}
0 commit comments