Search in sources :

Example 6 with Tile

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

the class AlignTask method alignMultiLayerMosaicTask.

@SuppressWarnings({ "unchecked", "rawtypes" })
public static final void alignMultiLayerMosaicTask(final List<Layer> layerRange, final Patch nail, final Align.Param cp, final Align.ParamOptimize p, final Align.ParamOptimize pcp, final boolean tilesAreInPlaceIn, final boolean largestGraphOnlyIn, final boolean hideDisconnectedTilesIn, final boolean deleteDisconnectedTilesIn, final boolean deformIn) {
    /* register */
    final List<AbstractAffineTile2D<?>> allTiles = new ArrayList<AbstractAffineTile2D<?>>();
    final List<AbstractAffineTile2D<?>> allFixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
    final List<AbstractAffineTile2D<?>> previousLayerTiles = new ArrayList<AbstractAffineTile2D<?>>();
    final HashMap<Patch, PointMatch> tileCenterPoints = new HashMap<Patch, PointMatch>();
    final Collection<Patch> fixedPatches = new HashSet<Patch>();
    if (null != nail)
        fixedPatches.add(nail);
    Layer previousLayer = null;
    for (final Layer layer : layerRange) {
        /* align all tiles in the layer */
        final List<Patch> patches = new ArrayList<Patch>();
        for (// ignore hidden tiles
        final Displayable a : // ignore hidden tiles
        layer.getDisplayables(Patch.class, true)) if (a instanceof Patch)
            patches.add((Patch) a);
        final List<AbstractAffineTile2D<?>> currentLayerTiles = new ArrayList<AbstractAffineTile2D<?>>();
        final List<AbstractAffineTile2D<?>> fixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
        Align.tilesFromPatches(p, patches, fixedPatches, currentLayerTiles, fixedTiles);
        // Will consider graphs and hide/delete tiles when all cross-layer graphs are found.
        alignTiles(p, currentLayerTiles, fixedTiles, tilesAreInPlaceIn, false, false, false);
        if (Thread.currentThread().isInterrupted())
            return;
        /* connect to the previous layer */
        /* generate tiles with the cross-section model from the current layer tiles */
        /* ------------------------------------------------------------------------ */
        /* TODO step back and make tiles bare containers for a patch and a model such that by changing the model the tile can be reused */
        final HashMap<Patch, AbstractAffineTile2D<?>> currentLayerPatchTiles = new HashMap<Patch, AbstractAffineTile2D<?>>();
        for (final AbstractAffineTile2D<?> t : currentLayerTiles) currentLayerPatchTiles.put(t.getPatch(), t);
        final List<AbstractAffineTile2D<?>> csCurrentLayerTiles = new ArrayList<AbstractAffineTile2D<?>>();
        final Set<AbstractAffineTile2D<?>> csFixedTiles = new HashSet<AbstractAffineTile2D<?>>();
        Align.tilesFromPatches(cp, patches, fixedPatches, csCurrentLayerTiles, csFixedTiles);
        final HashMap<Tile<?>, AbstractAffineTile2D<?>> tileTiles = new HashMap<Tile<?>, AbstractAffineTile2D<?>>();
        for (final AbstractAffineTile2D<?> t : csCurrentLayerTiles) tileTiles.put(currentLayerPatchTiles.get(t.getPatch()), t);
        for (final AbstractAffineTile2D<?> t : currentLayerTiles) {
            final AbstractAffineTile2D<?> csLayerTile = tileTiles.get(t);
            csLayerTile.addMatches(t.getMatches());
            for (final Tile<?> ct : t.getConnectedTiles()) csLayerTile.addConnectedTile(tileTiles.get(ct));
        }
        /* add a fixed tile only if there was a Patch selected */
        allFixedTiles.addAll(csFixedTiles);
        /* first, align connected graphs to each other */
        /* graphs in the current layer */
        final List<Set<Tile<?>>> currentLayerGraphs = AbstractAffineTile2D.identifyConnectedGraphs(csCurrentLayerTiles);
        if (Thread.currentThread().isInterrupted())
            return;
        // /* TODO just for visualization */
        // for ( final Set< Tile< ? > > graph : currentLayerGraphs )
        // {
        // Display.getFront().getSelection().clear();
        // Display.getFront().setLayer( ( ( AbstractAffineTile2D< ? > )graph.iterator().next() ).getPatch().getLayer() );
        // 
        // for ( final Tile< ? > tile : graph )
        // {
        // Display.getFront().getSelection().add( ( ( AbstractAffineTile2D< ? > )tile ).getPatch() );
        // Display.repaint();
        // }
        // Utils.showMessage( "OK" );
        // }
        /* graphs from the whole system that are present in the previous layer */
        final List<Set<Tile<?>>> graphs = AbstractAffineTile2D.identifyConnectedGraphs(allTiles);
        final HashMap<Set<Tile<?>>, Set<Tile<?>>> graphGraphs = new HashMap<Set<Tile<?>>, Set<Tile<?>>>();
        for (final Set<Tile<?>> graph : graphs) {
            if (Thread.currentThread().isInterrupted())
                return;
            final Set<Tile<?>> previousLayerGraph = new HashSet<Tile<?>>();
            for (final Tile<?> tile : previousLayerTiles) {
                if (graph.contains(tile)) {
                    graphGraphs.put(graph, previousLayerGraph);
                    previousLayerGraph.add(tile);
                }
            }
        }
        final Collection<Set<Tile<?>>> previousLayerGraphs = graphGraphs.values();
        // /* TODO just for visualization */
        // for ( final Set< Tile< ? > > graph : previousLayerGraphs )
        // {
        // Display.getFront().getSelection().clear();
        // Display.getFront().setLayer( ( ( AbstractAffineTile2D< ? > )graph.iterator().next() ).getPatch().getLayer() );
        // 
        // for ( final Tile< ? > tile : graph )
        // {
        // Display.getFront().getSelection().add( ( ( AbstractAffineTile2D< ? > )tile ).getPatch() );
        // Display.repaint();
        // }
        // Utils.showMessage( "OK" );
        // }
        /* generate snapshots of the graphs and preregister them using the parameters defined in cp */
        final List<AbstractAffineTile2D<?>[]> crossLayerTilePairs = new ArrayList<AbstractAffineTile2D<?>[]>();
        for (final Set<Tile<?>> currentLayerGraph : currentLayerGraphs) {
            for (final Set<Tile<?>> previousLayerGraph : previousLayerGraphs) {
                if (Thread.currentThread().isInterrupted())
                    return;
                alignGraphs(cp, layer, previousLayer, currentLayerGraph, previousLayerGraph);
                /* TODO this is pointless data shuffling just for type incompatibility---fix this at the root */
                final ArrayList<AbstractAffineTile2D<?>> previousLayerGraphTiles = new ArrayList<AbstractAffineTile2D<?>>();
                previousLayerGraphTiles.addAll((Set) previousLayerGraph);
                final ArrayList<AbstractAffineTile2D<?>> currentLayerGraphTiles = new ArrayList<AbstractAffineTile2D<?>>();
                currentLayerGraphTiles.addAll((Set) currentLayerGraph);
                AbstractAffineTile2D.pairOverlappingTiles(previousLayerGraphTiles, currentLayerGraphTiles, crossLayerTilePairs);
            }
        }
        /* ------------------------------------------------------------------------ */
        /* this is without the affine/rigid approximation per graph */
        // AbstractAffineTile2D.pairTiles( previousLayerTiles, csCurrentLayerTiles, crossLayerTilePairs );
        Align.connectTilePairs(cp, csCurrentLayerTiles, crossLayerTilePairs, Runtime.getRuntime().availableProcessors());
        if (Thread.currentThread().isInterrupted())
            return;
        // for ( final AbstractAffineTile2D< ? >[] tilePair : crossLayerTilePairs )
        // {
        // Display.getFront().setLayer( tilePair[ 0 ].getPatch().getLayer() );
        // Display.getFront().getSelection().clear();
        // Display.getFront().getSelection().add( tilePair[ 0 ].getPatch() );
        // Display.getFront().getSelection().add( tilePair[ 1 ].getPatch() );
        // 
        // Utils.showMessage( "1: OK?" );
        // 
        // Display.getFront().setLayer( tilePair[ 1 ].getPatch().getLayer() );
        // Display.getFront().getSelection().clear();
        // Display.getFront().getSelection().add( tilePair[ 0 ].getPatch() );
        // Display.getFront().getSelection().add( tilePair[ 1 ].getPatch() );
        // 
        // Utils.showMessage( "2: OK?" );
        // }
        /* prepare the next loop */
        allTiles.addAll(csCurrentLayerTiles);
        previousLayerTiles.clear();
        previousLayerTiles.addAll(csCurrentLayerTiles);
        /* optimize */
        Align.optimizeTileConfiguration(pcp, allTiles, allFixedTiles);
        if (Thread.currentThread().isInterrupted())
            return;
        for (final AbstractAffineTile2D<?> t : allTiles) t.getPatch().setAffineTransform(t.getModel().createAffine());
        previousLayer = layer;
    }
    final List<Set<Tile<?>>> graphs = AbstractAffineTile2D.identifyConnectedGraphs(allTiles);
    final List<AbstractAffineTile2D<?>> interestingTiles = new ArrayList<AbstractAffineTile2D<?>>();
    if (largestGraphOnlyIn && (hideDisconnectedTilesIn || deleteDisconnectedTilesIn)) {
        if (Thread.currentThread().isInterrupted())
            return;
        /* find largest graph. */
        Set<Tile<?>> largestGraph = null;
        for (final Set<Tile<?>> graph : graphs) if (largestGraph == null || largestGraph.size() < graph.size())
            largestGraph = graph;
        final Set<AbstractAffineTile2D<?>> tiles_to_keep = new HashSet<AbstractAffineTile2D<?>>();
        for (final Tile<?> t : largestGraph) tiles_to_keep.add((AbstractAffineTile2D<?>) t);
        if (hideDisconnectedTilesIn)
            for (final AbstractAffineTile2D<?> t : allTiles) if (!tiles_to_keep.contains(t))
                t.getPatch().setVisible(false);
        if (deleteDisconnectedTilesIn)
            for (final AbstractAffineTile2D<?> t : allTiles) if (!tiles_to_keep.contains(t))
                t.getPatch().remove(false);
        interestingTiles.addAll(tiles_to_keep);
    } else
        interestingTiles.addAll(allTiles);
    if (deformIn) {
        /* ############################################ */
        /* experimental: use the center points of all tiles to define a MLS deformation from the pure intra-layer registration to the globally optimal */
        Utils.log("deforming...");
        /* store the center location of each single tile for later deformation */
        for (final AbstractAffineTile2D<?> t : interestingTiles) {
            final double[] c = new double[] { t.getWidth() / 2.0, t.getHeight() / 2.0 };
            t.getModel().applyInPlace(c);
            final Point q = new Point(c);
            tileCenterPoints.put(t.getPatch(), new PointMatch(q.clone(), q));
        }
        for (final Layer layer : layerRange) {
            Utils.log("layer" + layer);
            if (Thread.currentThread().isInterrupted())
                return;
            /* again, align all tiles in the layer */
            final List<Patch> patches = new ArrayList<Patch>();
            for (final Displayable a : layer.getDisplayables(Patch.class)) if (a instanceof Patch)
                patches.add((Patch) a);
            final List<AbstractAffineTile2D<?>> currentLayerTiles = new ArrayList<AbstractAffineTile2D<?>>();
            final List<AbstractAffineTile2D<?>> fixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
            Align.tilesFromPatches(p, patches, fixedPatches, currentLayerTiles, fixedTiles);
            /* add a fixed tile only if there was a Patch selected */
            allFixedTiles.addAll(fixedTiles);
            // will consider graphs and hide/delete tiles when all cross-layer graphs are found
            alignTiles(p, currentLayerTiles, fixedTiles, true, false, false, false);
            /* for each independent graph do an independent transform */
            final List<Set<Tile<?>>> currentLayerGraphs = AbstractAffineTile2D.identifyConnectedGraphs(currentLayerTiles);
            for (final Set<Tile<?>> graph : currentLayerGraphs) {
                /* update the tile-center pointmatches */
                final Collection<PointMatch> matches = new ArrayList<PointMatch>();
                final Collection<AbstractAffineTile2D<?>> toBeDeformedTiles = new ArrayList<AbstractAffineTile2D<?>>();
                for (final AbstractAffineTile2D<?> t : (Collection<AbstractAffineTile2D<?>>) (Collection) graph) {
                    final PointMatch pm = tileCenterPoints.get(t.getPatch());
                    if (pm == null)
                        continue;
                    final double[] pl = pm.getP1().getL();
                    pl[0] = t.getWidth() / 2.0;
                    pl[1] = t.getHeight() / 2.0;
                    t.getModel().applyInPlace(pl);
                    matches.add(pm);
                    toBeDeformedTiles.add(t);
                }
                for (final AbstractAffineTile2D<?> t : toBeDeformedTiles) {
                    if (Thread.currentThread().isInterrupted())
                        return;
                    try {
                        final Patch patch = t.getPatch();
                        final Rectangle pbox = patch.getCoordinateTransformBoundingBox();
                        final AffineTransform pat = new AffineTransform();
                        pat.translate(-pbox.x, -pbox.y);
                        pat.preConcatenate(patch.getAffineTransform());
                        final mpicbg.trakem2.transform.AffineModel2D toWorld = new mpicbg.trakem2.transform.AffineModel2D();
                        toWorld.set(pat);
                        final MovingLeastSquaresTransform2 mlst = Align.createMLST(matches, 1.0f);
                        final CoordinateTransformList<CoordinateTransform> ctl = new CoordinateTransformList<CoordinateTransform>();
                        ctl.add(toWorld);
                        ctl.add(mlst);
                        ctl.add(toWorld.createInverse());
                        patch.appendCoordinateTransform(ctl);
                        patch.getProject().getLoader().regenerateMipMaps(patch);
                    } catch (final Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    layerRange.get(0).getParent().setMinimumDimensions();
    IJ.log("Done: register multi-layer mosaic.");
    return;
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) LayerSet(ini.trakem2.display.LayerSet) HashMap(java.util.HashMap) CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) AbstractAffineModel2D(mpicbg.models.AbstractAffineModel2D) AffineModel2D(mpicbg.models.AffineModel2D) HashSet(java.util.HashSet) Displayable(ini.trakem2.display.Displayable) Tile(mpicbg.models.Tile) Point(mpicbg.models.Point) Layer(ini.trakem2.display.Layer) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) NoninvertibleModelException(mpicbg.models.NoninvertibleModelException) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) PointMatch(mpicbg.models.PointMatch) MovingLeastSquaresTransform2(mpicbg.trakem2.transform.MovingLeastSquaresTransform2) Collection(java.util.Collection) AffineTransform(java.awt.geom.AffineTransform) Patch(ini.trakem2.display.Patch) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform) InvertibleCoordinateTransform(mpicbg.trakem2.transform.InvertibleCoordinateTransform)

Example 7 with Tile

use of mpicbg.models.Tile 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 8 with Tile

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

the class MatchIntensities method generateCoefficientsTiles.

protected static final <T extends Model<T> & Affine1D<T>> HashMap<Patch, ArrayList<Tile<T>>> generateCoefficientsTiles(final Collection<Patch> patches, final T template, final int nCoefficients) {
    final HashMap<Patch, ArrayList<Tile<T>>> map = new HashMap<Patch, ArrayList<Tile<T>>>();
    for (final Patch p : patches) {
        final ArrayList<Tile<T>> coefficientModels = new ArrayList<Tile<T>>();
        for (int i = 0; i < nCoefficients; ++i) coefficientModels.add(new Tile<T>(template.copy()));
        map.put(p, coefficientModels);
    }
    return map;
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Tile(mpicbg.models.Tile) Patch(ini.trakem2.display.Patch) Point(mpicbg.models.Point)

Aggregations

Tile (mpicbg.models.Tile)8 ArrayList (java.util.ArrayList)7 Point (mpicbg.models.Point)7 Layer (ini.trakem2.display.Layer)5 Patch (ini.trakem2.display.Patch)5 PointMatch (mpicbg.models.PointMatch)5 Rectangle (java.awt.Rectangle)4 HashMap (java.util.HashMap)4 NotEnoughDataPointsException (mpicbg.models.NotEnoughDataPointsException)4 AffineTransform (java.awt.geom.AffineTransform)3 Collection (java.util.Collection)3 Set (java.util.Set)3 ExecutorService (java.util.concurrent.ExecutorService)3 Future (java.util.concurrent.Future)3 TileConfiguration (mpicbg.models.TileConfiguration)3 AbstractAffineTile2D (mpicbg.trakem2.align.AbstractAffineTile2D)3 Displayable (ini.trakem2.display.Displayable)2 LayerSet (ini.trakem2.display.LayerSet)2 HashSet (java.util.HashSet)2 AbstractAffineModel2D (mpicbg.models.AbstractAffineModel2D)2