Я столкнулся с той же проблемой, что и вы, в OpenCV.У меня была пара стереоизображений, и я хотел вычислить внешние параметры камер и мировые координаты всех наблюдаемых точек.Эта проблема была рассмотрена здесь:
Бертольд К.П. Хорн.Относительная ориентация вновь.Бертольд К.П. Хорн.Лаборатория искусственного интеллекта, Массачусетский технологический институт, 545 Технология ...
http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.64.4700
Однако я не смог найти подходящее решение этой проблемы (возможно, вы найдете один).Из-за нехватки времени у меня не было времени, чтобы разобраться во всей математике в этой статье и реализовать ее самостоятельно, поэтому я нашел быстрое и грязное решение, которое работает для меня.Я объясню, что я сделал, чтобы решить эту проблему:
Предполагая, что у нас есть две камеры, где первая камера имеет внешние параметры RT = Matx :: eye () .Теперь сделайте предположение о вращении R второй камеры.Для каждой пары точек изображения, наблюдаемых на обоих изображениях, мы вычисляем направления их соответствующих лучей в мировых координатах и сохраняем их в 2d-массиве dirs (РЕДАКТИРОВАТЬ: предполагается, что внутренние параметры камеры известны),Мы можем сделать это, так как предполагаем, что знаем ориентацию каждой камеры.Теперь мы строим переопределенную линейную систему AC = 0 , где C - центр второй камеры.Я предоставляю вам функцию для вычисления A:
Mat buildA(Matx<double, 3, 3> &R, Array<Vec3d, 2> dirs)
{
CV_Assert(dirs.size(0) == 2);
int pointCount = dirs.size(1);
Mat A(pointCount, 3, DataType<double>::type);
Vec3d *a = (Vec3d *)A.data;
for (int i = 0; i < pointCount; i++)
{
a[i] = dirs(0, i).cross(toVec(R*dirs(1, i)));
double length = norm(a[i]);
if (length == 0.0)
{
CV_Assert(false);
}
else
{
a[i] *= (1.0/length);
}
}
return A;
}
Затем вызов cv :: SVD :: solveZ (A) даст вам решение нормы 1 для наименьших квадратовсистема.Таким образом, вы получаете вращение и перевод второй камеры.Однако, поскольку я только что сделал предположение о вращении второй камеры, я делаю несколько предположений о ее вращении (параметризованный с использованием вектора омега 3x1, из которого я вычисляю матрицу вращения с помощью cv :: Rodrigues), а затем уточняю этоРешение системы AC = 0 повторяется в оптимизаторе Левенберга-Марквардта с числовым якобианом.Это работает для меня, но это немного грязно, поэтому, если у вас есть время, я призываю вас реализовать то, что объясняется в статье.
РЕДАКТИРОВАТЬ:
Вот процедура в оптимизаторе Левенберга-Марквардта для оценки вектора остатков:
void Stereo::eval(Mat &X, Mat &residues, Mat &weights)
{
Matx<double, 3, 3> R2Ref = getRot(X); // Map the 3x1 euler angle to a rotation matrix
Mat A = buildA(R2Ref, _dirs); // Compute the A matrix that measures the distance between ray pairs
Vec3d c;
Mat cMat(c, false);
SVD::solveZ(A, cMat); // Find the optimum camera centre of the second camera at distance 1 from the first camera
residues = A*cMat; // Compute the output vector whose length we are minimizing
weights.setTo(1.0);
}
Кстати, я немного поискал в Интернете и нашел другой код, который может быть полезен для вычисленияотносительная ориентация между камерами.Я еще не пробовал код, но он кажется полезным:
http://www9.in.tum.de/praktika/ppbv.WS02/doc/html/reference/cpp/toc_tools_stereo.html
http://lear.inrialpes.fr/people/triggs/src/
http://www.maths.lth.se/vision/downloads/