Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow to specify floating point precision when fitting affine models #45

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions mpicbg/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,12 @@
<groupId>gov.nist.math</groupId>
<artifactId>jama</artifactId>
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
54 changes: 46 additions & 8 deletions mpicbg/src/main/java/mpicbg/models/AffineModel1D.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

import java.util.Collection;

import mpicbg.util.Util;

/**
*
* @author Stephan Saalfeld &lt;[email protected]&gt;
Expand Down Expand Up @@ -99,6 +101,20 @@ final public void fit(
final double[][] q,
final double[] w )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( p, q, w, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public void fit(
final double[][] p,
final double[][] q,
final double[] w,
final double epsilon )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
assert
p.length >= 1 &&
Expand All @@ -113,7 +129,7 @@ final public void fit(
final int l = p[ 0 ].length;

if ( l < MIN_NUM_MATCHES )
throw new NotEnoughDataPointsException( l + " data points are not enough to estimate a 2d affine model, at least " + MIN_NUM_MATCHES + " data points required." );
throw new NotEnoughDataPointsException( l + " data points are not enough to estimate a 1d affine model, at least " + MIN_NUM_MATCHES + " data points required." );

double pcx = 0;
double qcx = 0;
Expand Down Expand Up @@ -143,7 +159,7 @@ final public void fit(
b += wwpx * qx;
}

if ( a == 0 )
if ( Util.isApproxEqual( a, 0, epsilon ) )
throw new IllDefinedDataPointsException();

m00 = b / a;
Expand All @@ -163,6 +179,20 @@ final public void fit(
final float[][] q,
final float[] w )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( p, q, w, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public void fit(
final float[][] p,
final float[][] q,
final float[] w,
final float epsilon)
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
assert
p.length >= 1 &&
Expand All @@ -177,7 +207,7 @@ final public void fit(
final int l = p[ 0 ].length;

if ( l < MIN_NUM_MATCHES )
throw new NotEnoughDataPointsException( l + " data points are not enough to estimate a 2d affine model, at least " + MIN_NUM_MATCHES + " data points required." );
throw new NotEnoughDataPointsException( l + " data points are not enough to estimate a 1d affine model, at least " + MIN_NUM_MATCHES + " data points required." );

double pcx = 0;
double qcx = 0;
Expand Down Expand Up @@ -207,7 +237,7 @@ final public void fit(
b += wwpx * qx;
}

if ( a == 0 )
if ( Util.isApproxEqual( a, 0, epsilon ) )
throw new IllDefinedDataPointsException();

m00 = b / a;
Expand All @@ -219,15 +249,23 @@ final public void fit(
/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*
* TODO
*/
@Override
final public < P extends PointMatch >void fit( final Collection< P > matches )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( matches, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public < P extends PointMatch >void fit( final Collection< P > matches, final double epsilon )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
if ( matches.size() < MIN_NUM_MATCHES )
throw new NotEnoughDataPointsException( matches.size() + " data points are not enough to estimate a 2d affine model, at least " + MIN_NUM_MATCHES + " data points required." );
throw new NotEnoughDataPointsException( matches.size() + " data points are not enough to estimate a 1d affine model, at least " + MIN_NUM_MATCHES + " data points required." );

double pcx = 0;
double qcx = 0;
Expand Down Expand Up @@ -262,7 +300,7 @@ final public < P extends PointMatch >void fit( final Collection< P > matches )
b += wwpx * qx;
}

if ( a == 0 )
if ( Util.isApproxEqual( a, 0, epsilon ) )
throw new IllDefinedDataPointsException();

m00 = b / a;
Expand Down
46 changes: 43 additions & 3 deletions mpicbg/src/main/java/mpicbg/models/AffineModel2D.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import java.awt.geom.AffineTransform;
import java.util.Collection;

import mpicbg.util.Util;

