Search in sources :

Example 36 with PointMatch

use of mpicbg.models.PointMatch in project TrakEM2 by trakem2.

the class RegularizedAffineLayerAlignment method exec.

/**
 * @param param
 * @param layerRange
 * @param fixedLayers
 * @param emptyLayers
 * @param box
 * @param propagateTransformAfter
 * @param filter
 * @throws Exception
 */
@SuppressWarnings({ "rawtypes", "unchecked" })
public final void exec(final Param param, final List<Layer> layerRange, final Set<Layer> fixedLayers, final Set<Layer> emptyLayers, final Rectangle box, final boolean propagateTransformBefore, final boolean propagateTransformAfter, final Filter<Patch> filter) throws Exception {
    final double scale = Math.min(1.0, Math.min((double) param.ppm.sift.maxOctaveSize / (double) box.width, (double) param.ppm.sift.maxOctaveSize / (double) box.height));
    final ExecutorService exec = ExecutorProvider.getExecutorService(1.0f / (float) param.maxNumThreads);
    /* create tiles and models for all layers */
    final ArrayList<Tile<?>> tiles = new ArrayList<Tile<?>>();
    final AbstractAffineModel2D<?> m = (AbstractAffineModel2D<?>) Util.createModel(param.desiredModelIndex);
    final AbstractAffineModel2D<?> r = (AbstractAffineModel2D<?>) Util.createModel(param.regularizerIndex);
    for (int i = 0; i < layerRange.size(); ++i) {
        if (param.regularize)
            tiles.add(new Tile(new InterpolatedAffineModel2D(m.copy(), r.copy(), param.lambda)));
        else
            tiles.add(new Tile(m.copy()));
    }
    /* collect all pairs of slices for which a model could be found */
    final ArrayList<Triple<Integer, Integer, Collection<PointMatch>>> pairs = new ArrayList<Triple<Integer, Integer, Collection<PointMatch>>>();
    /* extract and save features, overwrite cached files if requested */
    try {
        AlignmentUtils.extractAndSaveLayerFeatures(layerRange, box, scale, filter, param.ppm.sift, param.ppm.clearCache, param.ppm.maxNumThreadsSift);
    } catch (final Exception e) {
        e.printStackTrace();
        IJError.print(e);
        return;
    }
    /* match and filter feature correspondences */
    int numFailures = 0, lastA = 0;
    final double pointMatchScale = 1.0 / scale;
    final ArrayList<Future<Triple<Integer, Integer, Collection<PointMatch>>>> modelFutures = new ArrayList<Future<Triple<Integer, Integer, Collection<PointMatch>>>>();
    for (int i = 0; i < layerRange.size(); ++i) {
        final int range = Math.min(layerRange.size(), i + param.maxNumNeighbors + 1);
        for (int j = i + 1; j < range; ++j) {
            modelFutures.add(exec.submit(new CorrespondenceCallable(param, layerRange.get(i), layerRange.get(j), pointMatchScale, i, j)));
        }
    }
    // Assume that futures are ordered in Triple.a
    try {
        for (final Future<Triple<Integer, Integer, Collection<PointMatch>>> future : modelFutures) {
            final Triple<Integer, Integer, Collection<PointMatch>> pair = future.get();
            if (lastA != pair.a) {
                numFailures = 0;
                lastA = pair.a;
            }
            if (pair.c == null) {
                numFailures++;
            // TODO: Cancel futures associated with pair.a
            } else if (numFailures < param.maxNumFailures) {
                pairs.add(pair);
            }
        }
    } catch (final InterruptedException ie) {
        Utils.log("Establishing feature correspondences interrupted.");
        for (final Future<Triple<Integer, Integer, Collection<PointMatch>>> future : modelFutures) {
            future.cancel(true);
        }
        return;
    }
    /* collect successfully matches pairs and break the search on gaps */
    /*
        for ( int t = 0; t < models.size(); ++t )
        {
            final Triple< Integer, Integer, Collection< PointMatch > > pair = models.get( t );
            if ( pair == null )
            {
                if ( ++numFailures > param.maxNumFailures )
                    break J;
            }
            else
            {
                numFailures = 0;
                pairs.add( pair );
            }
        }
*/
    /* Optimization */
    final TileConfiguration tileConfiguration = new TileConfiguration();
    for (final Triple<Integer, Integer, Collection<PointMatch>> pair : pairs) {
        final Tile<?> t1 = tiles.get(pair.a);
        final Tile<?> t2 = tiles.get(pair.b);
        tileConfiguration.addTile(t1);
        tileConfiguration.addTile(t2);
        t2.connect(t1, pair.c);
    }
    for (int i = 0; i < layerRange.size(); ++i) {
        final Layer layer = layerRange.get(i);
        if (fixedLayers.contains(layer))
            tileConfiguration.fixTile(tiles.get(i));
    }
    final List<Tile<?>> nonPreAlignedTiles = tileConfiguration.preAlign();
    IJ.log("pre-aligned all but " + nonPreAlignedTiles.size() + " tiles");
    tileConfiguration.optimize(param.maxEpsilon, param.maxIterationsOptimize, param.maxPlateauwidthOptimize);
    Utils.log(new StringBuffer("Successfully optimized configuration of ").append(tiles.size()).append(" tiles:").toString());
    Utils.log("  average displacement: " + String.format("%.3f", tileConfiguration.getError()) + "px");
    Utils.log("  minimal displacement: " + String.format("%.3f", tileConfiguration.getMinError()) + "px");
    Utils.log("  maximal displacement: " + String.format("%.3f", tileConfiguration.getMaxError()) + "px");
    if (propagateTransformBefore || propagateTransformAfter) {
        final Layer first = layerRange.get(0);
        final List<Layer> layers = first.getParent().getLayers();
        if (propagateTransformBefore) {
            final AffineTransform b = translateAffine(box, ((Affine2D<?>) tiles.get(0).getModel()).createAffine());
            final int firstLayerIndex = first.getParent().getLayerIndex(first.getId());
            for (int i = 0; i < firstLayerIndex; ++i) applyTransformToLayer(layers.get(i), b, filter);
        }
        if (propagateTransformAfter) {
            final Layer last = layerRange.get(layerRange.size() - 1);
            final AffineTransform b = translateAffine(box, ((Affine2D<?>) tiles.get(tiles.size() - 1).getModel()).createAffine());
            final int lastLayerIndex = last.getParent().getLayerIndex(last.getId());
            for (int i = lastLayerIndex + 1; i < layers.size(); ++i) applyTransformToLayer(layers.get(i), b, filter);
        }
    }
    for (int i = 0; i < layerRange.size(); ++i) {
        final AffineTransform b = translateAffine(box, ((Affine2D<?>) tiles.get(i).getModel()).createAffine());
        applyTransformToLayer(layerRange.get(i), b, filter);
    }
    Utils.log("Done.");
}
Also used : ArrayList(java.util.ArrayList) InterpolatedAffineModel2D(mpicbg.models.InterpolatedAffineModel2D) Tile(mpicbg.models.Tile) AbstractAffineModel2D(mpicbg.models.AbstractAffineModel2D) Layer(ini.trakem2.display.Layer) Point(mpicbg.models.Point) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) IllDefinedDataPointsException(mpicbg.models.IllDefinedDataPointsException) Triple(mpicbg.trakem2.util.Triple) PointMatch(mpicbg.models.PointMatch) ExecutorService(java.util.concurrent.ExecutorService) Collection(java.util.Collection) Future(java.util.concurrent.Future) AffineTransform(java.awt.geom.AffineTransform) TileConfiguration(mpicbg.models.TileConfiguration)

