Subversion Repositories seema-scanner

Rev

Rev 176 | Rev 206 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 176 Rev 196
Line 8... Line 8...
8
#include <numeric>
8
#include <numeric>
9
 
9
 
10
#include <png.h>
10
#include <png.h>
11
#include <zlib.h>
11
#include <zlib.h>
12
 
12
 
-
 
13
#include <eigen3/unsupported/Eigen/NonLinearOptimization>
-
 
14
 
-
 
15
 
13
namespace cvtools{
16
namespace cvtools{
14
 
17
 
15
// Convert an BGR 3-channel image back into a Bayered image. This saves memory when reading images from disk.
18
// Convert an BGR 3-channel image back into a Bayered image. This saves memory when reading images from disk.
16
void cvtColorBGRToBayerBG(const cv::Mat &imBGR, cv::Mat &imBayerBG){
19
void cvtColorBGRToBayerBG(const cv::Mat &imBGR, cv::Mat &imBayerBG){
17
 
20
 
Line 336... Line 339...
336
 
339
 
337
    cv::Mat err_tau = b - (A*cv::Mat(tau));
340
    cv::Mat err_tau = b - (A*cv::Mat(tau));
338
    std::cout << err_tau << std::endl;
341
    std::cout << err_tau << std::endl;
339
}
342
}
340
 
343
 
341
// Closed form solution to solve for the rotation axis from sets of 3D point coordinates of flat pattern feature points
-
 
342
// Algorithm according to Chen et al., Rotation axis calibration of a turntable using constrained global optimization, Optik 2014
-
 
343
// DTU, 2014, Jakob Wilm
-
 
344
void rotationAxisCalibration(const std::vector< std::vector<cv::Point3f> > Qcam, const std::vector<cv::Point3f> Qobj, cv::Vec3f &axis, cv::Vec3f &point, float &error){
-
 
345
 
-
 
346
    // number of frames (points on each arch)
-
 
347
    int l = Qcam.size();
-
 
348
 
-
 
349
    // number of points in each frame
-
 
350
    size_t mn = Qobj.size();
-
 
351
 
-
 
352
    assert(mn == Qcam[0].size());
-
 
353
 
-
 
354
    // construct matrix for axis determination
-
 
355
    cv::Mat M(6, 6, CV_32F, cv::Scalar(0));
-
 
356
 
-
 
357
    for(int k=0; k<l; k++){
-
 
358
        for(unsigned int idx=0; idx<mn; idx++){
-
 
359
 
-
 
360
//            float i = Qobj[idx].x+4;
-
 
361
//            float j = Qobj[idx].y+4;
-
 
362
            float i = Qobj[idx].x;
-
 
363
            float j = Qobj[idx].y;
-
 
364
 
-
 
365
            float x = Qcam[k][idx].x;
-
 
366
            float y = Qcam[k][idx].y;
-
 
367
            float z = Qcam[k][idx].z;
-
 
368
 
-
 
369
            M += (cv::Mat_<float>(6,6) << x*x, x*y, x*z, x, i*x, j*x,
-
 
370
                                            0, y*y, y*z, y, i*y, j*y,
-
 
371
                                            0,   0, z*z, z, i*z, j*z,
-
 
372
                                            0,   0,   0, 1,   i,   j,
-
 
373
                                            0,   0,   0, 0, i*i, i*j,
-
 
374
                                            0,   0,   0, 0,   0, j*j);
-
 
375
 
-
 
376
        }
-
 
377
    }
-
 
378
 
-
 
379
    cv::completeSymm(M, false);
-
 
380
 
-
 
381
    // solve for axis
-
 
382
    std::vector<float> lambda;
-
 
383
    cv::Mat u;
-
 
384
    cv::eigen(M, lambda, u);
-
 
385
 
-
 
386
    float minLambda = std::abs(lambda[0]);
-
 
387
    int idx = 0;
-
 
388
    for(unsigned int i=1; i<lambda.size(); i++){
-
 
389
        if(abs(lambda[i]) < minLambda){
-
 
390
            minLambda = lambda[i];
-
 
391
            idx = i;
-
 
392
        }
-
 
393
    }
-
 
394
 
-
 
395
    axis = u.row(idx).colRange(0, 3);
-
 
396
    axis = cv::normalize(axis);
-
 
397
 
-
 
398
    float nx = u.at<float>(idx, 0);
-
 
399
    float ny = u.at<float>(idx, 1);
-
 
400
    float nz = u.at<float>(idx, 2);
-
 
401
//    float d  = u.at<float>(idx, 3);
-
 
402
    float dh = u.at<float>(idx, 4);
-
 
403
    float dv = u.at<float>(idx, 5);
-
 
404
 
-
 
405
//    // Paper version: c is initially eliminated
-
 
406
//    cv::Mat A(l*mn, mn+2, CV_32F, cv::Scalar(0.0));
-
 
407
//    cv::Mat bb(l*mn, 1, CV_32F);
-
 
408
 
-
 
409
//    for(int k=0; k<l; k++){
-
 
410
//        for(int idx=0; idx<mn; idx++){
-
 
411
 
-
 
412
//            float i = Qobj[idx].x;
-
 
413
//            float j = Qobj[idx].y;
-
 
414
 
-
 
415
//            float x = Qcam[k][idx].x;
-
 
416
//            float y = Qcam[k][idx].y;
-
 
417
//            float z = Qcam[k][idx].z;
-
 
418
 
-
 
419
//            float f = x*x + y*y + z*z + (2*x*nx + 2*y*ny + 2*z*nz)*(i*dh + j*dv);
-
 
420
 
-
 
421
//            int row = k*mn+idx;
-
 
422
//            A.at<float>(row, 0) = 2*x - (2*z*nx)/nz;
-
 
423
//            A.at<float>(row, 1) = 2*y - (2*z*ny)/nz;
-
 
424
//            A.at<float>(row, idx+2) = 1.0;
-
 
425
 
-
 
426
//            bb.at<float>(row, 0) = f + (2*z*d)/nz;
-
 
427
//        }
-
 
428
//    }
-
 
429
 
-
 
430
//    // solve for point
-
 
431
//    cv::Mat abe;
-
 
432
//    cv::solve(A, bb, abe, cv::DECOMP_SVD);
-
 
433
 
-
 
434
//    float a = abe.at<float>(0, 0);
-
 
435
//    float b = abe.at<float>(1, 0);
-
 
436
//    float c = -(nx*a+ny*b+d)/nz;
-
 
437
 
-
 
438
    // Our version: solve simultanously for a,b,c
-
 
439
    cv::Mat A(l*mn, mn+3, CV_32F, cv::Scalar(0.0));
-
 
440
    cv::Mat bb(l*mn, 1, CV_32F);
-
 
441
 
-
 
442
    for(int k=0; k<l; k++){
-
 
443
        for(unsigned int idx=0; idx<mn; idx++){
-
 
444
 
-
 
445
            float i = Qobj[idx].x;
-
 
446
            float j = Qobj[idx].y;
-
 
447
 
-
 
448
            float x = Qcam[k][idx].x;
-
 
449
            float y = Qcam[k][idx].y;
-
 
450
            float z = Qcam[k][idx].z;
-
 
451
 
-
 
452
            float f = x*x + y*y + z*z + (2*x*nx + 2*y*ny + 2*z*nz)*(i*dh + j*dv);
-
 
453
 
-
 
454
            int row = k*mn+idx;
-
 
455
            A.at<float>(row, 0) = 2*x;
-
 
456
            A.at<float>(row, 1) = 2*y;
-
 
457
            A.at<float>(row, 2) = 2*z;
-
 
458
            A.at<float>(row, idx+3) = 1.0;
-
 
459
 
-
 
460
            bb.at<float>(row, 0) = f;
-
 
461
        }
-
 
462
    }
-
 
463
 
-
 
464
    // solve for point
-
 
465
    cv::Mat abe;
-
 
466
    cv::solve(A, bb, abe, cv::DECOMP_SVD);
-
 
467
 
-
 
468
    float a = abe.at<float>(0, 0);
-
 
469
    float b = abe.at<float>(1, 0);
-
 
470
    float c = abe.at<float>(2, 0);
-
 
471
 
-
 
472
    point[0] = a;
-
 
473
    point[1] = b;
-
 
474
    point[2] = c;
-
 
475
 
-
 
476
    // Error estimate (mean 3D point deviations from circles around rotation axis)
-
 
477
    error = 0;
-
 
478
    // loop through saddle points
-
 
479
    for(unsigned int idx=0; idx<mn; idx++){
-
 
480
 
-
 
481
        // vector of distances from rotation axis
-
 
482
        std::vector<float> dI(l);
-
 
483
        // loop through angular positions
-
 
484
        for(int k=0; k<l; k++){
-
 
485
            cv::Vec3f p = cv::Vec3f(Qcam[k][idx]);
-
 
486
            // point to line distance
-
 
487
            dI[k] = cv::norm((point-p)-(point-p).dot(axis)*axis);
-
 
488
        }
-
 
489
        float sum = std::accumulate(dI.begin(), dI.end(), 0.0);
-
 
490
        float mean = sum / dI.size();
-
 
491
        float meanDev = 0;
-
 
492
        for(int k=0; k<l; k++){
-
 
493
            meanDev += std::abs(dI[k] - mean);
-
 
494
        }
-
 
495
        meanDev /= l;
-
 
496
        //std::cout << meanDev << std::endl;
-
 
497
        error += meanDev;
-
 
498
    }
-
 
499
    error /= mn;
-
 
500
}
-
 
501
 
344
 
502
// Function to fit two sets of corresponding pose data.
345
// Function to fit two sets of corresponding pose data.
503
// Finds [Omega | tau], to minimize ||[R_mark | t_mark] - [Omega | tau][R | t]||^2
346
// Finds [Omega | tau], to minimize ||[R_mark | t_mark] - [Omega | tau][R | t]||^2
504
// Algorithm and notation according to Mili Shah, Comparing two sets of corresponding six degree of freedom data, CVIU 2011.
347
// Algorithm and notation according to Mili Shah, Comparing two sets of corresponding six degree of freedom data, CVIU 2011.
505
// DTU, 2013, Oline V. Olesen, Jakob Wilm
348
// DTU, 2013, Oline V. Olesen, Jakob Wilm