All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boofcv.alg.geo.f.FundamentalLinear Maven / Gradle / Ivy

Go to download

BoofCV is an open source Java library for real-time computer vision and robotics applications.

There is a newer version: 0.26
Show newest version
/*
 * Copyright (c) 2011-2014, Peter Abeles. All Rights Reserved.
 *
 * This file is part of BoofCV (http://boofcv.org).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package boofcv.alg.geo.f;

import boofcv.alg.geo.LowLevelMultiViewOps;
import boofcv.struct.geo.AssociatedPair;
import georegression.struct.point.Point2D_F64;
import org.ejml.data.DenseMatrix64F;
import org.ejml.factory.DecompositionFactory;
import org.ejml.interfaces.decomposition.SingularValueDecomposition;
import org.ejml.ops.CommonOps;
import org.ejml.ops.SingularOps;

import java.util.List;

/**
 * 

* Base class for linear algebra based algorithms for computing the Fundamental/Essential matrices. *

* *

* The computed fundamental matrix follow the following convention (with no noise) for the associated pair: * x2T*F*x1 = 0
* x1 = keyLoc and x2 = currLoc. *

* * @author Peter Abeles */ public abstract class FundamentalLinear { // contains the set of equations that are solved protected DenseMatrix64F A = new DenseMatrix64F(1,9); // svd used to extract the null space protected SingularValueDecomposition svdNull = DecompositionFactory.svd(9, 9, false, true, false); // svd used to enforce constraings on 3x3 matrix protected SingularValueDecomposition svdConstraints = DecompositionFactory.svd(3, 3, true, true, false); // SVD decomposition of F = U*S*V^T protected DenseMatrix64F svdU; protected DenseMatrix64F svdS; protected DenseMatrix64F svdV; protected DenseMatrix64F temp0 = new DenseMatrix64F(3,3); // matrix used to normalize results protected DenseMatrix64F N1 = new DenseMatrix64F(3,3); protected DenseMatrix64F N2 = new DenseMatrix64F(3,3); // should it compute a fundamental (true) or essential (false) matrix? boolean computeFundamental; /** * Specifies which type of matrix is to be computed * * @param computeFundamental true it computes a fundamental matrix and false for essential */ public FundamentalLinear( boolean computeFundamental ) { this.computeFundamental = computeFundamental; } /** * Projects the found estimate of E onto essential space. * * @return true if svd returned true. */ protected boolean projectOntoEssential( DenseMatrix64F E ) { if( !svdConstraints.decompose(E) ) { return false; } svdV = svdConstraints.getV(svdV,false); svdU = svdConstraints.getU(svdU,false); svdS = svdConstraints.getW(svdS); SingularOps.descendingOrder(svdU, false, svdS, svdV, false); // project it into essential space // the scale factor is arbitrary, but the first two singular values need // to be the same. so just set them to one svdS.unsafe_set(0, 0, 1); svdS.unsafe_set(1, 1, 1); svdS.unsafe_set(2, 2, 0); // recompute F CommonOps.mult(svdU, svdS, temp0); CommonOps.multTransB(temp0,svdV, E); return true; } /** * Projects the found estimate of F onto Fundamental space. * * @return true if svd returned true. */ protected boolean projectOntoFundamentalSpace( DenseMatrix64F F ) { if( !svdConstraints.decompose(F) ) { return false; } svdV = svdConstraints.getV(svdV,false); svdU = svdConstraints.getU(svdU,false); svdS = svdConstraints.getW(svdS); SingularOps.descendingOrder(svdU, false, svdS, svdV, false); // the smallest singular value needs to be set to zero, unlike svdS.set(2, 2, 0); // recompute F CommonOps.mult(svdU, svdS, temp0); CommonOps.multTransB(temp0,svdV, F); return true; } /** * Undo the normalization done to the input matrices for a Fundamental matrix. *
* M = N2T*M*N1 * * @param M Either the homography or fundamental matrix computed from normalized points. * @param N1 normalization matrix. * @param N2 normalization matrix. */ protected void undoNormalizationF(DenseMatrix64F M, DenseMatrix64F N1, DenseMatrix64F N2) { // M = N2^T * M * N1 CommonOps.multTransA(N2,M,temp0); CommonOps.mult(temp0,N1,M); } /** * Reorganizes the epipolar constraint equation (xT2*F*x1 = 0) such that it * is formulated as a standard linear system of the form Ax=0. Where A contains the pixel locations and x is * the reformatted fundamental matrix. * * @param points Set of associated points in left and right images. * @param A Matrix where the reformatted points are written to. */ protected void createA(List points, DenseMatrix64F A ) { A.reshape(points.size(),9, false); A.zero(); Point2D_F64 f_norm = new Point2D_F64(); Point2D_F64 s_norm = new Point2D_F64(); final int size = points.size(); for( int i = 0; i < size; i++ ) { AssociatedPair p = points.get(i); Point2D_F64 f = p.p1; Point2D_F64 s = p.p2; // normalize the points LowLevelMultiViewOps.applyPixelNormalization(N1, f, f_norm); LowLevelMultiViewOps.applyPixelNormalization(N2, s, s_norm); // perform the Kronecker product with the two points being in // homogeneous coordinates (z=1) A.unsafe_set(i,0,s_norm.x*f_norm.x); A.unsafe_set(i,1,s_norm.x*f_norm.y); A.unsafe_set(i,2,s_norm.x); A.unsafe_set(i,3,s_norm.y*f_norm.x); A.unsafe_set(i,4,s_norm.y*f_norm.y); A.unsafe_set(i,5,s_norm.y); A.unsafe_set(i,6,f_norm.x); A.unsafe_set(i,7,f_norm.y); A.unsafe_set(i,8,1); } } /** * Returns the U from the SVD of F. * * @return U matrix. */ public DenseMatrix64F getSvdU() { return svdU; } /** * Returns the S from the SVD of F. * * @return S matrix. */ public DenseMatrix64F getSvdS() { return svdS; } /** * Returns the V from the SVD of F. * * @return V matrix. */ public DenseMatrix64F getSvdV() { return svdV; } /** * Returns true if it is computing a fundamental matrix or false if it is an essential matrix. * @return true for fundamental and false for essential */ public boolean isComputeFundamental() { return computeFundamental; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy