12

W jaki sposób mogę pobrać macierz obrotu, wektor translacji i może niektóre współczynniki skalowania każdej kamery za pomocą OpenCV, gdy mam zdjęcia obiektu z widoku każdej z tych kamer? Dla każdego obrazu mam współrzędne obrazu kilku punktów charakterystycznych. Nie wszystkie punkty są widoczne na wszystkich zdjęciach. Chcę odwzorować obliczone współrzędne 3D punktów charakterystycznych obiektu na nieco inny obiekt, aby wyrównać kształt drugiego obiektu do pierwszego obiektu.Zewnętrzna kamera OpenCV z punktów charakterystycznych

Słyszałem, że jest to możliwe przy użyciu cv::calibrateCamera(...) ale nie mogę dostać całkiem przez niego ...

Czy ktoś ma doświadczenia z tego rodzaju problem?

+0

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

+1

Współrzędne 3D fotografowanego obiektu są nieznane. –

+0

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

Odpowiedz

11

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/

+0

Dziękuję bardzo za odpowiedź. Myślę, że rozumiem, co napisałeś i kodowałeś, a to pomoże mi znaleźć rozwiązanie mojego problemu. Jednak uważam, że 'cv :: calibrateCamera (...)' działa całkiem podobnie do tego, co zaproponowałeś. Opisują algorytm w następujący sposób: –

+0

1. Najpierw oblicza początkowe parametry wewnętrzne (opcja dostępna tylko dla wzorów kalibracji planarnych) lub odczytuje je z parametrów wejściowych. Współczynniki zniekształceń są początkowo ustawione na zera (chyba że podano niektóre wartości CV_CALIB_FIX_K?). 2. Początkowa pozycja kamery jest szacowana tak, jakby wewnętrzne parametry były już znane. Odbywa się to za pomocą FindExtrinsicCameraParams2 –

+0

3. Następnie uruchamia się globalny algorytm optymalizacji Levenberga-Marquardta, aby zminimalizować błąd reprojection, tj. Całkowitą sumę kwadratów odległości między obserwowanymi punktami punktów obrazu a rzutowanym (przy użyciu bieżących szacunków parametrów kamery i pozy) punkty obiektu objectPoints; zobacz ProjectPoints2. –

2

Czy są to statyczne kamery, które chcesz skalibrować do wykorzystania w przyszłości jako parę stereo? W takim przypadku należy użyć funkcji cv::stereoCalibrate(). OpenCV zawiera przykładowy kod, z których jeden to stereo_calib.cpp, który warto zbadać.

+0

Dzięki za odpowiedź, ale nie jestem zainteresowany wykorzystaniem pary stereo. Mam jedną kamerę, która służy do oglądania tego samego obiektu z różnych stron. Następnie punkty charakterystyczne zaznaczone na każdym zdjęciu powinny pomóc mi w obliczeniu nowych pozycji dla odpowiednich punktów wirtualnego obiektu, który ma zostać nieco zdeformowany. Obiekt wirtualny powinien następnie mieć dokładną geometrię jako rzeczywisty obiekt, który został sfotografowany. BTW 'cv :: calibrateCamera (...)' używa 'cv :: stereoCalibrate()' w postępie obliczeń. –

+0

Ok, czy twoja kamera jest skalibrowana (np. Czy znasz parametry wewnętrzne - długość ogniskową, pochylenie piksela, punkt zasadniczy, współczynniki zniekształcenia)? – Chris

+0

Mogę je oszacować, ale rzeczywiste wartości są nieznane. –

Powiązane problemy