Example 37 with PointMatch

use of mpicbg.models.PointMatch in project TrakEM2 by trakem2.

the class Render method sampleAverageScale.

/**
 * Sample the average scaling of a given {@link CoordinateTransform} by transferring
 * a set of point samples using the {@link CoordinateTransform} and then
 * least-squares fitting a {@link SimilarityModel2D} to it.
 *
 * @param ct
 * @param width of the samples set
 * @param height of the samples set
 * @param dx spacing between samples
 *
 * @return average scale factor
 */
protected static final double sampleAverageScale(final CoordinateTransform ct, final int width, final int height, final double dx) {
    final ArrayList<PointMatch> samples = new ArrayList<PointMatch>();
    for (double y = 0; y < height; y += dx) {
        for (double x = 0; x < width; x += dx) {
            final Point p = new Point(new double[] { x, y });
            p.apply(ct);
            samples.add(new PointMatch(p, p));
        }
    }
    final SimilarityModel2D model = new SimilarityModel2D();
    try {
        model.fit(samples);
    } catch (final NotEnoughDataPointsException e) {
        e.printStackTrace(System.err);
        return 1;
    }
    final double[] data = new double[6];
    model.toArray(data);
    return Math.sqrt(data[0] * data[0] + data[1] * data[1]);
}
Also used : PointMatch(mpicbg.models.PointMatch) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) ArrayList(java.util.ArrayList) Point(mpicbg.models.Point) SimilarityModel2D(mpicbg.models.SimilarityModel2D)

Aggregations

PointMatch (mpicbg.models.PointMatch)37 ArrayList (java.util.ArrayList)26 Point (mpicbg.models.Point)24 AffineModel2D (mpicbg.models.AffineModel2D)16 NotEnoughDataPointsException (mpicbg.models.NotEnoughDataPointsException)15 SimilarityModel2D (mpicbg.models.SimilarityModel2D)14 AbstractAffineModel2D (mpicbg.models.AbstractAffineModel2D)12 Patch (ini.trakem2.display.Patch)10 AffineTransform (java.awt.geom.AffineTransform)10 Layer (ini.trakem2.display.Layer)9 Rectangle (java.awt.Rectangle)8 TranslationModel2D (mpicbg.models.TranslationModel2D)7 RigidModel2D (mpicbg.models.RigidModel2D)6 RigidModel2D (mpicbg.trakem2.transform.RigidModel2D)6 TranslationModel2D (mpicbg.trakem2.transform.TranslationModel2D)6 HashMap (java.util.HashMap)5 SIFT (mpicbg.ij.SIFT)5 Feature (mpicbg.imagefeatures.Feature)5 FloatArray2DSIFT (mpicbg.imagefeatures.FloatArray2DSIFT)5 Tile (mpicbg.models.Tile)5