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!