Search in sources :

Example 6 with CoordinateTransformList

use of mpicbg.trakem2.transform.CoordinateTransformList in project TrakEM2 by trakem2.

the class Patch method keyPressed.

@Override
public void keyPressed(final KeyEvent ke) {
    final Object source = ke.getSource();
    if (!(source instanceof DisplayCanvas))
        return;
    final DisplayCanvas dc = (DisplayCanvas) source;
    final Roi roi = dc.getFakeImagePlus().getRoi();
    final int mod = ke.getModifiers();
    switch(ke.getKeyCode()) {
        case KeyEvent.VK_C:
            // Ignoring masks: outside is already black, and ImageJ cannot handle alpha masks.
            if (0 == (mod ^ (Event.SHIFT_MASK | Event.ALT_MASK))) {
                // Place the source image, untransformed, into clipboard:
                final ImagePlus imp = getImagePlus();
                if (null != imp)
                    imp.copy(false);
            } else if (0 == mod || (0 == (mod ^ Event.SHIFT_MASK))) {
                CoordinateTransformList<CoordinateTransform> list = null;
                if (hasCoordinateTransform()) {
                    list = new CoordinateTransformList<CoordinateTransform>();
                    list.add(getCoordinateTransform());
                }
                if (0 == mod) {
                    // SHIFT is not down
                    final AffineModel2D am = new AffineModel2D();
                    am.set(this.at);
                    if (null == list)
                        list = new CoordinateTransformList<CoordinateTransform>();
                    list.add(am);
                }
                ImageProcessor ip;
                if (null != list) {
                    final TransformMesh mesh = new TransformMesh(list, meshResolution, o_width, o_height);
                    final TransformMeshMapping mapping = new TransformMeshMapping(mesh);
                    ip = mapping.createMappedImageInterpolated(getImageProcessor());
                } else {
                    ip = getImageProcessor();
                }
                new ImagePlus(this.title, ip).copy(false);
            }
            ke.consume();
            break;
        case KeyEvent.VK_F:
            // fill mask with current ROI using
            if (null != roi && M.isAreaROI(roi)) {
                Bureaucrat.createAndStart(new Worker.Task("Filling image mask") {

                    @Override
                    public void exec() {
                        getLayerSet().addDataEditStep(Patch.this);
                        if (0 == mod) {
                            addAlphaMask(roi, ProjectToolbar.getForegroundColorValue());
                        } else if (0 == (mod ^ Event.SHIFT_MASK)) {
                            // shift is down: fill outside
                            try {
                                final Area localRoi = M.areaInInts(M.getArea(roi)).createTransformedArea(at.createInverse());
                                final Area invLocalRoi = new Area(new Rectangle(0, 0, getOWidth(), getOHeight()));
                                invLocalRoi.subtract(localRoi);
                                addAlphaMaskLocal(invLocalRoi, ProjectToolbar.getForegroundColorValue());
                            } catch (final NoninvertibleTransformException e) {
                                IJError.print(e);
                                return;
                            }
                        }
                        getLayerSet().addDataEditStep(Patch.this);
                        // wait
                        try {
                            updateMipMaps().get();
                        } catch (final Throwable t) {
                            IJError.print(t);
                        }
                        Display.repaint();
                    }
                }, project);
            }
            // capturing:
            ke.consume();
            break;
        default:
            super.keyPressed(ke);
            break;
    }
}
Also used : TransformMeshMapping(mpicbg.trakem2.transform.TransformMeshMapping) CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) Rectangle(java.awt.Rectangle) ShapeRoi(ij.gui.ShapeRoi) Roi(ij.gui.Roi) ImagePlus(ij.ImagePlus) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) ImageProcessor(ij.process.ImageProcessor) Area(java.awt.geom.Area) AffineModel2D(mpicbg.trakem2.transform.AffineModel2D) Worker(ini.trakem2.utils.Worker) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform) TransformMesh(mpicbg.trakem2.transform.TransformMesh) CoordinateTransformMesh(mpicbg.models.CoordinateTransformMesh)

Example 7 with CoordinateTransformList

use of mpicbg.trakem2.transform.CoordinateTransformList in project TrakEM2 by trakem2.

the class Patch method getArea.

/**
 * Returns an Area in world coords representing the inside of this Patch. The fully alpha pixels are considered outside.
 */
