2013-06-10 31 views
5

Libs: OpenCV docelowa: Android (OpenCV4Android)Android & OpenCV: Homography do kamery Pose rozważa Camera intrinsics i Backprojection

próbuję obliczyć Homography samolotu świata (np ekranem monitora), aby aparat pozy , przekształć go i zreorganizuj punkty za zadania śledzenia. Używam OpenCVs findHomography()/getPerspectiveTransform(), aby uzyskać homografię. Reprojection punktów przy użyciu perspectiveTransform() (jak wyjaśniono tutaj: http://docs.opencv.org/doc/tutorials/features2d/feature_homography/feature_homography.html), który działa całkiem dobrze. "Punkty ekranu" to współrzędne światowe krawędzi monitora (przy użyciu współczynnika kształtu i wartości z równej 0), a "punkty obrazu" to współrzędne X/Y krawędzi ekranu na obrazie.

Mat homography = org.opencv.imgproc.Imgproc.getPerspectiveTransform(screenPoints, imagePoints); 

mam macierz kalibracji kamery (Użyłem przybornik kalibracji Matlab) i znalazłem podpowiedź (w komentarzach) dla @https://dsp.stackexchange.com/questions/2736/step-by-step-camera-pose-estimation-for-visual-tracking-and-planar-markers rozważa parametry kamery w homography.

H '= k^-1 * H

(H' - Homography matrycą za kalibracji aparatu, H - Homography matrycą K^-1 - odwrotna aparat matryca kalibracji).

Mat intrinsicInverse = new Mat(3, 3, CvType.CV_32FC1); 
Core.invert(intrinsic, intrinsicInverse); 
intrinsicInverse.convertTo(intrinsicInverse, CvType.CV_32FC1);   
homography.convertTo(homography, CvType.CV_32FC1); 
// compute H respect the intrinsics 
Core.gemm(intrinsicInverse, homography, 1, new Mat(), 0, homography); 

Moim następnym krokiem ist obliczyć aparatu stanowią od homography jak opisano tutaj Computing camera pose with homography matrix based on 4 coplanar points.

Ponieważ im próbuje to zrobić na Androida miałem do portu C++ kod Java:

private Mat cameraPoseFromHomography(Mat h) { 
    Log.d("DEBUG", "cameraPoseFromHomography: homography " + matToString(h)); 

    Mat pose = Mat.eye(3, 4, CvType.CV_32FC1); // 3x4 matrix, the camera pose 
    float norm1 = (float) Core.norm(h.col(0)); 
    float norm2 = (float) Core.norm(h.col(1)); 
    float tnorm = (norm1 + norm2)/2.0f;  // Normalization value 

    Mat normalizedTemp = new Mat(); 
    Core.normalize(h.col(0), normalizedTemp); 
    normalizedTemp.convertTo(normalizedTemp, CvType.CV_32FC1); 
    normalizedTemp.copyTo(pose.col(0)); 

    Core.normalize(h.col(1), normalizedTemp); 
    normalizedTemp.convertTo(normalizedTemp, CvType.CV_32FC1);  
    normalizedTemp.copyTo(pose.col(1)); 

    Mat p3 = pose.col(0).cross(pose.col(1)); 
    p3.copyTo(pose.col(2)); 

    Mat temp = h.col(2); 
    double[] buffer = new double[3]; 
    h.col(2).get(0, 0, buffer); 
    pose.put(0, 3, buffer[0]/tnorm); 
    pose.put(1, 3, buffer[1]/tnorm); 
    pose.put(2, 3, buffer[2]/tnorm); 

    return pose; 
} 

nie mogę sprawdzić, czy kod jest robienie właściwych rzeczy, ale to działa. W tym momencie zakładam, że mam pełną kamerę, biorąc pod uwagę kalibrację aparatu.

Jak opisano tutaj http://opencv.willowgarage.com/documentation/python/calib3d_camera_calibration_and_3d_reconstruction.html#rodrigues2, ponownego odwzorowania z 3D-punkt jest tylko

P = K * CP * P

(p - 2D pozycja, K - matryca kalibracji CP - kamera stanowią, P - 3D-Point)

Core.gemm(intrinsic, cameraPosition, 1, new Mat(), 0, vec4t); 
    Core.gemm(vec4t, point, 1, new Mat(), 0, result); 

Wynik jest daleko od położenia obrazu źródłowego krawędzi ekranu. Ale mogę zidentyfikować wszystkie trzy krawędzie przez ich względne różnice - może to być po prostu jakiś czynnik, który jest nieprawidłowy.

Po raz pierwszy wykonuję zadanie Computer Vision i możliwe, że zrobiłem coś złego. Mam książkę "Wielokrotny widok geometrii" od Zissermana i czytam wszystkie powiązane części - ale szczerze mówiąc - nie dostałem większości.

UPDATE:

Znalazłeś błąd w moim matrycy aparatu - realizacja powyżej jest po prostu działa bez zarzutu!

Odpowiedz

1

Spraw, aby działał w inny sposób. Zamiast użycia findHomography()/getP erspectiveTransform() znalazłem inną funkcję nazwaną solvePnP(), która zwraca pozę kamery w oparciu o punkty świata i obrazy oraz wewnętrzną matrycę kamery.

Używanie tej funkcji w połączeniu z metodą projectPoints() - udało mi się zreorganizować punkty 3D z powrotem na obraz.

W przypadku krawędzi ekranu są one umieszczane we właściwym miejscu na obrazie.

UPDATE:

Znalazłem błąd w moim realizacji - moja kamera wewnętrzna matryca myliłem. Aparat fotograficzny z powyższej implementacji homografii pracuje dla mnie!

0

Zależność pomiędzy Homography kalibrowanych przypadku (H) i kalibracją przypadku (H ') jest

H' =^(- 1), gdzie K jest wewnętrzna matryca kamery.