|
View:
New views
1 Messages
—
Rating Filter:
Alert me
|
|
|
compute cameras from essential matrixAttached is a preliminary patch (no tests, docs) that adds
cvComputeCamera to cv, for the case of computing cameras from the essential matrix (or fundamental matrix and one or two calibration matrices). Eventually this call would also support computing projective and/or metric cameras from F, T, and H. It's a straight forward application of SVD, with the evaluation of key formulas generated by Maple. Perhaps icvCompute_Rt_from_E should be collapsed so all solutions aren't expanded inline. Feedback? Complaints? Xavier [patch051008.diff] diff -r 4e159c511668 -r 6efbce59014a cv/include/cv.h --- a/cv/include/cv.h Sat May 10 13:07:11 2008 -0400 +++ b/cv/include/cv.h Sat May 10 13:39:32 2008 -0400 @@ -1187,6 +1187,20 @@ CVAPI(void) cvReleasePOSITObject( CvPOS /****************************************************************************************\ +* Multiple View Geometry * +\****************************************************************************************/ + + +#define CV_CAMERA_E 1 +#define CV_CAMERA_ALL_POSSIBLE 2 + +CVAPI(void) cvComputeCamera(const CvMat* Tm, + const CvMat* K1m,const CvMat* K2m, + CvMat* output, + int flags = CV_CAMERA_E); + + +/****************************************************************************************\ * Epipolar Geometry * \****************************************************************************************/ diff -r 4e159c511668 -r 6efbce59014a cv/src/Makefile.am --- a/cv/src/Makefile.am Sat May 10 13:07:11 2008 -0400 +++ b/cv/src/Makefile.am Sat May 10 13:39:32 2008 -0400 @@ -24,7 +24,7 @@ lib_cv_la_SOURCES = \ cvpyrsegmentation.cpp cvrotcalipers.cpp cvsamplers.cpp cvsegmentation.cpp cvshapedescr.cpp \ cvsmooth.cpp cvsnakes.cpp cvsubdivision2d.cpp cvsumpixels.cpp \ cvswitcher.cpp cvtables.cpp cvtemplmatch.cpp cvthresh.cpp \ - cvundistort.cpp cvutils.cpp + cvundistort.cpp cvutils.cpp cvessential.cpp lib_cv_la_LDFLAGS = -no-undefined @LDFLAGS@ # real library diff -r 4e159c511668 -r 6efbce59014a cv/src/cvessential.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cv/src/cvessential.cpp Sat May 10 13:39:32 2008 -0400 @@ -0,0 +1,367 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2008, Xavier Delacour, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +// 2008-05-10 Xavier Delacour <xavier.delacour@...> + +#include "_cv.h" + +// * add support for camera from F +// * add support for camera from T +// * add support for camera from [H,K] +// * factor cvComputeCamera into cvcamera.cpp, but leave the essential matrix bits here + +// * have option to return parameterized solutions? +// * i'd prefer not, would rather have return always be set of stacked cameras.. +// * and then have separate calls to decompose (with identity K) and parameterize + +// * move cvmat2array, array2cvmat, svdarray to utility header? + +// * select which of four remaining solutions has most points in front of +// * both cameras (requires triangulation and chirality utils) + +static inline void cvmat2array(const CvMat* M, double* A) { + CvMat Am; + cvInitMatHeader(&Am, M->rows, M->cols, CV_64FC1, A); + cvConvert(M, &Am); +} + +static inline void array2cvmat(int m, int n, const double* A, CvMat* M) { + assert(M->rows == m); + assert(M->cols == n); + CvMat Am; + cvInitMatHeader(&Am, M->rows, M->cols, CV_64FC1, (void*)A); + cvConvert(&Am, M); +} + +static inline void svdarray(int m, int n, double* A, + double* D, double* U = 0, double* V = 0, + int flags = CV_SVD_MODIFY_A|CV_SVD_U_T|CV_SVD_V_T) { + CvMat Amat, Dmat, Umat, Vmat; + + cvInitMatHeader(&Amat, m, n, CV_64FC1, (void*)A); + cvInitMatHeader(&Dmat, n, 1, CV_64FC1, (void*)D); + + if (U) { + int u_m = flags & CV_SVD_U_T ? n : m; + int u_n = flags & CV_SVD_U_T ? m : n; + cvInitMatHeader(&Umat, u_m, u_n, CV_64FC1, U); + } + + if (V) + cvInitMatHeader(&Vmat, n, n, CV_64FC1, V); + + cvSVD(&Amat, &Dmat, U ? &Umat : 0, V ? &Vmat : 0, flags); +} + + +static inline void icvCompute_E_uniform(const double* F, const double* K, double* E) { + /* + _F:=mat(3,3,F); + _K:=Matrix([[K[1],K[2],K[3]],[0,K[5],K[6]],[0,0,K[9]]]); + _E:=Tr(_K)._F._K; + compile_compseq([flat(_E)],["E"]); + */ + double t1 = K[0]; + double t2 = t1 * t1; + double t3 = F[0]; + E[0] = t2 * t3; + double t4 = t1 * t3; + double t5 = K[1]; + double t7 = F[1]; + double t8 = t1 * t7; + double t9 = K[4]; + E[1] = t4 * t5 + t8 * t9; + double t11 = K[2]; + double t13 = K[5]; + double t15 = F[2]; + double t17 = K[8]; + E[2] = t4 * t11 + t8 * t13 + t1 * t15 * t17; + double t20 = F[3]; + double t22 = t3 * t5 + t9 * t20; + E[3] = t22 * t1; + double t25 = F[4]; + double t27 = t5 * t7 + t9 * t25; + E[4] = t22 * t5 + t27 * t9; + double t32 = F[5]; + E[5] = t22 * t11 + t27 * t13 + (t5 * t15 + t9 * t32) * t17; + double t40 = t3 * t11 + t13 * t20 + t17 * F[6]; + E[6] = t40 * t1; + double t46 = t11 * t7 + t13 * t25 + t17 * F[7]; + E[7] = t40 * t5 + t46 * t9; + E[8] = t40 * t11 + t46 * t13 + (t11 * t15 + t13 * t32 + t17 * F[8]) * t17; +} + +static inline void icvCompute_E(const double* F, + const double* K1, const double* K2, + double* E) { + /* + _F:=mat(3,3,F); + _K1:=Matrix([[K1[1],K1[2],K1[3]],[0,K1[5],K1[6]],[0,0,K1[9]]]); + _K2:=Matrix([[K2[1],K2[2],K2[3]],[0,K2[5],K2[6]],[0,0,K2[9]]]); + _E:=Tr(_K2)._F._K1; + compile_compseq([flat(_E)],["E"]); + */ + double t1 = K2[0]; + double t2 = F[0]; + double t3 = t1 * t2; + double t4 = K1[0]; + E[0] = t3 * t4; + double t5 = K1[1]; + double t7 = F[1]; + double t8 = t1 * t7; + double t9 = K1[4]; + E[1] = t3 * t5 + t8 * t9; + double t11 = K1[2]; + double t13 = K1[5]; + double t15 = F[2]; + double t17 = K1[8]; + E[2] = t3 * t11 + t8 * t13 + t1 * t15 * t17; + double t19 = K2[1]; + double t21 = K2[4]; + double t22 = F[3]; + double t24 = t19 * t2 + t21 * t22; + E[3] = t24 * t4; + double t27 = F[4]; + double t29 = t19 * t7 + t21 * t27; + E[4] = t24 * t5 + t29 * t9; + double t34 = F[5]; + E[5] = t24 * t11 + t29 * t13 + (t19 * t15 + t21 * t34) * t17; + double t38 = K2[2]; + double t40 = K2[5]; + double t42 = K2[8]; + double t45 = t38 * t2 + t40 * t22 + t42 * F[6]; + E[6] = t45 * t4; + double t51 = t38 * t7 + t40 * t27 + t42 * F[7]; + E[7] = t45 * t5 + t51 * t9; + E[8] = t45 * t11 + t51 * t13 + (t38 * t15 + t40 * t34 + t42 * F[8]) * t17; +} + +// note that E is modified +static inline void icvCompute_Rt_from_E(double* E, double* P1234) { + double U[9]; + double V[9]; + double D[3]; + svdarray(3, 3, E, D, U, V); + + /* + _W:=Matrix([[0,-1,0],[1,0,0],[0,0,1]]); + __Z:=Matrix([[0,1,0],[-1,0,0],[0,0,0]]); + _U:=Tr(mat(3,3,U)); + _V:=Tr(mat(3,3,V)); + + _Tx:=_U.__Z.Tr(_U); + _t:=Vector([_Tx[3,2],_Tx[1,3],_Tx[2,1]]); + _R1:=_U._W.Tr(_V); + _R2:=_U.Tr(_W).Tr(_V); + + _P1:=Matrix([_R1,_t]); + _P2:=Matrix([_R2,_t]); + _P3:=Matrix([_R1,-_t]); + _P4:=Matrix([_R2,-_t]); + _P1234:=Matrix([[_P1],[_P2],[_P3],[_P4]]); + compile_compseq([flat(_P1234)],["P1234"]); + */ + double t1 = U[3]; + double t2 = V[0]; + double t3 = t1 * t2; + double t4 = U[0]; + double t5 = V[3]; + double t6 = t4 * t5; + double t7 = U[6]; + double t8 = V[6]; + double t9 = t7 * t8; + P1234[0] = t3 - t6 + t9; + double t10 = V[1]; + double t11 = t1 * t10; + double t12 = V[4]; + double t13 = t4 * t12; + double t14 = V[7]; + double t15 = t7 * t14; + P1234[1] = t11 - t13 + t15; + double t16 = V[2]; + double t17 = t1 * t16; + double t18 = V[5]; + double t19 = t4 * t18; + double t20 = V[8]; + double t21 = t7 * t20; + P1234[2] = t17 - t19 + t21; + double t22 = U[1]; + double t23 = U[5]; + double t25 = U[4]; + double t26 = U[2]; + P1234[3] = -t22 * t23 + t25 * t26; + double t28 = t25 * t2; + double t29 = t22 * t5; + double t30 = U[7]; + double t31 = t30 * t8; + P1234[4] = t28 - t29 + t31; + double t32 = t25 * t10; + double t33 = t22 * t12; + double t34 = t30 * t14; + P1234[5] = t32 - t33 + t34; + double t35 = t25 * t16; + double t36 = t22 * t18; + double t37 = t30 * t20; + P1234[6] = t35 - t36 + t37; + P1234[7] = -t1 * t26 + t4 * t23; + double t40 = t23 * t2; + double t41 = t26 * t5; + double t42 = U[8]; + double t43 = t42 * t8; + P1234[8] = t40 - t41 + t43; + double t44 = t23 * t10; + double t45 = t26 * t12; + double t46 = t42 * t14; + P1234[9] = t44 - t45 + t46; + double t47 = t23 * t16; + double t48 = t26 * t18; + double t49 = t42 * t20; + P1234[10] = t47 - t48 + t49; + P1234[11] = -t4 * t25 + t1 * t22; + P1234[12] = -t3 + t6 + t9; + P1234[13] = -t11 + t13 + t15; + P1234[14] = -t17 + t19 + t21; + P1234[15] = P1234[3]; + P1234[16] = -t28 + t29 + t31; + P1234[17] = -t32 + t33 + t34; + P1234[18] = -t35 + t36 + t37; + P1234[19] = P1234[7]; + P1234[20] = -t40 + t41 + t43; + P1234[21] = -t44 + t45 + t46; + P1234[22] = -t47 + t48 + t49; + P1234[23] = P1234[11]; + P1234[24] = P1234[0]; + P1234[25] = P1234[1]; + P1234[26] = P1234[2]; + P1234[27] = -P1234[15]; + P1234[28] = P1234[4]; + P1234[29] = P1234[5]; + P1234[30] = P1234[6]; + P1234[31] = -P1234[19]; + P1234[32] = P1234[8]; + P1234[33] = P1234[9]; + P1234[34] = P1234[10]; + P1234[35] = -P1234[23]; + P1234[36] = P1234[12]; + P1234[37] = P1234[13]; + P1234[38] = P1234[14]; + P1234[39] = P1234[27]; + P1234[40] = P1234[16]; + P1234[41] = P1234[17]; + P1234[42] = P1234[18]; + P1234[43] = P1234[31]; + P1234[44] = P1234[20]; + P1234[45] = P1234[21]; + P1234[46] = P1234[22]; + P1234[47] = P1234[35]; +} + +void cvComputeCamera(const CvMat* Tm, + const CvMat* K1m, const CvMat* K2m, + CvMat* output, + int flags) { + CV_FUNCNAME("cvComputeCamera"); + __BEGIN__; + + // compute P2 given essential matrix, or fundamental matrix and + // one or two calibration matrices (one if K's are uniform across views). + // P1 is canonical [I|0]. + if (flags & CV_CAMERA_E) { + if (Tm->cols != 3 || Tm->rows != 3) + CV_ERROR(CV_StsUnmatchedSizes, "E/F must be 3x3"); + if (K1m && (K1m->cols != 3 || K1m->rows != 3)) + CV_ERROR(CV_StsUnmatchedSizes, "K1 must be 3x3"); + if (K2m && (K2m->cols != 3 || K2m->rows != 3)) + CV_ERROR(CV_StsUnmatchedSizes, "K2 must be 3x3"); + + double E[9]; + + // E = K2' * F * K1 + if (K1m && K2m) { + double F[9], K1[9], K2[9]; + cvmat2array(Tm, F); + cvmat2array(K1m, K1); + cvmat2array(K2m, K2); + icvCompute_E(F, K1, K2, E); + } + + // E = K1' * F * K1 + else if (K1m) { + double F[9], K1[9]; + cvmat2array(Tm, F); + cvmat2array(K1m, K1); + icvCompute_E_uniform(F, K1, E); + } + + // E given + else { + cvmat2array(Tm, E); + } + + double P1234[12*4]; + icvCompute_Rt_from_E(E, P1234); + + // if user wants, just return all solutions + if (flags & CV_CAMERA_ALL_POSSIBLE) { + if (output->cols != 4 || output->rows != 3 * 4) + CV_ERROR(CV_StsUnmatchedSizes, "expecting output to be 12x4"); + array2cvmat(3 * 4, 4, P1234, output); + return; + } + + assert(0); + + // * triangulate here + + // * compute chirality here + + int best_i; // 0 <= i < 4 + + if (output->cols != 4 || output->rows != 3) + CV_ERROR(CV_StsUnmatchedSizes, "expecting output to be 3x4"); + array2cvmat(3, 4, P1234 + best_i * 12, output); + + } else { + CV_ERROR(CV_StsBadArg, "bad flags"); + } + + __END__; +} ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ Opencvlibrary-devel mailing list Opencvlibrary-devel@... https://lists.sourceforge.net/lists/listinfo/opencvlibrary-devel |
| Free Forum Powered by Nabble | Forum Help |