@Override public double getSimilarity( final ArrayList<PointMatch> matches ) { final int numDimensions = matches.get( 0 ).getP1().getL().length; double difference = 0; for ( final PointMatch match : matches ) difference += Point.squareDistance( match.getP1(), match.getP2() ); return difference / (double)numDimensions; } }
@Override final public PointMatch createPointMatch( final Point p1, final Point p2, final double w ) { return new PointMatch( p1, p2, w ); } };
/** * Flip symmetrically, weights remains unchanged. * * @param matches * @return */ final public static Collection< PointMatch > flip( final Collection< PointMatch > matches ) { final ArrayList< PointMatch > list = new ArrayList< PointMatch >(); flip( matches, list ); return list; }
/** * Apply a transformation to the second point (P2) of a list of Point matches * * @param list list of point matches * @param t transformation to be applied * * @return new list of point matches (after the transformation) */ public static List<PointMatch> applyTransformReverse( List<PointMatch> list, CoordinateTransform t) { // We need to flip the point matches in order to apply the previous transform List<PointMatch> new_list = (List<PointMatch>) PointMatch.flip(list); PointMatch.apply(new_list, t); // and flip back new_list = (List<PointMatch>) PointMatch.flip(new_list); return new_list; }
/** * Apply the current {@link AbstractModel} to all local point coordinates by weight. * Update {@link #cost} and {@link #distance}. * */ final public void update( final double amount ) { double d = 0.0; double c = 0.0; final int numMatches = matches.size(); if ( numMatches > 0 ) { double sumWeight = 0.0; for ( final PointMatch match : matches ) { match.apply( model, amount ); final double dl = match.getDistance(); d += dl; c += dl * dl * match.getWeight(); sumWeight += match.getWeight(); } d /= numMatches; c /= sumWeight; } distance = d; cost = c; model.setCost( c ); }
@Override final public < P extends PointMatch >void fit( final Collection< P > matches ) throws NotEnoughDataPointsException { if ( matches.size() < MIN_NUM_MATCHES ) throw new NotEnoughDataPointsException( matches.size() + " data points are not enough to estimate a 1d translation model, at least " + MIN_NUM_MATCHES + " data points required." ); // center of mass: double pcx = 0; double qcx = 0; double ws = 0.0f; for ( final P m : matches ) { final double[] p = m.getP1().getL(); final double[] q = m.getP2().getW(); final double w = m.getWeight(); ws += w; pcx += w * p[ 0 ]; qcx += w * q[ 0 ]; } pcx /= ws; qcx /= ws; t = qcx - pcx; }
PointMatch.sourcePoints( inliers, p1 ); PointMatch.targetPoints( inliers, p2 ); imp1.setRoi( Util.pointsToPointRoi( p1 ) ); imp2.setRoi( Util.pointsToPointRoi( p2 ) ); i1.add( m1.get( m.getP1() ) ); i2.add( m2.get( m.getP2() ) );
for ( final PointMatch m : matches ) final double[] l = m.getP1().getL(); final double[] w = m.getP2().getW(); for ( int i = 0; i < location.length; ++i ) location[ i ] = w[ i ]; return; final double weight = m.getWeight() * weigh( s ); final PointMatch mw = new PointMatch( m.getP1(), m.getP2(), weight ); weightedMatches.add( mw );
PointMatch.apply( inliers, model ); IJ.log( inliers.size() + " corresponding features with an average displacement of " + decimalFormat.format( PointMatch.meanDistance( inliers ) ) + "px identified." ); IJ.log( "Estimated transformation model: " + model ); PointMatch.sourcePoints( inliers, p1 ); PointMatch.targetPoints( inliers, p2 ); imp1.setRoi( Util.pointsToPointRoi( p1 ) ); imp2.setRoi( Util.pointsToPointRoi( p2 ) );
final Point p1 = pm.getP1(); final Point p2 = pm.getP2(); final double[] l1 = p1.getL(); final double[] w1 = p1.getW(); PointMatch.sourcePoints( inliers, points ); if ( Transforms.isIdentity( model, points, param.identityTolerance * param.layerScale ) ) Utils.log( layerNameB + " -> " + layerNameA + ": " + inliers.size() + " corresponding features with an average displacement of " + ( PointMatch.meanDistance( inliers ) / param.layerScale ) + "px identified." ); Utils.log( "Estimated transformation model: " + model ); models.set( ti, new Triple< Integer, Integer, AbstractModel< ? > >( sliceA, sliceB, model ) );
final public static void targetPoints( final Collection< PointMatch > matches, final Collection< Point > targetPoints ) { for ( final PointMatch m : matches ) targetPoints.add( m.getP2() ); }
protected static void setPointRois( final ImagePlus imp1, final ImagePlus imp2, final ArrayList<PointMatch> inliers ) { final ArrayList<Point> list1 = new ArrayList<Point>(); final ArrayList<Point> list2 = new ArrayList<Point>(); PointMatch.sourcePoints( inliers, list1 ); PointMatch.targetPoints( inliers, list2 ); PointRoi sourcePoints = mpicbg.ij.util.Util.pointsToPointRoi(list1); PointRoi targetPoints = mpicbg.ij.util.Util.pointsToPointRoi(list2); imp1.setRoi( sourcePoints ); imp2.setRoi( targetPoints ); }
final Point p1 = pm.getP1(); final Point p2 = pm.getP2(); final double[] l1 = p1.getL(); final double[] w1 = p1.getW(); PointMatch.apply( inliers, model ); Utils.log( layerNameB + " -> " + layerNameA + ": " + inliers.size() + " corresponding features with an average displacement of " + ( PointMatch.meanDistance( inliers ) ) + "px identified." ); Utils.log( "Estimated transformation model: " + model + ( param.multipleHypotheses ? ( " from " + nHypotheses + " hypotheses" ) : "" ) ); return new Triple< Integer, Integer, Collection< PointMatch > >( sliceA, sliceB, inliers );
final public static void sourcePoints( final Collection< PointMatch > matches, final Collection< Point > sourcePoints ) { for ( final PointMatch m : matches ) sourcePoints.add( m.getP1() ); }
/** * Apply an arbitrary coordinate transformation to each Tile's * PointMatches. This coordinate transformation is not supposed to be * compatible to {@link #modelClass}. * * This method is intended to be used for initializing the mesh in case * that further operations estimate a refined configuration. * * @param t */ final public void apply( final CoordinateTransform t ) { final Set< PointMatch > s = va.keySet(); for ( final PointMatch m : s ) { final Set< PointMatch > matches = pt.get( m ).getMatches(); for ( final PointMatch match : matches ) match.apply( t ); /** * Update the location of the vertex */ m.getP2().apply( t ); updateAffine( m ); } } }
static public final class ReferenceData { /** Patch id vs transform */ final Map<Long,Patch.TransformProperties> tp; /** A map of Displayable vs a map of Layer id vs list of Patch ids in that Layer that lay under the Patch, sorted by stack index. */ final Map<Displayable,Map<Long,TreeMap<Integer,Long>>> underlying; /** A list of the Layer ids form which at least one Patch was used to determine a transform of part of a VectorData instance. I.e. the visited layers. */ final Set<Long> src_layer_lids_used; ReferenceData(final Map<Long,Patch.TransformProperties> tp, final Map<Displayable,Map<Long,TreeMap<Integer,Long>>> underlying, final Set<Long> src_layer_lids_used) { this.tp = tp; this.underlying = underlying; this.src_layer_lids_used = src_layer_lids_used; } }
final static protected class MatchFeaturesAndFindModelThread extends Thread { final protected Param p; final protected List< AbstractAffineTile2D< ? > > tiles; //final protected HashMap< AbstractAffineTile2D< ? >, Collection< Feature > > tileFeatures; final protected List< AbstractAffineTile2D< ? >[] > tilePairs; final protected AtomicInteger ai; final protected AtomicInteger ap; final protected int steps; final protected boolean multipleHypotheses; public MatchFeaturesAndFindModelThread( final Param p, final List< AbstractAffineTile2D< ? > > tiles, final List< AbstractAffineTile2D< ? >[] > tilePairs, final AtomicInteger ai, final AtomicInteger ap, final int steps, final boolean multipleHypotheses ) { this.p = p; this.tiles = tiles; this.tilePairs = tilePairs; this.ai = ai; this.ap = ap; this.steps = steps; this.multipleHypotheses = multipleHypotheses; } public MatchFeaturesAndFindModelThread(
PointMatch.sourcePoints( inliers2, points ); if ( Transforms.isIdentity( model, points, param.identityTolerance ) )
float[] mean_distance = new float[MAX_ITER+1]; for(int iSlice = 0; iSlice < inliers.length; iSlice++) mean_distance[0] += PointMatch.meanDistance(inliers[iSlice]); PointMatch.flip(inliers[0], firstMatches); try{ PointMatch.flip(inliers[iSlice], flippedMatches); for(final PointMatch match : flippedMatches ) combined_inliers.add(match); PointMatch.apply(inliers[iSlice-1], t); if(iSlice-1 < inliers.length-1) inliers[iSlice] = applyTransformReverse(inliers[iSlice], t); mean_distance[n+1] += PointMatch.meanDistance(inliers[k]);
PointMatch.sourcePoints( inliers, points ); if ( Transforms.isIdentity( model, points, p.identityTolerance ) ) IJ.log( sliceB + " -> " + sliceA + ": " + inliers.size() + " corresponding features with an average displacement of " + PointMatch.meanDistance( inliers ) + "px identified." ); IJ.log( "Estimated transformation model: " + model ); models.set( ti, new Triple< Integer, Integer, AbstractModel< ? > >( sliceA, sliceB, model ) );