@Override
public Area getArea() {
    CoordinateTransform ct = null;
    if (hasAlphaMask()) {
        // Read the mask as a ROI for the 0 pixels only and apply the AffineTransform to it:
        ImageProcessor alpha_mask = getAlphaMask();
        if (null == alpha_mask) {
            Utils.log2("Could not retrieve alpha mask for " + this);
        } else {
            if (hasCoordinateTransform()) {
                // must transform it
                ct = getCoordinateTransform();
                final TransformMesh mesh = new TransformMesh(ct, meshResolution, o_width, o_height);
                final TransformMeshMapping mapping = new TransformMeshMapping(mesh);
                // Without interpolation
                alpha_mask = mapping.createMappedImage(alpha_mask);
            // Keep in mind the affine of the Patch already contains the translation specified by the mesh bounds.
            }
            // Threshold all non-zero areas of the mask:
            alpha_mask.setThreshold(1, 255, ImageProcessor.NO_LUT_UPDATE);
            final ImagePlus imp = new ImagePlus("", alpha_mask);
            // TODO replace by our much faster method that scans by line, in AmiraImporter
            final ThresholdToSelection tts = new ThresholdToSelection();
            tts.setup("", imp);
            tts.run(alpha_mask);
            final Roi roi = imp.getRoi();
            if (null == roi) {
                // All pixels in the alpha mask have a value of zero
                return new Area();
            }
            return M.getArea(roi).createTransformedArea(this.at);
        }
    }
    // No alpha mask, or error in retrieving it:
    final int[] x = new int[o_width + o_width + o_height + o_height];
    final int[] y = new int[x.length];
    int next = 0;
    // Top edge:
    for (int i = 0; i <= o_width; i++, next++) {
        // len: o_width + 1
        x[next] = i;
        y[next] = 0;
    }
    // Right edge:
    for (int i = 1; i <= o_height; i++, next++) {
        // len: o_height
        x[next] = o_width;
        y[next] = i;
    }
    // bottom edge:
    for (int i = o_width - 1; i > -1; i--, next++) {
        // len: o_width
        x[next] = i;
        y[next] = o_height;
    }
    // left edge:
    for (int i = o_height - 1; i > 0; i--, next++) {
        // len: o_height -1
        x[next] = 0;
        y[next] = i;
    }
    if (hasCoordinateTransform() && null == ct)
        ct = getCoordinateTransform();
    if (null != ct) {
        final CoordinateTransformList<CoordinateTransform> t = new CoordinateTransformList<CoordinateTransform>();
        t.add(ct);
        final TransformMesh mesh = new TransformMesh(ct, meshResolution, o_width, o_height);
        final Rectangle box = mesh.getBoundingBox();
        final AffineTransform aff = new AffineTransform(this.at);
        // Must correct for the inverse of the mesh translation, because the affine also includes the translation.
        aff.translate(-box.x, -box.y);
        final AffineModel2D affm = new AffineModel2D();
        affm.set(aff);
        t.add(affm);
        /*
			 * WORKS FINE, but for points that fall outside the mesh, they don't get transformed!
			// Do it like Patch does it to generate the mipmap, with a mesh (and all the imprecisions of a mesh):
			final CoordinateTransformList t = new CoordinateTransformList();
			final TransformMesh mesh = new TransformMesh(this.ct, meshResolution, o_width, o_height);
			final AffineTransform aff = new AffineTransform(this.at);
			t.add(mesh);
			final AffineModel2D affm = new AffineModel2D();
			affm.set(aff);
			t.add(affm);
			*/
        final double[] f = new double[] { x[0], y[0] };
        t.applyInPlace(f);
        final Path2D.Float path = new Path2D.Float(Path2D.Float.WIND_EVEN_ODD, x.length + 1);
        path.moveTo(f[0], f[1]);
        for (int i = 1; i < x.length; i++) {
            f[0] = x[i];
            f[1] = y[i];
            t.applyInPlace(f);
            path.lineTo(f[0], f[1]);
        }
        // line to last call to moveTo
        path.closePath();
        return new Area(path);
    } else {
        return new Area(new Polygon(x, y, x.length)).createTransformedArea(this.at);
    }
}
Also used : TransformMeshMapping(mpicbg.trakem2.transform.TransformMeshMapping) CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) Path2D(java.awt.geom.Path2D) Rectangle(java.awt.Rectangle) ImagePlus(ij.ImagePlus) ShapeRoi(ij.gui.ShapeRoi) Roi(ij.gui.Roi) ImageProcessor(ij.process.ImageProcessor) Area(java.awt.geom.Area) AffineModel2D(mpicbg.trakem2.transform.AffineModel2D) AffineTransform(java.awt.geom.AffineTransform) ThresholdToSelection(ij.plugin.filter.ThresholdToSelection) Polygon(java.awt.Polygon) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform) TransformMesh(mpicbg.trakem2.transform.TransformMesh) CoordinateTransformMesh(mpicbg.models.CoordinateTransformMesh)

Example 8 with CoordinateTransformList

use of mpicbg.trakem2.transform.CoordinateTransformList in project TrakEM2 by trakem2.

the class Patch method getFullCoordinateTransform.

/**
 * Create a {@link CoordinateTransform} that incorporates both the
 * {@link CoordinateTransform} of this {@link Patch} (if present) and its
 * {@link AffineTransform}.  The returned {@link CoordinateTransform} directly
 * transfers the {@link Patch} into world coordinates.  An image can be rendered
 * e.g. using {@link mpicbg.ij.TransformMeshMapping} with an
 * {@link mpicbg.models.TransformMesh}.  Note that you may prefer to use
 * {@link mpicbg.models.TransformMesh} which does not perform auto-boxing as
 * opposed to {@link TransformMesh} in the mpicbg.trakem2 package.
 *
 * @return
 */
