opencv与eigen之间svd求解的精度差

我发现opencv和eigen之间的求解函数的精度有很大的不同,你可以看到下面的代码

    double A[12 * 12] = { 898985.9229685856, 810318.7228193029, 249750.0195282509, 528092.128827526, 487356.910038895, 231454.1507723731, 437677.8880533592, 416653.697583782, 71739.31443597845, 456513.7847810316, 475693.5967964944, 113008.8509444033,
    810318.7228193029, 731529.6132012453, 201025.6334517392, 482023.4868692894, 447119.3251370092, 188584.2175010706, 394540.4278552125, 375582.5118748858, 50543.93199966016, 415596.6971863336, 433437.3514379457, 94116.58744947071,
    249750.0195282509, 201025.6334517392, 581751.6321730034, 18742.96053231739, -31137.91232132711, 490535.2601782645, 120939.6922512043, 115255.7328472394, 320224.5505249942, 39443.19696976502, 33020.93417446916, 196138.8430646659,
    528092.128827526, 482023.4868692893, 18742.96053231741, 358348.0948335672, 338842.7543471307, 76037.04780626712, 234367.9735641981, 223090.3304699353, -8760.543687205402, 274535.545818369, 285524.4758569343, 80540.85580493197,
    487356.910038895, 447119.3251370092, -31137.91232132709, 338842.7543471307, 325763.4643619889, 18480.58018783665, 221961.6324282217, 211266.7978596656, -42375.38294785233, 265406.9968108685, 277446.2235289829, 45207.43173131952,
    231454.150772373, 188584.2175010706, 490535.2601782645, 76037.04780626709, 18480.58018783663, 548070.3877931313, 46238.44492339531, 44155.08497533086, 337630.3299142077, 351.2480468719641, -13731.6950460632, 325288.1347849321,
    437677.8880533592, 394540.4278552125, 120939.6922512043, 234367.9735641981, 221961.6324282217, 46238.44492339532, 245524.657428636, 233714.1474336621, 412.086628163318, 244266.640171457, 258170.073182061, -23519.29952320445,
    416653.697583782, 375582.5118748858, 115255.7328472395, 223090.3304699353, 211266.7978596656, 44155.08497533087, 233714.1474336621, 222471.8341149957, 483.2438551969496, 232500.8417781408, 245731.272583056, -22309.42085945132,
    71739.31443597844, 50543.93199966014, 320224.5505249942, -8760.543687205418, -42375.38294785234, 337630.3299142077, 412.0866281633072, 483.2438551969392, 217641.4297366303, -37825.53457107001, -47970.23615025294, 187995.8693692561,
    456513.7847810316, 415596.6971863336, 39443.19696976504, 274535.545818369, 265406.9968108685, 351.2480468719775, 244266.6401714571, 232500.8417781408, -37825.53457107, 261509.3967302362, 276325.4609223044, -23587.43800500009,
    475693.5967964944, 433437.3514379457, 33020.93417446917, 285524.4758569343, 277446.2235289829, -13731.69504606319, 258170.073182061, 245731.272583056, -47970.23615025293, 276325.4609223044, 292458.6980138036, -35943.31654406196,
    113008.8509444033, 94116.5874494707, 196138.8430646659, 80540.85580493195, 45207.43173131951, 325288.1347849321, -23519.29952320446, -22309.42085945133, 187995.8693692561, -23587.4380050001, -35943.31654406197, 256325.4886444691 };