/**
* 2d-affine transformation models to be applied to points in 2d-space.
* This model includes the closed form weighted least squares solution as
Expand Down Expand Up @@ -117,6 +119,20 @@ final public void fit(
final double[][] q,
final double[] w )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( p, q, w, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public void fit(
final double[][] p,
final double[][] q,
final double[] w,
final double epsilon )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
assert
p.length >= 2 &&
Expand Down Expand Up @@ -183,7 +199,7 @@ final public void fit(

final double det = a00 * a11 - a01 * a01;

if ( det == 0 )
if ( Util.isApproxEqual( det, 0, epsilon ) )
throw new IllDefinedDataPointsException();

m00 = ( a11 * b00 - a01 * b10 ) / det;
Expand All @@ -207,6 +223,20 @@ final public void fit(
final float[][] q,
final float[] w )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( p, q, w, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public void fit(
final float[][] p,
final float[][] q,
final float[] w,
final float epsilon )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
assert
p.length >= 2 &&
Expand Down Expand Up @@ -273,7 +303,7 @@ final public void fit(

final double det = a00 * a11 - a01 * a01;

if ( det == 0 )
if ( Util.isApproxEqual( det, 0, epsilon ) )
throw new IllDefinedDataPointsException();

m00 = ( a11 * b00 - a01 * b10 ) / det;
Expand All @@ -294,6 +324,16 @@ final public void fit(
@Override
final public < P extends PointMatch >void fit( final Collection< P > matches )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( matches, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public < P extends PointMatch >void fit( final Collection< P > matches, final double epsilon )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
if ( matches.size() < MIN_NUM_MATCHES )
throw new NotEnoughDataPointsException( matches.size() + " data points are not enough to estimate a 2d affine model, at least " + MIN_NUM_MATCHES + " data points required." );
Expand Down Expand Up @@ -343,7 +383,7 @@ final public < P extends PointMatch >void fit( final Collection< P > matches )

final double det = a00 * a11 - a01 * a01;

if ( det == 0 )
if ( Util.isApproxEqual( det, 0, epsilon ) )
throw new IllDefinedDataPointsException();

m00 = ( a11 * b00 - a01 * b10 ) / det;
Expand Down
51 changes: 45 additions & 6 deletions mpicbg/src/main/java/mpicbg/models/AffineModel3D.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.Collection;

import mpicbg.util.Matrix3x3;
import mpicbg.util.Util;

/**
* 3d-affine transformation models to be applied to points in 3d-space.
Expand Down Expand Up @@ -148,6 +149,20 @@ final public void fit(
final double[][] q,
final double[] w )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( p, q, w, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public void fit(
final double[][] p,
final double[][] q,
final double[] w,
final double epsilon )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
assert
p.length >= 3 &&
Expand All @@ -162,7 +177,7 @@ final public void fit(
final int l = p[ 0 ].length;

if ( l < MIN_NUM_MATCHES )
throw new NotEnoughDataPointsException( l + " data points are not enough to estimate a 2d affine model, at least " + MIN_NUM_MATCHES + " data points required." );
throw new NotEnoughDataPointsException( l + " data points are not enough to estimate a 3d affine model, at least " + MIN_NUM_MATCHES + " data points required." );

double pcx = 0, pcy = 0, pcz = 0;
double qcx = 0, qcy = 0, qcz = 0;
Expand Down Expand Up @@ -244,7 +259,7 @@ final public void fit(
a12 * a12 * a00 -
a22 * a01 * a01;

if ( det == 0 )
if ( Util.isApproxEqual( det, 0, epsilon ) )
throw new IllDefinedDataPointsException();

final double idet = 1.0 / det;
Expand Down Expand Up @@ -285,6 +300,20 @@ final public void fit(
final float[][] q,
final float[] w )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( p, q, w, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public void fit(
final float[][] p,
final float[][] q,
final float[] w,
final float epsilon )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
assert
p.length >= 3 &&
Expand All @@ -299,7 +328,7 @@ final public void fit(
final int l = p[ 0 ].length;

if ( l < MIN_NUM_MATCHES )
throw new NotEnoughDataPointsException( l + " data points are not enough to estimate a 2d affine model, at least " + MIN_NUM_MATCHES + " data points required." );
throw new NotEnoughDataPointsException( l + " data points are not enough to estimate a 3d affine model, at least " + MIN_NUM_MATCHES + " data points required." );

double pcx = 0, pcy = 0, pcz = 0;
double qcx = 0, qcy = 0, qcz = 0;
Expand Down Expand Up @@ -381,7 +410,7 @@ final public void fit(
a12 * a12 * a00 -
a22 * a01 * a01;

if ( det == 0 )
if ( Util.isApproxEqual( det, 0, epsilon ) )
throw new IllDefinedDataPointsException();

final double idet = 1.0 / det;
Expand Down Expand Up @@ -419,9 +448,19 @@ final public void fit(
@Override
final public < P extends PointMatch >void fit( final Collection< P > matches )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
fit( matches, 0 );
}

/**
* Closed form weighted least squares solution as described by
* \citet{SchaeferAl06}.
*/
final public < P extends PointMatch >void fit( final Collection< P > matches, final double epsilon )
throws NotEnoughDataPointsException, IllDefinedDataPointsException
{
if ( matches.size() < MIN_NUM_MATCHES )
throw new NotEnoughDataPointsException( matches.size() + " data points are not enough to estimate a 2d affine model, at least " + MIN_NUM_MATCHES + " data points required." );
throw new NotEnoughDataPointsException( matches.size() + " data points are not enough to estimate a 3d affine model, at least " + MIN_NUM_MATCHES + " data points required." );

double pcx = 0, pcy = 0, pcz = 0;
double qcx = 0, qcy = 0, qcz = 0;
Expand Down Expand Up @@ -494,7 +533,7 @@ final public < P extends PointMatch >void fit( final Collection< P > matches )
a12 * a12 * a00 -
a22 * a01 * a01;

if ( det == 0 )
if ( Util.isApproxEqual( det, 0, epsilon ) )
throw new IllDefinedDataPointsException();

final double idet = 1.0 / det;
Expand Down
36 changes: 36 additions & 0 deletions mpicbg/src/main/java/mpicbg/util/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -366,4 +366,40 @@ final public static void memset( final char[] array, final char value )
for ( int i = 1; i < len; i += i )
System.arraycopy( array, 0, array, i, ( ( len - i ) < i ) ? ( len - i ) : i );
}

/**
* Checks if two real values are approximately equal.
*
* @param a
* @param b
* @param threshold
* @return
*/
final public static boolean isApproxEqual( final float a, final float b, final float threshold )
{
if ( a == b )
return true;
else if ( a + threshold > b && a - threshold < b )
return true;
else
return false;
}

/**
* Checks if two real values are approximately equal.
*
* @param a
* @param b
* @param threshold
* @return
*/
final public static boolean isApproxEqual( final double a, final double b, final double threshold )
{
if ( a == b )
return true;
else if ( a + threshold > b && a - threshold < b )
return true;
else
return false;
}
}
Loading