public final CoordinateTransform getFullCoordinateTransform() {
    final CoordinateTransform ctp = getCoordinateTransform();
    if (ctp == null) {
        final AffineModel2D affine = new AffineModel2D();
        affine.set(at);
        return affine;
    } else {
        final Rectangle box = getCoordinateTransformBoundingBox();
        final AffineTransform at2 = new AffineTransform(at);
        at2.translate(-box.x, -box.y);
        final AffineModel2D affine = new AffineModel2D();
        affine.set(at2);
        final CoordinateTransformList<CoordinateTransform> ctl = new CoordinateTransformList<CoordinateTransform>();
        ctl.add(ctp);
        ctl.add(affine);
        return ctl;
    }
}
Also used : CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) AffineModel2D(mpicbg.trakem2.transform.AffineModel2D) Rectangle(java.awt.Rectangle) AffineTransform(java.awt.geom.AffineTransform) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform)

Example 9 with CoordinateTransformList

use of mpicbg.trakem2.transform.CoordinateTransformList in project TrakEM2 by trakem2.

the class TMLHandler method makeCoordinateTransform.

private final void makeCoordinateTransform(String type, final HashMap<String, String> ht_attributes) {
    try {
        type = type.toLowerCase();
        if (type.equals("ict_transform")) {
            final CoordinateTransform ct = (CoordinateTransform) Class.forName(ht_attributes.get("class")).newInstance();
            ct.init(ht_attributes.get("data"));
            if (ct_list_stack.isEmpty()) {
                if (last_patch != null)
                    last_ct = ct;
            } else {
                ct_list_stack.get(ct_list_stack.size() - 1).add(ct);
            }
        } else if (type.equals("iict_transform")) {
            final InvertibleCoordinateTransform ict = (InvertibleCoordinateTransform) Class.forName(ht_attributes.get("class")).newInstance();
            ict.init(ht_attributes.get("data"));
            if (ct_list_stack.isEmpty()) {
                if (last_patch != null)
                    last_ct = ict;
                else if (last_stack != null)
                    last_ict = ict;
            } else {
                ct_list_stack.get(ct_list_stack.size() - 1).add(ict);
            }
        } else if (type.equals("ict_transform_list")) {
            final CoordinateTransformList<CoordinateTransform> ctl = new CoordinateTransformList<CoordinateTransform>();
            if (ct_list_stack.isEmpty()) {
                if (last_patch != null)
                    last_ct = ctl;
            } else
                ct_list_stack.get(ct_list_stack.size() - 1).add(ctl);
            ct_list_stack.add((TransformList) ctl);
        } else if (type.equals("iict_transform_list")) {
            final InvertibleCoordinateTransformList<InvertibleCoordinateTransform> ictl = new InvertibleCoordinateTransformList<InvertibleCoordinateTransform>();
            if (ct_list_stack.isEmpty()) {
                if (last_patch != null)
                    last_ct = ictl;
                else if (last_stack != null)
                    last_ict = ictl;
            } else
                ct_list_stack.get(ct_list_stack.size() - 1).add(ictl);
            ct_list_stack.add((TransformList) ictl);
        }
    } catch (Exception e) {
        IJError.print(e);
    }
}
Also used : InvertibleCoordinateTransformList(mpicbg.trakem2.transform.InvertibleCoordinateTransformList) InvertibleCoordinateTransform(mpicbg.trakem2.transform.InvertibleCoordinateTransform) InvertibleCoordinateTransformList(mpicbg.trakem2.transform.InvertibleCoordinateTransformList) CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) InvertibleCoordinateTransformList(mpicbg.trakem2.transform.InvertibleCoordinateTransformList) TransformList(mpicbg.models.TransformList) CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform) InvertibleCoordinateTransform(mpicbg.trakem2.transform.InvertibleCoordinateTransform) SAXException(org.xml.sax.SAXException) SAXParseException(org.xml.sax.SAXParseException)

Example 10 with CoordinateTransformList

use of mpicbg.trakem2.transform.CoordinateTransformList 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)

Aggregations

CoordinateTransform (mpicbg.trakem2.transform.CoordinateTransform)11 CoordinateTransformList (mpicbg.trakem2.transform.CoordinateTransformList)11 Rectangle (java.awt.Rectangle)9 AffineTransform (java.awt.geom.AffineTransform)8 AffineModel2D (mpicbg.trakem2.transform.AffineModel2D)6 ImageProcessor (ij.process.ImageProcessor)5 AbstractAffineModel2D (mpicbg.models.AbstractAffineModel2D)4 AffineModel2D (mpicbg.models.AffineModel2D)4 CoordinateTransformMesh (mpicbg.models.CoordinateTransformMesh)4 ImagePlus (ij.ImagePlus)3 Layer (ini.trakem2.display.Layer)3 Patch (ini.trakem2.display.Patch)3 Area (java.awt.geom.Area)3 NoninvertibleTransformException (java.awt.geom.NoninvertibleTransformException)3 ArrayList (java.util.ArrayList)3 NotEnoughDataPointsException (mpicbg.models.NotEnoughDataPointsException)3 Point (mpicbg.models.Point)3 Roi (ij.gui.Roi)2 ShapeRoi (ij.gui.ShapeRoi)2 ByteProcessor (ij.process.ByteProcessor)2