/*! Realize the VVS loop for the tracking \param nbInfos : Size of the features \param w : weight of the features after M-Estimation. */ void vpMbKltTracker::computeVVS(const unsigned int &nbInfos, vpColVector &w) { vpMatrix L; // interaction matrix vpColVector R; // residu vpMatrix L_true; // interaction matrix vpMatrix LVJ_true; //vpColVector R_true; // residu vpColVector v; // "speed" for VVS vpHomography H; vpColVector w_true; vpRobust robust(2*nbInfos); vpMatrix LTL; vpColVector LTR; vpHomogeneousMatrix cMoPrev; vpHomogeneousMatrix ctTc0_Prev; vpColVector error_prev(2*nbInfos); double mu = 0.01; double normRes = 0; double normRes_1 = -1; unsigned int iter = 0; R.resize(2*nbInfos); L.resize(2*nbInfos, 6, 0); while( ((int)((normRes - normRes_1)*1e8) != 0 ) && (iter<maxIter) ){ unsigned int shift = 0; computeVVSInteractionMatrixAndResidu(shift, R, L, H, kltPolygons, kltCylinders, ctTc0); bool reStartFromLastIncrement = false; computeVVSCheckLevenbergMarquardtKlt(iter, nbInfos, cMoPrev, error_prev, ctTc0_Prev, mu, reStartFromLastIncrement); if(!reStartFromLastIncrement){ computeVVSWeights(iter, nbInfos, R, w_true, w, robust); computeVVSPoseEstimation(iter, L, w, L_true, LVJ_true, normRes, normRes_1, w_true, R, LTL, LTR, error_prev, v, mu, cMoPrev, ctTc0_Prev); } // endif(!reStartFromLastIncrement) iter++; } if(computeCovariance){ computeVVSCovariance(w_true, cMoPrev, L_true, LVJ_true); } }
/*! \brief Compute the pose using virtual visual servoing approach and a robust cotrol law This approach is described in A.I. Comport, E. Marchand, M. Pressigout, F. Chaumette. Real-time markerless tracking for augmented reality: the virtual visual servoing framework. IEEE Trans. on Visualization and Computer Graphics, 12(4):615-628, Juillet 2006. */ void vpPose::poseVirtualVSrobust(vpHomogeneousMatrix & cMo) { try{ double residu_1 = 1e8 ; double r =1e8-1; // we stop the minimization when the error is bellow 1e-8 vpMatrix W ; vpRobust robust(2*listP.size()) ; robust.setThreshold(0.0000) ; vpColVector w,res ; unsigned int nb = listP.size() ; vpMatrix L(2*nb,6) ; vpColVector error(2*nb) ; vpColVector sd(2*nb),s(2*nb) ; vpColVector v ; listP.front() ; vpPoint P; std::list<vpPoint> lP ; // create sd unsigned int k =0 ; for (std::list<vpPoint>::const_iterator it = listP.begin(); it != listP.end(); ++it) { P = *it; sd[2*k] = P.get_x() ; sd[2*k+1] = P.get_y() ; lP.push_back(P) ; k ++; } int iter = 0 ; res.resize(s.getRows()/2) ; w.resize(s.getRows()/2) ; W.resize(s.getRows(), s.getRows()) ; w =1 ; while((int)((residu_1 - r)*1e12) !=0) { residu_1 = r ; // Compute the interaction matrix and the error vpPoint P ; k =0 ; for (std::list<vpPoint>::const_iterator it = lP.begin(); it != lP.end(); ++it) { P = *it; // forward projection of the 3D model for a given pose // change frame coordinates // perspective projection P.track(cMo) ; double x = s[2*k] = P.get_x(); // point projected from cMo double y = s[2*k+1] = P.get_y(); double Z = P.get_Z() ; L[2*k][0] = -1/Z ; L[2*k][1] = 0 ; L[2*k][2] = x/Z ; L[2*k][3] = x*y ; L[2*k][4] = -(1+x*x) ; L[2*k][5] = y ; L[2*k+1][0] = 0 ; L[2*k+1][1] = -1/Z ; L[2*k+1][2] = y/Z ; L[2*k+1][3] = 1+y*y ; L[2*k+1][4] = -x*y ; L[2*k+1][5] = -x ; k ++; } error = s - sd ; // compute the residual r = error.sumSquare() ; for(unsigned int k=0 ; k <error.getRows()/2 ; k++) { res[k] = vpMath::sqr(error[2*k]) + vpMath::sqr(error[2*k+1]) ; } robust.setIteration(0); robust.MEstimator(vpRobust::TUKEY, res, w); // compute the pseudo inverse of the interaction matrix for (unsigned int k=0 ; k < error.getRows()/2 ; k++) { W[2*k][2*k] = w[k] ; W[2*k+1][2*k+1] = w[k] ; } // compute the pseudo inverse of the interaction matrix vpMatrix Lp ; (W*L).pseudoInverse(Lp,1e-6) ; // compute the VVS control law v = -lambda*Lp*W*error ; cMo = vpExponentialMap::direct(v).inverse()*cMo ; ; if (iter++>vvsIterMax) break ; } if(computeCovariance) covarianceMatrix = vpMatrix::computeCovarianceMatrix(L,v,-lambda*error, W*W); // Remark: W*W = W*W.t() since the matrix is diagonale, but using W*W is more efficient. } catch(...) { vpERROR_TRACE(" ") ; throw ; } }
double vpHomography::computeRotation(unsigned int nbpoint, vpPoint *c1P, vpPoint *c2P, vpHomogeneousMatrix &c2Mc1, int userobust ) { vpColVector e(2) ; double r_1 = -1 ; vpColVector p2(3) ; vpColVector p1(3) ; vpColVector Hp2(3) ; vpColVector Hp1(3) ; vpMatrix H2(2,3) ; vpColVector e2(2) ; vpMatrix H1(2,3) ; vpColVector e1(2) ; int only_1 = 0 ; int only_2 = 0 ; int iter = 0 ; unsigned int n=0 ; for (unsigned int i=0 ; i < nbpoint ; i++) { // if ((c2P[i].get_x() !=-1) && (c1P[i].get_x() !=-1)) if ( (std::fabs(c2P[i].get_x() + 1) > std::fabs(vpMath::maximum(c2P[i].get_x(), 1.))) && (std::fabs(c1P[i].get_x() + 1) > std::fabs(vpMath::maximum(c1P[i].get_x(), 1.))) ) { n++ ; } } if ((only_1==1) || (only_2==1)) ; else n *=2 ; vpRobust robust(n); vpColVector res(n) ; vpColVector w(n) ; w =1 ; robust.setThreshold(0.0000) ; vpMatrix W(2*n,2*n) ; W = 0 ; vpMatrix c2Rc1(3,3) ; double r =0 ; while (vpMath::equal(r_1,r,threshold_rotation) == false ) { r_1 =r ; // compute current position //Change frame (current) for (unsigned int i=0 ; i < 3 ; i++) for (unsigned int j=0 ; j < 3 ; j++) c2Rc1[i][j] = c2Mc1[i][j] ; vpMatrix L(2,3), Lp ; int k =0 ; for (unsigned int i=0 ; i < nbpoint ; i++) { //if ((c2P[i].get_x() !=-1) && (c1P[i].get_x() !=-1)) if ( (std::fabs(c2P[i].get_x() + 1) > std::fabs(vpMath::maximum(c2P[i].get_x(), 1.))) && (std::fabs(c1P[i].get_x() + 1) > std::fabs(vpMath::maximum(c1P[i].get_x(), 1.))) ) { p2[0] = c2P[i].get_x() ; p2[1] = c2P[i].get_y() ; p2[2] = 1.0 ; p1[0] = c1P[i].get_x() ; p1[1] = c1P[i].get_y() ; p1[2] = 1.0 ; Hp2 = c2Rc1.t()*p2 ; // p2 = Hp1 Hp1 = c2Rc1*p1 ; // p1 = Hp2 Hp2 /= Hp2[2] ; // normalisation Hp1 /= Hp1[2] ; // set up the interaction matrix double x = Hp2[0] ; double y = Hp2[1] ; H2[0][0] = x*y ; H2[0][1] = -(1+x*x) ; H2[0][2] = y ; H2[1][0] = 1+y*y ; H2[1][1] = -x*y ; H2[1][2] = -x ; H2 *=-1 ; H2 = H2*c2Rc1.t() ; // Set up the error vector e2[0] = Hp2[0] - c1P[i].get_x() ; e2[1] = Hp2[1] - c1P[i].get_y() ; // set up the interaction matrix x = Hp1[0] ; y = Hp1[1] ; H1[0][0] = x*y ; H1[0][1] = -(1+x*x) ; H1[0][2] = y ; H1[1][0] = 1+y*y ; H1[1][1] = -x*y ; H1[1][2] = -x ; // Set up the error vector e1[0] = Hp1[0] - c2P[i].get_x() ; e1[1] = Hp1[1] - c2P[i].get_y() ; if (only_2==1) { if (k == 0) { L = H2 ; e = e2 ; } else { L = vpMatrix::stackMatrices(L,H2) ; e = vpMatrix::stackMatrices(e,e2) ; } } else if (only_1==1) { if (k == 0) { L = H1 ; e= e1 ; } else { L = vpMatrix::stackMatrices(L,H1) ; e = vpMatrix::stackMatrices(e,e1) ; } } else { if (k == 0) {L = H2 ; e = e2 ; } else { L = vpMatrix::stackMatrices(L,H2) ; e = vpMatrix::stackMatrices(e,e2) ; } L = vpMatrix::stackMatrices(L,H1) ; e = vpMatrix::stackMatrices(e,e1) ; } k++ ; } } if (userobust) { robust.setIteration(0); for (unsigned int k=0 ; k < n ; k++) { res[k] = vpMath::sqr(e[2*k]) + vpMath::sqr(e[2*k+1]) ; } robust.MEstimator(vpRobust::TUKEY, res, w); // compute the pseudo inverse of the interaction matrix for (unsigned int k=0 ; k < n ; k++) { W[2*k][2*k] = w[k] ; W[2*k+1][2*k+1] = w[k] ; } } else { for (unsigned int k=0 ; k < 2*n ; k++) W[k][k] = 1 ; } // CreateDiagonalMatrix(w, W) ; (L).pseudoInverse(Lp, 1e-6) ; // Compute the camera velocity vpColVector c2Rc1, v(6) ; c2Rc1 = -2*Lp*W*e ; for (unsigned int i=0 ; i < 3 ; i++) v[i+3] = c2Rc1[i] ; // only for simulation updatePoseRotation(c2Rc1, c2Mc1) ; r =e.sumSquare() ; if ((W*e).sumSquare() < 1e-10) break ; if (iter>25) break ; iter++ ; // std::cout << iter <<" e=" <<(e).sumSquare() <<" e=" <<(W*e).sumSquare() <<std::endl ; } // std::cout << c2Mc1 <<std::endl ; return (W*e).sumSquare() ; }
double vpHomography::computeDisplacement(unsigned int nbpoint, vpPoint *c1P, vpPoint *c2P, vpPlane *oN, vpHomogeneousMatrix &c2Mc1, vpHomogeneousMatrix &c1Mo, int userobust ) { vpColVector e(2) ; double r_1 = -1 ; vpColVector p2(3) ; vpColVector p1(3) ; vpColVector Hp2(3) ; vpColVector Hp1(3) ; vpMatrix H2(2,6) ; vpColVector e2(2) ; vpMatrix H1(2,6) ; vpColVector e1(2) ; int only_1 = 1 ; int only_2 = 0 ; int iter = 0 ; unsigned int i ; unsigned int n=0 ; n = nbpoint ; if ((only_1==1) || (only_2==1)) ; else n *=2 ; vpRobust robust(n); vpColVector res(n) ; vpColVector w(n) ; w =1 ; robust.setThreshold(0.0000) ; vpMatrix W(2*n,2*n) ; W = 0 ; vpColVector N1(3), N2(3) ; double d1, d2 ; double r =1e10 ; iter =0 ; while (vpMath::equal(r_1,r,threshold_displacement) == false ) { r_1 =r ; // compute current position //Change frame (current) vpHomogeneousMatrix c1Mc2, c2Mo ; vpRotationMatrix c1Rc2, c2Rc1 ; vpTranslationVector c1Tc2, c2Tc1 ; c1Mc2 = c2Mc1.inverse() ; c2Mc1.extract(c2Rc1) ; c2Mc1.extract(c2Tc1) ; c2Mc1.extract(c1Rc2) ; c1Mc2.extract(c1Tc2) ; c2Mo = c2Mc1*c1Mo ; vpMatrix L(2,3), Lp ; int k =0 ; for (i=0 ; i < nbpoint ; i++) { getPlaneInfo(oN[i], c1Mo, N1, d1) ; getPlaneInfo(oN[i], c2Mo, N2, d2) ; p2[0] = c2P[i].get_x() ; p2[1] = c2P[i].get_y() ; p2[2] = 1.0 ; p1[0] = c1P[i].get_x() ; p1[1] = c1P[i].get_y() ; p1[2] = 1.0 ; vpMatrix H(3,3) ; Hp2 = ((vpMatrix)c1Rc2 + ((vpMatrix)c1Tc2*N2.t())/d2)*p2 ; // p2 = Hp1 Hp1 = ((vpMatrix)c2Rc1 + ((vpMatrix)c2Tc1*N1.t())/d1)*p1 ; // p1 = Hp2 Hp2 /= Hp2[2] ; // normalisation Hp1 /= Hp1[2] ; // set up the interaction matrix double x = Hp2[0] ; double y = Hp2[1] ; double Z1 ; Z1 = (N1[0]*x+N1[1]*y+N1[2])/d1 ; // 1/z H2[0][0] = -Z1 ; H2[0][1] = 0 ; H2[0][2] = x*Z1 ; H2[1][0] = 0 ; H2[1][1] = -Z1 ; H2[1][2] = y*Z1 ; H2[0][3] = x*y ; H2[0][4] = -(1+x*x) ; H2[0][5] = y ; H2[1][3] = 1+y*y ; H2[1][4] = -x*y ; H2[1][5] = -x ; H2 *=-1 ; vpMatrix c1CFc2(6,6) ; { vpMatrix sTR = c1Tc2.skew()*(vpMatrix)c1Rc2 ; for (unsigned int k=0 ; k < 3 ; k++) for (unsigned int l=0 ; l<3 ; l++) { c1CFc2[k][l] = c1Rc2[k][l] ; c1CFc2[k+3][l+3] = c1Rc2[k][l] ; c1CFc2[k][l+3] = sTR[k][l] ; } } H2 = H2*c1CFc2 ; // Set up the error vector e2[0] = Hp2[0] - c1P[i].get_x() ; e2[1] = Hp2[1] - c1P[i].get_y() ; x = Hp1[0] ; y = Hp1[1] ; Z1 = (N2[0]*x+N2[1]*y+N2[2])/d2 ; // 1/z H1[0][0] = -Z1 ; H1[0][1] = 0 ; H1[0][2] = x*Z1 ; H1[1][0] = 0 ; H1[1][1] = -Z1 ; H1[1][2] = y*Z1; H1[0][3] = x*y ; H1[0][4] = -(1+x*x) ; H1[0][5] = y ; H1[1][3] = 1+y*y ; H1[1][4] = -x*y ; H1[1][5] = -x ; // Set up the error vector e1[0] = Hp1[0] - c2P[i].get_x() ; e1[1] = Hp1[1] - c2P[i].get_y() ; if (only_2==1) { if (k == 0) { L = H2 ; e = e2 ; } else { L = vpMatrix::stackMatrices(L,H2) ; e = vpMatrix::stackMatrices(e,e2) ; } } else if (only_1==1) { if (k == 0) { L = H1 ; e= e1 ; } else { L = vpMatrix::stackMatrices(L,H1) ; e = vpMatrix::stackMatrices(e,e1) ; } } else { if (k == 0) {L = H2 ; e = e2 ; } else { L = vpMatrix::stackMatrices(L,H2) ; e = vpMatrix::stackMatrices(e,e2) ; } L = vpMatrix::stackMatrices(L,H1) ; e = vpMatrix::stackMatrices(e,e1) ; } k++ ; } if (userobust) { robust.setIteration(0); for (unsigned int k=0 ; k < n ; k++) { res[k] = vpMath::sqr(e[2*k]) + vpMath::sqr(e[2*k+1]) ; } robust.MEstimator(vpRobust::TUKEY, res, w); // compute the pseudo inverse of the interaction matrix for (unsigned int k=0 ; k < n ; k++) { W[2*k][2*k] = w[k] ; W[2*k+1][2*k+1] = w[k] ; } } else { for (unsigned int k=0 ; k < 2*n ; k++) W[k][k] = 1 ; } (W*L).pseudoInverse(Lp, 1e-16) ; // Compute the camera velocity vpColVector c2Tcc1 ; c2Tcc1 = -1*Lp*W*e ; // only for simulation c2Mc1 = vpExponentialMap::direct(c2Tcc1).inverse()*c2Mc1 ; ; // UpdatePose2(c2Tcc1, c2Mc1) ; r =(W*e).sumSquare() ; if (r < 1e-15) {break ; } if (iter>1000){break ; } if (r>r_1) { break ; } iter++ ; } return (W*e).sumSquare() ; }
AbstractBuffer<int32_t> ADCensus::constructDisparityMap(const AbstractBuffer<pixel> *leftImage, const AbstractBuffer<pixel> *rightImage, const AbstractBuffer<grayPixel> *leftGrayImage, const AbstractBuffer<grayPixel> *rightGrayImage) { // Initialization int width = leftImage->w; int height = leftImage->h; BaseTimeStatisticsCollector collector; Statistics outerStats; outerStats.setValue("H", height); outerStats.setValue("W", width); AbstractBuffer<int32_t> bestDisparities = AbstractBuffer<int32_t>(height, width); AbstractBuffer<COST_TYPE> minCosts = AbstractBuffer<COST_TYPE>(height, width); minCosts.fillWith(-1); // Disparity computation outerStats.startInterval(); AbstractBuffer<int64_t> leftCensus = AbstractBuffer<int64_t>(height, width); AbstractBuffer<int64_t> rightCensus = AbstractBuffer<int64_t>(height, width); makeCensus(leftGrayImage, leftCensus); makeCensus(rightGrayImage, rightCensus); outerStats.resetInterval("Making census"); makeAggregationCrosses(leftImage); outerStats.resetInterval("Making aggregation crosses"); for (uint i = 0; i < CORE_COUNT_OF(table1); i++) { table1[i] = robust(i, lambdaCT); table2[i] = robust(i, lambdaAD); } bool parallelDisp = true; parallelable_for(0, width / 3, [this, &minCosts, &bestDisparities, &leftImage, &rightImage, &leftCensus, &rightCensus, &collector, height, width, parallelDisp](const BlockedRange<int> &r) { for (int d = r.begin(); d != r.end(); ++d) { Statistics stats; stats.startInterval(); AbstractBuffer<COST_TYPE> costs = AbstractBuffer<COST_TYPE>(height, width); stats.resetInterval("Matrix construction"); parallelable_for(windowHh, height - windowHh, [this, &costs, &leftImage, &rightImage, &leftCensus, &rightCensus, d, width](const BlockedRange<int> &r) { for (int y = r.begin(); y != r.end(); ++y) { auto *im1 = &leftImage->element(y, windowWh + d); auto *im2 = &rightImage->element(y, windowWh); int64_t *cen1 = &leftCensus.element(y, windowWh + d); int64_t *cen2 = &rightCensus.element(y, windowWh); int x = windowWh + d; #ifdef WITH_SSE for (; x < width - windowWh; x += 8) { FixedVector<Int16x8, 4> c1 = SSEReader8BBBB_DDDD::read((uint32_t *)im1); FixedVector<Int16x8, 4> c2 = SSEReader8BBBB_DDDD::read((uint32_t *)im2); UInt16x8 dr = SSEMath::difference(UInt16x8(c1[RGBColor::FIELD_R]), UInt16x8(c2[RGBColor::FIELD_R])); UInt16x8 dg = SSEMath::difference(UInt16x8(c1[RGBColor::FIELD_G]), UInt16x8(c2[RGBColor::FIELD_G])); UInt16x8 db = SSEMath::difference(UInt16x8(c1[RGBColor::FIELD_B]), UInt16x8(c2[RGBColor::FIELD_B])); UInt16x8 ad = (dr + dg + db) >> 2; Int16x8 cost_ad = Int16x8(robustLUTAD(ad[0]), robustLUTAD(ad[1]), robustLUTAD(ad[2]), robustLUTAD(ad[3]), robustLUTAD(ad[4]), robustLUTAD(ad[5]), robustLUTAD(ad[6]), robustLUTAD(ad[7])); Int64x2 cen10(&cen1[0]); Int64x2 cen12(&cen1[2]); Int64x2 cen14(&cen1[4]); Int64x2 cen16(&cen1[6]); Int64x2 cen20(&cen2[0]); Int64x2 cen22(&cen2[2]); Int64x2 cen24(&cen2[4]); Int64x2 cen26(&cen2[6]); Int64x2 diff0 = cen10 ^ cen20; Int64x2 diff2 = cen12 ^ cen22; Int64x2 diff4 = cen14 ^ cen24; Int64x2 diff6 = cen16 ^ cen26; Int16x8 cost_ct(robustLUTCen(_mm_popcnt_u64(diff0.getInt(0))), robustLUTCen(_mm_popcnt_u64(diff0.getInt(1))), robustLUTCen(_mm_popcnt_u64(diff2.getInt(0))), robustLUTCen(_mm_popcnt_u64(diff2.getInt(1))), robustLUTCen(_mm_popcnt_u64(diff4.getInt(0))), robustLUTCen(_mm_popcnt_u64(diff4.getInt(1))), robustLUTCen(_mm_popcnt_u64(diff6.getInt(0))), robustLUTCen(_mm_popcnt_u64(diff6.getInt(1)))); Int16x8 cost_total = cost_ad + cost_ct; for (int i = 0; i < 8; ++i) { costs.element(y, x + i) = cost_total[i]; } im1 += 8; im2 += 8; cen1+= 8; cen2+= 8; } #else for (; x < width - windowWh; ++x) { uint8_t c_ad = costAD(*im1, *im2); uint8_t c_census = hammingDist(*cen1, *cen2); costs.element(y, x) = robustLUTCen(c_census) + robustLUTAD(c_ad); im1 ++; im2 ++; cen1++; cen2++; } #endif } }, !parallelDisp ); stats.resetInterval("Cost computation"); aggregateCosts(&costs, windowWh + d, windowHh, width - windowWh, height - windowHh); stats.resetInterval("Cost aggregation"); for (int x = windowWh + d; x < width - windowWh; ++x) { for (int y = windowHh; y < height - windowHh; ++y) { tbb::mutex::scoped_lock(bestDisparitiesMutex); if(costs.element(y, x) < minCosts.element(y, x)) { minCosts.element(y, x) = costs.element(y, x); bestDisparities.element(y, x) = d; //result.element(y,x) = (bestDisparities.element(y, x) / (double)width * 255 * 3); } } } //BMPLoader().save("../../result.bmp", result); stats.endInterval("Comparing with previous minimum"); collector.addStatistics(stats); } }, parallelDisp);