eightPointAlgorithm.h

Go to the documentation of this file.
00001 
00015 #ifndef DLR_COMPUTERVISION_EIGHTPOINTALGORITHM_H
00016 #define DLR_COMPUTERVISION_EIGHTPOINTALGORITHM_H
00017 
00018 #include <dlrNumeric/array2D.h>
00019 
00020 namespace dlr {
00021 
00022   namespace computerVision {
00023 
00065     template<class Iterator>
00066     dlr::numeric::Array2D<double>
00067     eightPointAlgorithm(Iterator sequence0Begin, Iterator sequence0End,
00068                         Iterator sequence1Begin);
00069     
00070     
00096     template<class Iterator>
00097     dlr::numeric::Array2D<double>
00098     eightPointAlgorithm(Iterator sequence0Begin, Iterator sequence0End,
00099                         Iterator sequence1Begin,
00100                         dlr::numeric::Array1D<double>& eigenvalues);
00101 
00102 
00103 
00125     void
00126     normalizePointSequence(dlr::numeric::Array2D<double> const& inputPoints,
00127                            dlr::numeric::Array2D<double>& outputPoints,
00128                            dlr::numeric::Array2D<double>& transform);
00129 
00130   } // namespace computerVision
00131     
00132 } // namespace dlr
00133 
00134 
00135 /* ============ Definitions of inline & template functions ============ */
00136 
00137 
00138 #include <cmath>
00139 #include <dlrLinearAlgebra/linearAlgebra.h>
00140 #include <dlrNumeric/utilities.h>
00141 
00142 
00143 namespace dlr {
00144 
00145   namespace computerVision {
00146 
00147 
00148     template<class Iterator>
00149     dlr::numeric::Array2D<double>
00150     eightPointAlgorithm(Iterator sequence0Begin, Iterator sequence0End,
00151                         Iterator sequence1Begin)
00152     {
00153       dlr::numeric::Array1D<double> eigenvalues;
00154       return eightPointAlgorithm(
00155         sequence0Begin, sequence0End, sequence1Begin, eigenvalues);
00156     }
00157     
00158     
00159     template<class Iterator>
00160     dlr::numeric::Array2D<double>
00161     eightPointAlgorithm(Iterator sequence0Begin, Iterator sequence0End,
00162                         Iterator sequence1Begin,
00163                         dlr::numeric::Array1D<double>& eigenvalues)
00164     {
00165       // Find out how many points we have.  Even if this subtraction
00166       // is O(N), it will be dominated by the matrix multiplication
00167       // below.
00168       size_t numberOfCorrespondences = sequence0End - sequence0Begin;
00169 
00170       
00171       // Following Hartley, precondition the data by translating and
00172       // scaling (independently for each image) so that the points
00173       // roughly form a unit circle.  This greatly improves the
00174       // stability of the math below.
00175       dlr::numeric::Array2D<double> inputArray(numberOfCorrespondences, 3);
00176       dlr::numeric::Array2D<double> inputPrimeArray(numberOfCorrespondences, 3);
00177       Iterator begin0 = sequence0Begin;
00178       Iterator begin1 = sequence1Begin;
00179       size_t pointIndex = 0;
00180       while(begin0 != sequence0End) {
00181         dlr::numeric::Array1D<double> tmpRow = inputArray.getRow(pointIndex);
00182         tmpRow[0] = begin0->x();
00183         tmpRow[1] = begin0->y();
00184         tmpRow[2] = 1.0;
00185 
00186         tmpRow = inputPrimeArray.getRow(pointIndex);
00187         tmpRow[0] = begin1->x();
00188         tmpRow[1] = begin1->y();
00189         tmpRow[2] = 1.0;
00190 
00191         ++pointIndex;
00192         ++begin0;
00193         ++begin1;
00194       }
00195 
00196       dlr::numeric::Array2D<double> KKInv;
00197       dlr::numeric::Array2D<double> normalizedPoints;
00198       normalizePointSequence(inputArray, normalizedPoints, KKInv);
00199 
00200       dlr::numeric::Array2D<double> KPrimeInv;
00201       dlr::numeric::Array2D<double> normalizedPrimePoints;
00202       normalizePointSequence(inputPrimeArray, normalizedPrimePoints, KPrimeInv);
00203 
00204       // For each pair of points u, u', the fundamental matrix, F,
00205       // satisfies the equation:
00206       //
00207       //   transpose(u') * F * u = 0
00208       //
00209       // where the points u are drawn from sequence0, and the points
00210       // u' are drawn from sequence1.
00211       // 
00212       // We rearrange this equation to get
00213       //
00214       //   ||f_00*u_x*u'_x + f_01*u_y*u'_x + f_02*u'_x
00215       //     + f_10*u_x*u'_y + f_11*u_y*u'_y + f_12*u'_y
00216       //     + f_20*u_x + f_21*u_y + f_22|| = 0
00217       //
00218       // where f_ij is the element of F in the i^th row and the j^th
00219       // column, u_x & u_y are the x & y components of u,
00220       // respectively, and u'_x & u'_y are the x & y components of u',
00221       // respectively.
00222       //
00223       // or,
00224       // 
00225       //   ||A * vec(F)|| = 0
00226       //
00227       // With the matrix A as specified in the code below.
00228         
00229       dlr::numeric::Array2D<double> AMatrix(numberOfCorrespondences, 9);
00230       for(size_t rowIndex = 0; rowIndex < numberOfCorrespondences; ++rowIndex) {
00231         dlr::numeric::Array1D<double> currentRow = AMatrix.getRow(rowIndex);
00232         const dlr::numeric::Array1D<double>& uu =
00233           normalizedPoints.getRow(rowIndex);
00234         const dlr::numeric::Array1D<double>& uPrime =
00235           normalizedPrimePoints.getRow(rowIndex);
00236         currentRow[0] = uu[0] * uPrime[0];
00237         currentRow[1] = uu[1] * uPrime[0];
00238         currentRow[2] = uu[2] * uPrime[0];
00239         currentRow[3] = uu[0] * uPrime[1];
00240         currentRow[4] = uu[1] * uPrime[1];
00241         currentRow[5] = uu[2] * uPrime[1];
00242         currentRow[6] = uu[0] * uPrime[2];
00243         currentRow[7] = uu[1] * uPrime[2];
00244         currentRow[8] = uu[2] * uPrime[2];
00245       }
00246 
00247       // Solve for the F that minimizes the residual in the least
00248       // squares sense.
00249       dlr::numeric::Array2D<double> ATA =
00250         dlr::numeric::matrixMultiply(AMatrix.transpose(), AMatrix);
00251       dlr::numeric::Array2D<double> eigenvectors;
00252       dlr::linearAlgebra::eigenvectorsSymmetric(ATA, eigenvalues, eigenvectors);
00253       dlr::numeric::Array2D<double> FMatrix(3, 3);
00254       FMatrix[0] = eigenvectors(0, 8);
00255       FMatrix[1] = eigenvectors(1, 8);
00256       FMatrix[2] = eigenvectors(2, 8);
00257       FMatrix[3] = eigenvectors(3, 8);
00258       FMatrix[4] = eigenvectors(4, 8);
00259       FMatrix[5] = eigenvectors(5, 8);
00260       FMatrix[6] = eigenvectors(6, 8);
00261       FMatrix[7] = eigenvectors(7, 8);
00262       FMatrix[8] = eigenvectors(8, 8);
00263 
00264       // Good.  Now we have an estimate for F, here we enforce that F
00265       // must not be full rank.
00266       dlr::numeric::Array2D<double> uArray;
00267       dlr::numeric::Array1D<double> sigmaArray;
00268       dlr::numeric::Array2D<double> vTransposeArray;
00269       dlr::linearAlgebra::singularValueDecomposition(
00270         FMatrix, uArray, sigmaArray, vTransposeArray);
00271       uArray[2] = 0.0;
00272       for(size_t ii = 0; ii < sigmaArray.size(); ++ii) {
00273         vTransposeArray.getRow(ii) *= sigmaArray(ii);
00274       }
00275       FMatrix = matrixMultiply(uArray, vTransposeArray);
00276 
00277       // Transform back to unnormalized coordinates.
00278       FMatrix =
00279         dlr::numeric::matrixMultiply(
00280           dlr::numeric::matrixMultiply(KPrimeInv.transpose(), FMatrix), KKInv);
00281       
00282       return FMatrix;
00283     }
00284 
00285   } // namespace computerVision
00286     
00287 } // namespace dlr
00288 
00289 #endif /* #ifndef DLR_COMPUTERVISION_EIGHTPOINTALGORITHM_H */

Generated on Tue Jan 6 23:24:56 2009 for dlrComputerVision Utility Library by  doxygen 1.5.6