2013-06-10 16 views
5

Libs: OpenCV Obiettivo: Android (OpenCV4Android)Android & OpenCV: omografia alla Camera Pose considerare Camera Intrinsics e retroproiezione

cerco di calcolare l'omografia di un aereo mondo (ad esempio monitor) per ottenere la fotocamera posa , trasformalo e riproietta i punti per le attività di monitoraggio. Sto usando OpenCVs findHomography()/getPerspectiveTransform() per ottenere l'omografia. La riproiezione dei punti usando perspectiveTransform() (come spiegato qui: http://docs.opencv.org/doc/tutorials/features2d/feature_homography/feature_homography.html) che funziona piuttosto bene. Gli "screenpoints" sono le coordinate del mondo dei bordi del monitor (utilizzando il rapporto di aspetto e un valore z di 0) e i "punti immagine" sono le coordinate x/y dei bordi dello schermo nell'immagine.

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

ho la matrice di calibrazione fotocamera (ho usato il toolbox MATLAB calibrazione) e ho trovato un suggerimento (nei commenti @https://dsp.stackexchange.com/questions/2736/step-by-step-camera-pose-estimation-for-visual-tracking-and-planar-markers) per ritenere i parametri della telecamera in omografia.

H '= K^-1 * H

(H' - omografia-Matrix considerando calibrazione della telecamera, H - omografia-Matrix, K^-1 - matrice inversa calibrazione della telecamera).

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); 

Il mio prossimo passo ist per calcolare la fotocamera posa da omografia come misura descritto qui Computing camera pose with homography matrix based on 4 coplanar points.

Dal momento che im cercando di fare questo su Android ho dovuto porto del codice C++ a 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; 
} 

non posso controllare se il codice sta facendo la cosa giusta, ma è in esecuzione. A questo punto presumo di avere la posa della fotocamera completa considerando la calibrazione della telecamera.

Come descritto qui http://opencv.willowgarage.com/documentation/python/calib3d_camera_calibration_and_3d_reconstruction.html#rodrigues2, la riproiezione di un 3D-punto è proprio

p = K * CP * P

(p - 2D-Position, K - matrice di calibrazione, CP - fotocamera posa, P - 3D-Point)

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

Il risultato è lontano dalle posizioni dell'immagine sorgente dei bordi dello schermo. Ma posso identificare tutti e tre gli spigoli con le relative differenze - quindi potrebbe essere solo un fattore che è sbagliato.

È la prima volta che eseguo un tale compito di Computer Vision ed è possibile che abbia fatto qualcosa di sostanzialmente sbagliato. Ho il libro "Multiple View Geometry" di Zisserman e ho letto tutte le parti correlate - ma ad essere onesti - non ne ho avuto la maggior parte.

UPDATE:

Trovato un bug nella mia matrice di macchina fotografica - l'attuazione di cui sopra è solo lavorando bene!

risposta

1

Farlo funzionare in un altro modo. Invece di usare findHomography()/getP erspectiveTransform() ho trovato un'altra funzione chiamata solvePnP() che restituisce la posa della telecamera basata su punti di mondo e immagini e una matrice di telecamere intrinseca.

Utilizzando questa funzione in combinazione con il metodo projectPoints(), sono stato in grado di riproiettare i punti 3d sull'immagine.

In caso di bordi dello schermo, vengono posizionati nel punto giusto dell'immagine.

UPDATE:

ho trovato un bug nel mio implementazione - la mia matrice intrinseca macchina fotografica era sbagliato. La posa della telecamera dall'implementazione dell'omografia sopra sta funzionando per me!

0

Il rapporto tra omografia in caso calibrato (H) e caso non calibrato (H ') è

H' =^(- 1), dove K è matrice intrinseca di ripresa.