double b[12 * 6] = { 1.135079963815199, -1.737008760023347e-005, -1.14788672186087, -22.15035032134063, 80.44698779557288, -21.9044398612078,
1.135077990281113, -1.845456006272884e-005, -0.9222106124115483, -17.7954021039541, 72.52178834764608, -21.9044398612078,
-1.493421873708686e-005, 1.135103367834827, -0.6307958223686835, -52.30973095054119, 22.15130554587545, 39.8620292075595,
1.235845498708259, -3.116928113028713e-005, -0.3509833812973479, -9.08646721529038, 43.12878444390064, -31.9981378393477,
1.235844929784385, -3.289413175093619e-005, -0.08346396070754115, -2.1599364566006, 40.84412486730294, -31.9981378393477,
-3.291740615644716e-006, 1.235845799915359, -0.9982564680214177, -65.97769587560578, 8.525096960966657, 10.55432400649275,
0.8990040835087663, 1.144108143631186e-007, -0.322034488532175, 0.04286635122543141, 45.08359484639355, 0.1196833652035621,
0.8990035434689417, 1.191027056361307e-007, -0.180469502605382, 0.02402003540629786, 42.9149331156856, 0.1196833652035617,
-7.046210792377509e-006, 0.8990173056539426, -0.005065514372970498, -40.15025106099804, 0.07728343449092763, 13.77207569783806,
1.028354260299575, -1.313079778231854e-005, 0.3438783854746975, 3.892891490934206, 44.88018590728826, -11.63981671994761,
1.028354895561602, -1.365289948496125e-005, 0.529105125915579, 5.989502873601374, 47.43122255444317, -11.63981671994761,
6.210090856467627e-006, 1.028333179606735, -0.3078563491362242, -43.62798410447173, -4.239671501778426, -14.16265926892159 };

/*
result = [-0.3590091098466054, -0.2265165744326622, 0.01717656346097791, 0.5925151293267734, 0.3509174872152348, 0.2456871592707213, 0.1622287407242721, 0.2500
791264886463, 0.2033894125653286, -0.07122942870906308, -0.2952635103576415, -0.492024034978804;
-0.2350541486812541, -0.1631381236829929, 0.2446580238447737, -0.7939179358198095, 0.08337043590980134, -0.3207435534863135, 1.010984099672061, 0.42
32983599087659, -1.112052360999286, -0.003429670256903591, 0.04297456068134826, 1.56904181093309;
0.06708744915391682, 0.03587620808428434, -0.07759876975349278, 0.07247114387611006, -0.1008247375172606, -0.03055769157499982, -0.4750233421936581,
-0.2453739988700771, 0.4965936432148034, 0.2109896294043406, 0.3392221906587455, -0.3117577169611102;
-9.09563175737799e-005, -6.232535991446612e-005, 8.12687324308835e-005, -0.0003022468842891383, 3.154184323186795e-005, -0.0001564353276422826, 0.00
04422578812696253, 0.0001997794636752549, -0.0004997507498655659, -3.146488432258052e-005, -3.530563529583033e-005, 0.0005351753830485212;
0.000122850932271772, 8.212400770240413e-005, 2.353583368561539e-005, -0.0001868222170033518, -0.0001050342946687456, -9.095309985099905e-005, -2.42
164304110927e-005, -4.991521136359495e-005, -5.485452282674233e-005, 5.633195273334225e-005, 0.0001329856037697007, 0.000131280897795553;
-5.514058081983523e-005, -4.0569097208618e-005, 8.192064620546867e-005, 6.572562871389357e-005, -1.016124554143165e-006, 4.13356787566465e-005, 3.08
9666793197444e-005, 6.150073284094459e-005, 7.418838591118405e-005, -8.436798102190297e-006, -4.448959219084568e-005, -0.0002048998397820362]
*/
Mat cvAd(12, 12, CV_64FC1, A);
Mat cvbd(12, 6, CV_64FC1, b);
Mat cvAf, cvbf;
Mat cvxf, cvxd;
cvAd.convertTo(cvAf, CV_32FC1);
cvbd.convertTo(cvbf, CV_32FC1);

cv::solve(cvAd, cvbd, cvxd, DECOMP_SVD);
cv::solve(cvAf, cvbf, cvxf, DECOMP_SVD);


MatrixXd eigenxd,eigenxd1,eigenxd2;
MatrixXf eigenxf;
Eigen::Map<MatrixXd> eigenAd(A,12,12);
Eigen::Map<MatrixXd> eigenbd(b,12,6);

MatrixXf eigenAf = eigenAd.cast<float>();
MatrixXf eigenbf = eigenbd.cast<float>();

eigenxd = eigenAd.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(eigenbd);
eigenxf = eigenAf.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(eigenbf);

eigenxd1 = eigenAd.ldlt().solve(eigenbd);
eigenxd2 = eigenAd.llt().solve(eigenbd);

