2017-05-23 126 views
0

我在Windows上使用OpenCV 3.1。OpenCV solvePnPRansac

的代码片段:

RNG rng; // random number generator 

cv::Mat rVec = (cv::Mat_<double>(3, 1) << 0.08257, -0.6168, 1.4675); 
cv::Mat tVec = (cv::Mat_<double>(3, 1) << -0.3806, -0.1605, 0.6087); 

for (int i = 0; i < 10000; i++) 
{ 
    rVec.ptr<double>(0)[0] += rng.rand_linear(0.0, 0.5); // mean 0, marin +-0.5 
    rVec.ptr<double>(1)[0] += rng.rand_linear(0.0, 0.5); 
    rVec.ptr<double>(2)[0] += rng.rand_linear(0.0, 0.5); 
    tVec.ptr<double>(0)[0] += rng.rand_linear(0.0, 0.5); 
    tVec.ptr<double>(1)[0] += rng.rand_linear(0.0, 0.5); 
    tVec.ptr<double>(2)[0] += rng.rand_linear(0.0, 0.5); 

    std::cout << rVec.t() << " --> "; 
    bool success = cv::solvePnPRansac(patternPoints3d, imgPoints, camIntrinsics.camMat, camIntrinsics.distCoeffs, rVec, tVec, true, 100, 8.f, 0.99, cv::noArray(), cv::SOLVEPNP_ITERATIVE); 
    std::cout << rVec.t() << std::endl; 
} 

输出是一样的东西:

[-0.2853612945502569, -0.9418475404979531, 1.68440248184304] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[0.1479919034434538, -0.2763278773652259, 1.150822641518221] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[0.0706268803594689, -0.9919233518319074, 1.32315553697224] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[0.3478958481835257, -0.3697621750777457, 1.716206426456824] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[-0.3340069694997688, -0.3675019960516933, 1.51973527339685] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[0.5445069792592954, -0.9075993847234044, 1.259690332649529] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 

所以,无论出发假设的,我得到完全相同的最终结果。

移动的,我减少迭代的次数从100

bool success = cv::solvePnPRansac(patternPoints3d, imgPoints, camIntrinsics.camMat, camIntrinsics.distCoeffs, rVec, tVec, true, 100, 8.f, 0.99, cv::noArray(), cv::SOLVEPNP_ITERATIVE); 

1迭代

​​

相同的结果:

[0.4316089014435242, -0.3745184350425247, 1.000847428296015] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[-0.06206055466029242, -0.6728777329569552, 1.324249691752971] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[-0.2321970797231366, -0.2713987283075098, 1.36880229898195] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[-0.3178144781006445, -0.5075788347182665, 1.912844335384921] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 

此外上,改变从0的置信论据0.99

​​

0.01

bool success = cv::solvePnPRansac(patternPoints3d, imgPoints, camIntrinsics.camMat, camIntrinsics.distCoeffs, rVec, tVec, true, 1, 8.f, 0.01, cv::noArray(), cv::SOLVEPNP_ITERATIVE); 

相同的结果:

[-0.1541070262057652, -0.9795359918514136, 0.9881938066838982] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[-0.09741225946638182, -0.2123314354700837, 1.35100669316414] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[0.4136190534016173, -0.5970452204944435, 1.596524650886908] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 
[-0.1438873709732612, -0.6913048753647003, 1.76558963228415] --> [0.0825705957511495, -0.6167564127260689, 1.467542801941067] 

与内围值,取值同样的事情。这似乎就好像这些论据没有任何区别。结果实际上看起来不错,我只是想更好地理解它。

所以,我的结论是,solvePnPRansac()做同样的事情,无论参数。我究竟做错了什么?

回答

2

不幸的是,当前的(OpenCV的3.2)solvePnPRansac()方法不符合的文档:

  • 它是将要使用的时点的数目是>= 5用于MSS的(最小的样品集)SOLVEPNP_EPNP方法步骤(见here
  • 最终摄影机姿态估计并没有考虑到useExtrinsicGuess(见here

我会努力如果根据文档的预期行为提高了精确度,则可以提交问题并提交请求(如果我有一些时间的话),否则文档必须更改。


不知道理解你的代码:

  • 您生成一个随机的相机姿态rvectvec
  • 但似乎你从来没有更新您的2D图像点(需要使用projectPoints()) ?

您的来电:

bool success = cv::solvePnPRansac(patternPoints3d, imgPoints, camIntrinsics.camMat, camIntrinsics.distCoeffs, rVec, tVec, true, 100, 8.f, 0.99, cv::noArray(), cv::SOLVEPNP_ITERATIVE);

当你看doc,你使用标志SOLVEPNP_ITERATIVE这是一种方法来估计使用迭代优化方案的摄像机姿态,因此需要解决方案的初始估计。

在提供useExtrinsicGuess = true,它将使用参数直接rvectvec,否则会在内部调用另一个方法来获得rvectvec第一估计。

+0

实际上,如果你仔细观察,我会设置'rvec'和'tvec'为算法收敛的值。即使我已经将rvec和tvec设置为零,算法也会收敛到它对于这些给定点始终保持不变的值。 为什么我需要更新图像点?图像点是我在图像上观察到的点。 我想看到的是,对于相同的数据,我应该根据我使用的参数得到稍微不同的结果。但是这没有发生。 – ancajic

+0

我使用'useExtrinsicGuess = true',这样我就可以明确地为迭代算法设置不同的起始位置。确保它以相同的解决方案结束,而不管它从何处开始。 – ancajic

+1

@ancajic好吧,我读得太快对不起。我编辑了我的答案。 – Catree