Byłem skonfrontowany z tym samym problemem co ty, w OpenCV. Miałem parę obrazów stereo i chciałem obliczyć parametry zewnętrzne kamer i współrzędne światowe wszystkich zaobserwowanych punktów. Ten problem został potraktowany tutaj:
Berthold K. P. Horn. Weryfikacja orientacji względnej. Berthold K. P. Horn. Artificial Intelligence Laboratory, Massachusetts Institute of Technology, 545 Technology ...
http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.64.4700
Jednak nie był w stanie znaleźć odpowiedniego wdrożenia tego problemu (być może znajdziesz jeden). Z powodu ograniczeń czasowych nie miałem czasu, aby zrozumieć wszystkie matematyki w tym dokumencie i wdrożyć je samodzielnie, więc wpadłem na szybkie i brudne rozwiązanie, które działa dla mnie. Wyjaśnię, co zrobiłem, aby go rozwiązać:
Zakładając, że mamy dwie kamery, gdzie pierwsza kamera ma zewnętrzne parametry RT = Matx :: eye(). Teraz zgadnij o obrocie R drugiej kamery. Dla każdej pary punktów obrazu obserwowanych na obu obrazach obliczamy kierunki ich odpowiadających promieni we współrzędnych światowych i zapisujemy je w tablicy 2d dirs (EDYCJA: zakłada się, że parametry kamery wewnętrznej są znane). Możemy to zrobić, ponieważ zakładamy, że znamy orientację każdej kamery. Teraz budujemy nadokreślony układ liniowy, gdzie C jest środkiem drugiej kamery. I zapewniają dostęp do funkcji do obliczenia:
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;
}
Potem dzwoni cv :: SVD :: solveZ (A) daje rozwiązanie najmniejszych kwadratów normie 1 do niniejszego układu. W ten sposób uzyskujesz obrót i tłumaczenie drugiej kamery. Jednakże, ponieważ właśnie zgadywałem o rotacji drugiej kamery, poczyniłem kilka domysłów na temat jej rotacji (sparametryzowałem używając omega 3x1, z której obliczyłem macierz rotacji za pomocą cv :: Rodrigues), a następnie sprecyzowałem to przez rozwiązywanie systemu AC = 0 z powtarzaniem w optymalizatorze Levenberga-Marquardta z numerycznym jacobianem. To działa dla mnie, ale jest trochę brudne, więc jeśli masz czas, zachęcam cię do wdrożenia tego, co wyjaśniono w artykule.
EDIT:
Oto rutyna w optymalizator Levenberg-Marquardt oceny wektor pozostałości:
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);
}
Nawiasem mówiąc, szukałem trochę więcej w internecie i znaleźć inny kod, który może być przydatny do obliczenia względnej orientacji między kamerami. Nie próbowałem jeszcze żadnego kodu, ale wydaje się przydatne:
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/
Nie jest jasne, powyżej, jeśli wiemy, że świat 3D współrzędne punktów, które można zaobserwować na różnych obrazach. W takim przypadku jest to problem z punktu widzenia perspektywy i można skalibrować parametry każdej kamery za pomocą algorytmu EPnP dostępnego tutaj: http://cvlab.epfl.ch/software/EPnP/index.php. W przeciwnym razie zobacz moją odpowiedź poniżej. – Rulle
Współrzędne 3D fotografowanego obiektu są nieznane. –
Jeśli światowe współrzędne punktów na obiekcie są niepodobne, nie sądzę, aby cv :: calibrateCamera zadziałało, ponieważ wydaje się, że punkty obiektu są _known_. – Rulle