cout << "cvxd" << endl << cvbd - cvAd*cvxd << endl << "==================="<<endl;
cout << "cvxf" << endl << cvbf - cvAf*cvxf << endl << "===================" << endl;
cout << "eigenxd" << endl << eigenbd - eigenAd*eigenxd << endl << "===================" << endl;
cout << "eigenxf" << endl << eigenbf - eigenAf*eigenxf << endl << "===================" << endl;
cout << "eigenxd1" << endl << eigenbd - eigenAd*eigenxd1 << endl << "===================" << endl;
cout << "eigenxd2" << endl << eigenbd - eigenAd*eigenxd2 << endl << "===================" << endl;

你可以测试上面的代码,发现opencv的双精度具有最好的精度,那么eigen的错误是可怕的,谁能告诉我为什么? 🙂

enter image description here

最佳答案 您的地图设置错误(它假定列主要存储顺序,而“矩阵”A和b实际上是行主要顺序).如果您在Eigen矩阵中输入值,您将得到正确的结果:

    MatrixXd eigenAd(12, 12);
    eigenAd <<
        898985.9229685856, 810318.7228193029, 249750.0195282509, 528092.128827526, 487356.910038895, 231454.1507723731, 437677.8880533592, 416653.697583782, 71739.31443597845, 456513.7847810316, 475693.5967964944, 113008.8509444033,
        810318.7228193029, 731529.6132012453, 201025.6334517392, 482023.4868692894, 447119.3251370092, 188584.2175010706, 394540.4278552125, 375582.5118748858, 50543.93199966016, 415596.6971863336, 433437.3514379457, 94116.58744947071,
        249750.0195282509, 201025.6334517392, 581751.6321730034, 18742.96053231739, -31137.91232132711, 490535.2601782645, 120939.6922512043, 115255.7328472394, 320224.5505249942, 39443.19696976502, 33020.93417446916, 196138.8430646659,
        528092.128827526, 482023.4868692893, 18742.96053231741, 358348.0948335672, 338842.7543471307, 76037.04780626712, 234367.9735641981, 223090.3304699353, -8760.543687205402, 274535.545818369, 285524.4758569343, 80540.85580493197,
        487356.910038895, 447119.3251370092, -31137.91232132709, 338842.7543471307, 325763.4643619889, 18480.58018783665, 221961.6324282217, 211266.7978596656, -42375.38294785233, 265406.9968108685, 277446.2235289829, 45207.43173131952,
        231454.150772373, 188584.2175010706, 490535.2601782645, 76037.04780626709, 18480.58018783663, 548070.3877931313, 46238.44492339531, 44155.08497533086, 337630.3299142077, 351.2480468719641, -13731.6950460632, 325288.1347849321,
        437677.8880533592, 394540.4278552125, 120939.6922512043, 234367.9735641981, 221961.6324282217, 46238.44492339532, 245524.657428636, 233714.1474336621, 412.086628163318, 244266.640171457, 258170.073182061, -23519.29952320445,
        416653.697583782, 375582.5118748858, 115255.7328472395, 223090.3304699353, 211266.7978596656, 44155.08497533087, 233714.1474336621, 222471.8341149957, 483.2438551969496, 232500.8417781408, 245731.272583056, -22309.42085945132,
        71739.31443597844, 50543.93199966014, 320224.5505249942, -8760.543687205418, -42375.38294785234, 337630.3299142077, 412.0866281633072, 483.2438551969392, 217641.4297366303, -37825.53457107001, -47970.23615025294, 187995.8693692561,
        456513.7847810316, 415596.6971863336, 39443.19696976504, 274535.545818369, 265406.9968108685, 351.2480468719775, 244266.6401714571, 232500.8417781408, -37825.53457107, 261509.3967302362, 276325.4609223044, -23587.43800500009,
        475693.5967964944, 433437.3514379457, 33020.93417446917, 285524.4758569343, 277446.2235289829, -13731.69504606319, 258170.073182061, 245731.272583056, -47970.23615025293, 276325.4609223044, 292458.6980138036, -35943.31654406196,
        113008.8509444033, 94116.5874494707, 196138.8430646659, 80540.85580493195, 45207.43173131951, 325288.1347849321, -23519.29952320446, -22309.42085945133, 187995.8693692561, -23587.4380050001, -35943.31654406197, 256325.4886444691;
    MatrixXd eigenbd(12, 6);
    eigenbd <<
        1.135079963815199, -1.737008760023347e-005, -1.14788672186087, -22.15035032134063, 80.44698779557288, -21.9044398612078,
        1.135077990281113, -1.845456006272884e-005, -0.9222106124115483, -17.7954021039541, 72.52178834764608, -21.9044398612078,
        -1.493421873708686e-005, 1.135103367834827, -0.6307958223686835, -52.30973095054119, 22.15130554587545, 39.8620292075595,
        1.235845498708259, -3.116928113028713e-005, -0.3509833812973479, -9.08646721529038, 43.12878444390064, -31.9981378393477,
        1.235844929784385, -3.289413175093619e-005, -0.08346396070754115, -2.1599364566006, 40.84412486730294, -31.9981378393477,
        -3.291740615644716e-006, 1.235845799915359, -0.9982564680214177, -65.97769587560578, 8.525096960966657, 10.55432400649275,
        0.8990040835087663, 1.144108143631186e-007, -0.322034488532175, 0.04286635122543141, 45.08359484639355, 0.1196833652035621,
        0.8990035434689417, 1.191027056361307e-007, -0.180469502605382, 0.02402003540629786, 42.9149331156856, 0.1196833652035617,
        -7.046210792377509e-006, 0.8990173056539426, -0.005065514372970498, -40.15025106099804, 0.07728343449092763, 13.77207569783806,
        1.028354260299575, -1.313079778231854e-005, 0.3438783854746975, 3.892891490934206, 44.88018590728826, -11.63981671994761,
        1.028354895561602, -1.365289948496125e-005, 0.529105125915579, 5.989502873601374, 47.43122255444317, -11.63981671994761,
        6.210090856467627e-006, 1.028333179606735, -0.3078563491362242, -43.62798410447173, -4.239671501778426, -14.16265926892159;

    eigenxd = eigenAd.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(eigenbd);

    cout << "eigenxd" << endl << eigenbd - eigenAd*eigenxd << endl << "===================" << endl;

