/** * License: GPL * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package lenscorrection; import java.util.Collection; import mpicbg.models.AbstractAffineModel2D; import mpicbg.models.AbstractModel; import mpicbg.models.IllDefinedDataPointsException; import mpicbg.models.NotEnoughDataPointsException; import mpicbg.models.PointMatch; /** * A wrpper for {@link NonLinearTransform} and the {@link AbstractAffineModel2D} * to which it is regularized. * * @author Stephan Saalfeld saalfeld@mpi-cbg.de * @version 0.1a */ public class PolynomialModel2D extends AbstractModel< PolynomialModel2D > { private NonLinearTransform nlt = new NonLinearTransform(); private AbstractAffineModel2D< ? > affine = null; private float lambda = 0f; public AbstractAffineModel2D< ? > getAffine(){ return affine; } public void setAffine( final AbstractAffineModel2D< ? > affine ){ this.affine = affine; } public void setAffine( final Class< ? extends AbstractAffineModel2D< ? > > affineClass ) throws Exception { affine = affineClass.newInstance(); } public int getOrder(){ return nlt.getDimension(); } public void setOrder( final int order ){ nlt.setDimension( order ); } public float getLambda(){ return lambda; } public void setLambda( final float lambda ){ this.lambda = lambda; } @Override public PolynomialModel2D copy() { final PolynomialModel2D clone = new PolynomialModel2D(); clone.nlt = nlt.copy(); clone.affine = affine.copy(); clone.lambda = lambda; return clone; } @Override public < P extends PointMatch >void fit( final Collection< P > pointMatches ) throws NotEnoughDataPointsException, IllDefinedDataPointsException { if ( pointMatches.size() < getMinNumMatches() ) throw new NotEnoughDataPointsException( pointMatches.size() + " data points are not enough to estimate a 2d polynomial of order " + nlt.getDimension() + ", at least " + getMinNumMatches() + " data points required." ); affine.fit( pointMatches ); final double h1[][] = new double[ pointMatches.size() ][ 2 ]; final double h2[][] = new double[ pointMatches.size() ][ 2 ]; int i = 0; for ( final P match : pointMatches ) { final double[] tmp1 = match.getP1().getL().clone(); affine.applyInPlace( tmp1 ); final double[] tmp2 = match.getP2().getW(); h1[ i ] = new double[]{ tmp1[ 0 ], tmp1[ 1 ] }; h2[ i ] = new double[]{ tmp2[ 0 ], tmp2[ 1 ] }; ++i; } nlt.fit( h1, h2, lambda ); } @Override public int getMinNumMatches() { return Math.max( affine.getMinNumMatches(), nlt.getMinNumMatches() ); } @Override public void set( final PolynomialModel2D m ) { nlt.set( m.nlt ); affine = m.affine.copy(); lambda = m.lambda; } @Override public String toString() { return "affine: " + affine.toString() + "; polynomial: " + nlt.toString(); } @Override public double[] apply( final double[] location ) { final double[] l = location.clone(); applyInPlace( l ); return l; } @Override public void applyInPlace( final double[] location ) { affine.applyInPlace( location ); nlt.applyInPlace( location ); } }