OpenCV решитьPnPRansac

Я использую OpenCV 3.1 на Windows.

Фрагмент кода:

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 итерация

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

Тот же результат:

[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,99

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

до 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]

То же самое с аргументом inlier порога. Кажется просто, как будто эти аргументы не имеют никакого значения. Результат на самом деле выглядит довольно неплохо, я просто хочу немного лучше его понять.

Итак, мой вывод таков, что solvePnPRansac() делает то же самое, независимо от аргументов. Что я делаю неправильно?

1

Решение

К сожалению, текущий (OpenCV 3.2) solvePnPRansac() Метод не соответствует документации:

  • это SOLVEPNP_EPNP метод, который будет использоваться, когда число точек >= 5 для шага MSS (минимальный набор образцов) (см. Вот)
  • окончательная оценка позы камеры не учитывает useExtrinsicGuess (увидеть Вот)

Я постараюсь представить вопрос и, возможно, запрос на удаление (когда у меня будет некоторое время), если ожидаемое поведение в соответствии с документом повысит точность, в противном случае документация должна быть изменена.


Не уверен, что понимаю ваш код:

  • вы генерируете случайную позу камеры rvec а также tvec
  • но кажется, что вы никогда не обновите точки 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);,

Когда вы смотрите на доктор, вы используете флаг SOLVEPNP_ITERATIVE Это метод оценки позы камеры, который использует итеративную схему оптимизации и, следовательно, нуждается в начальной оценке решения.

При предоставлении useExtrinsicGuess = true, он будет использовать напрямую rvec а также tvec в аргументах, иначе он вызовет внутри себя другой метод, чтобы получить первую оценку rvec а также tvec,

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]