得到:

eigenxd
-9.60676e-011 7.37335e-010 -2.61663e-010 2.30926e-013 0 -2.84217e-014
-7.75824e-011 4.98972e-010 -1.82739e-010 2.16716e-013 1.42109e-014 -2.13163e-014
-1.26559e-010 4.49373e-010 -8.63035e-011 1.35003e-013 5.32907e-014 -8.52651e-014
-3.24141e-011 4.11972e-010 -1.60591e-010 1.45661e-013 3.55271e-014 7.10543e-015
3.08733e-011 3.85311e-010 -6.56479e-011 8.61533e-014 1.42109e-014 0
-1.55599e-010 6.6456e-011 -1.10498e-011 2.84217e-014 4.26326e-014 -6.92779e-014
-2.91087e-011 3.38351e-010 -1.00066e-010 1.15838e-013 3.55271e-014 -2.90323e-014
-3.82642e-011 3.37249e-010 -7.60052e-011 9.88445e-014 2.84217e-014 -2.85466e-014
-5.70235e-011 7.49061e-011 -1.58936e-012 3.55271e-014 4.84335e-015 -2.30926e-014
1.67075e-011 2.68443e-010 -5.97834e-011 7.99361e-014 -2.13163e-014 -1.42109e-014
-1.21549e-010 4.20426e-010 -8.72535e-011 1.81188e-013 1.42109e-014 -2.13163e-014
3.19289e-011 -4.59559e-011 -2.17792e-011 2.13163e-014 -1.77636e-015 3.55271e-015

另一种方法是使用RowMajor矩阵(Eigen :: Map< Matrix< double,-1,-1,Eigen :: RowMajor>>)代替,即

Eigen::Map<Matrix<double, -1, -1, Eigen::RowMajor>> eigenAd(A,12,12);
点赞