Search in sources :

Example 26 with PointMatch

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

the class Distortion_Correction method extractSIFTPoints.

protected void extractSIFTPoints(final int index, final List<Feature>[] siftFeatures, final List<List<PointMatch>> inliers, final List<AbstractAffineModel2D<?>> models) {
    // save all matching candidates
    final List<List<PointMatch>> candidates = new ArrayList<List<PointMatch>>();
    for (int j = 0; j < siftFeatures.length; j++) {
        if (index == j)
            continue;
        candidates.add(FloatArray2DSIFT.createMatches(siftFeatures[index], siftFeatures[j], 1.5f, null, Float.MAX_VALUE, 0.5f));
    }
    // get rid of the outliers and save the transformations to match the inliers
    for (int i = 0; i < candidates.size(); ++i) {
        final List<PointMatch> tmpInliers = new ArrayList<PointMatch>();
        final AbstractAffineModel2D<?> m;
        switch(sp.expectedModelIndex) {
            case 0:
                m = new TranslationModel2D();
                break;
            case 1:
                m = new RigidModel2D();
                break;
            case 2:
                m = new SimilarityModel2D();
                break;
            case 3:
                m = new AffineModel2D();
                break;
            default:
                return;
        }
        try {
            m.filterRansac(candidates.get(i), tmpInliers, 1000, sp.maxEpsilon, sp.minInlierRatio, 10);
        } catch (final NotEnoughDataPointsException e) {
            e.printStackTrace();
        }
        inliers.add(tmpInliers);
        models.add(m);
    }
}
Also used : PointMatch(mpicbg.models.PointMatch) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) RigidModel2D(mpicbg.models.RigidModel2D) ArrayList(java.util.ArrayList) AbstractAffineModel2D(mpicbg.models.AbstractAffineModel2D) AffineModel2D(mpicbg.models.AffineModel2D) ArrayList(java.util.ArrayList) List(java.util.List) TranslationModel2D(mpicbg.models.TranslationModel2D) SimilarityModel2D(mpicbg.models.SimilarityModel2D)

Example 27 with PointMatch

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

the class Distortion_Correction method createInverseDistortionModel.

/**
 * Estimates a polynomial distortion model for a set of
 * {@linkplain PointMatch corresponding points} and returns the inverse of
 * this model which then may be used to undo the distortion.
 *
 * @param pointMatches
 *   a list of matches, plus affines that transfer each match
 *   into a common image frame
 * @param dimension the order of the polynomial model
 * @param lambda regularization factor
 * @param imageWidth
 * @param imageHeight
 *
 * @return a polynomial distortion model to undo the distortion
 */
public static NonLinearTransform createInverseDistortionModel(final Collection<PointMatchCollectionAndAffine> pointMatches, final int dimension, final double lambda, final int imageWidth, final int imageHeight) {
    int wholeCount = 0;
    for (final PointMatchCollectionAndAffine pma : pointMatches) if (pma.pointMatches.size() > 10)
        wholeCount += pma.pointMatches.size();
    final double[][] tp = new double[wholeCount][6];
    final double[][] h1 = new double[wholeCount][2];
    final double[][] h2 = new double[wholeCount][2];
    int count = 0;
    for (final PointMatchCollectionAndAffine pma : pointMatches) {
        if (pma.pointMatches.size() > 10) {
            int i = 0;
            for (final PointMatch match : pma.pointMatches) {
                final double[] tmp1 = match.getP1().getL();
                final double[] tmp2 = match.getP2().getL();
                h1[count] = new double[] { (double) tmp1[0], (double) tmp1[1] };
                h2[count] = new double[] { (double) tmp2[0], (double) tmp2[1] };
                pma.affine.getMatrix(tp[count]);
                count++;
                ++i;
            }
        }
    }
    final NonLinearTransform nlt = distortionCorrection(h1, h2, tp, dimension, lambda, imageWidth, imageHeight);
    nlt.inverseTransform(h1);
    return nlt;
}
Also used : PointMatch(mpicbg.models.PointMatch)

Example 28 with PointMatch

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

the class BlockMatchPairCallable method call.

@Override
public BlockMatchResults call() throws Exception {
    final ArrayList<PointMatch> pm12 = new ArrayList<PointMatch>();
    final ArrayList<PointMatch> pm21 = new ArrayList<PointMatch>();
    System.out.println("BMC rev 0: " + pair.a + " " + pair.b);
    final Pair<FloatProcessor, FloatProcessor> pair1 = makeFlatImage(layer1, AlignmentUtils.filterPatches(layer1, filter), box, param.layerScale);
    final Pair<FloatProcessor, FloatProcessor> pair2 = makeFlatImage(layer2, AlignmentUtils.filterPatches(layer2, filter), box, param.layerScale);
    final FloatProcessor ip1 = pair1.a;
    final FloatProcessor ip1Mask = pair1.b;
    final FloatProcessor ip2 = pair2.a;
    final FloatProcessor ip2Mask = pair2.b;
    final AbstractModel<?> localSmoothnessFilterModel = Util.createModel(param.localModelIndex);
    final int blockRadius = Math.max(16, mpicbg.util.Util.roundPos(param.layerScale * param.blockRadius));
    /* scale pixel distances */
    final int searchRadius = (int) Math.round(param.layerScale * param.searchRadius);
    final double localRegionSigma = param.layerScale * param.localRegionSigma;
    final double maxLocalEpsilon = param.layerScale * param.maxLocalEpsilon;
    if (!layer1Fixed) {
        BlockMatching.matchByMaximalPMCC(ip1, ip2, ip1Mask, ip2Mask, 1.0, ((InvertibleCoordinateTransform) pair.c).createInverse(), blockRadius, blockRadius, searchRadius, searchRadius, param.minR, param.rodR, param.maxCurvatureR, v1, pm12, new ErrorStatistic(1));
        if (Thread.interrupted()) {
            throw new InterruptedException("Block matching interrupted.");
        }
        if (param.useLocalSmoothnessFilter) {
            localSmoothnessFilterModel.localSmoothnessFilter(pm12, pm12, localRegionSigma, maxLocalEpsilon, param.maxLocalTrust);
        }
    }
    if (!layer2Fixed) {
        BlockMatching.matchByMaximalPMCC(ip2, ip1, ip2Mask, ip1Mask, 1.0f, pair.c, blockRadius, blockRadius, searchRadius, searchRadius, param.minR, param.rodR, param.maxCurvatureR, v2, pm21, new ErrorStatistic(1));
        if (Thread.interrupted()) {
            throw new InterruptedException("Block matching interrupted.");
        }
        if (param.useLocalSmoothnessFilter) {
            localSmoothnessFilterModel.localSmoothnessFilter(pm21, pm21, localRegionSigma, maxLocalEpsilon, param.maxLocalTrust);
        }
    }
    return new BlockMatchResults(v1, v2, pm12, pm21, layer1Fixed, layer2Fixed, pair);
}
Also used : PointMatch(mpicbg.models.PointMatch) FloatProcessor(ij.process.FloatProcessor) ErrorStatistic(mpicbg.models.ErrorStatistic) ArrayList(java.util.ArrayList) Point(mpicbg.models.Point)

Example 29 with PointMatch

use of mpicbg.models.PointMatch 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 30 with PointMatch

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

the class Align method alignLayersLinearly.

/**
 * Align a range of layers by accumulating pairwise alignments of contiguous layers.
 *
 * @param layers The range of layers to align pairwise.
 * @param numThreads The number of threads to use.
 * @param filter The {@link Filter} to decide which {@link Patch} instances to use in each {@link Layer}. Can be null.
 */
public static final void alignLayersLinearly(final List<Layer> layers, final int numThreads, final Filter<Patch> filter) {
    param.sift.maxOctaveSize = 1600;
    if (!param.setup("Align layers linearly"))
        return;
    final Rectangle box = layers.get(0).getParent().getMinimalBoundingBox(Patch.class);
    final double scale = Math.min(1.0, Math.min((double) param.sift.maxOctaveSize / box.width, (double) param.sift.maxOctaveSize / box.height));
    final Param p = param.clone();
    p.maxEpsilon *= scale;
    final FloatArray2DSIFT sift = new FloatArray2DSIFT(p.sift);
    final SIFT ijSIFT = new SIFT(sift);
    Rectangle box1 = null;
    Rectangle box2 = null;
    final Collection<Feature> features1 = new ArrayList<Feature>();
    final Collection<Feature> features2 = new ArrayList<Feature>();
    final List<PointMatch> candidates = new ArrayList<PointMatch>();
    final List<PointMatch> inliers = new ArrayList<PointMatch>();
    final AffineTransform a = new AffineTransform();
    int i = 0;
    for (final Layer l : layers) {
        long s = System.currentTimeMillis();
        features1.clear();
        features1.addAll(features2);
        features2.clear();
        final Rectangle box3 = l.getMinimalBoundingBox(Patch.class);
        if (box3 == null)
            continue;
        box1 = box2;
        box2 = box3;
        final List<Patch> patches = l.getAll(Patch.class);
        if (null != filter) {
            for (final Iterator<Patch> it = patches.iterator(); it.hasNext(); ) {
                if (!filter.accept(it.next()))
                    it.remove();
            }
        }
        ijSIFT.extractFeatures(l.getProject().getLoader().getFlatImage(l, box2, scale, 0xffffffff, ImagePlus.GRAY8, Patch.class, patches, true).getProcessor(), features2);
        Utils.log(features2.size() + " features extracted in layer \"" + l.getTitle() + "\" (took " + (System.currentTimeMillis() - s) + " ms).");
        if (features1.size() > 0) {
            s = System.currentTimeMillis();
            candidates.clear();
            FeatureTransform.matchFeatures(features2, features1, candidates, p.rod);
            final AbstractAffineModel2D<?> model;
            switch(p.expectedModelIndex) {
                case 0:
                    model = new TranslationModel2D();
                    break;
                case 1:
                    model = new RigidModel2D();
                    break;
                case 2:
                    model = new SimilarityModel2D();
                    break;
                case 3:
                    model = new AffineModel2D();
                    break;
                default:
                    return;
            }
            boolean modelFound;
            boolean again = false;
            try {
                do {
                    again = false;
                    modelFound = model.filterRansac(candidates, inliers, 1000, p.maxEpsilon, p.minInlierRatio, p.minNumInliers, 3);
                    if (modelFound && p.rejectIdentity) {
                        final ArrayList<Point> points = new ArrayList<Point>();
                        PointMatch.sourcePoints(inliers, points);
                        if (Transforms.isIdentity(model, points, p.identityTolerance)) {
                            Utils.log("Identity transform for " + inliers.size() + " matches rejected.");
                            candidates.removeAll(inliers);
                            inliers.clear();
                            again = true;
                        }
                    }
                } while (again);
            } catch (final NotEnoughDataPointsException e) {
                modelFound = false;
            }
            if (modelFound) {
                Utils.log("Model found for layer \"" + l.getTitle() + "\" and its predecessor:\n  correspondences  " + inliers.size() + " of " + candidates.size() + "\n  average residual error  " + (model.getCost() / scale) + " px\n  took " + (System.currentTimeMillis() - s) + " ms");
                final AffineTransform b = new AffineTransform();
                b.translate(box1.x, box1.y);
                b.scale(1.0f / scale, 1.0f / scale);
                b.concatenate(model.createAffine());
                b.scale(scale, scale);
                b.translate(-box2.x, -box2.y);
                a.concatenate(b);
                l.apply(Displayable.class, a);
                Display.repaint(l);
            } else {
                Utils.log("No model found for layer \"" + l.getTitle() + "\" and its predecessor:\n  correspondence candidates  " + candidates.size() + "\n  took " + (System.currentTimeMillis() - s) + " ms");
                a.setToIdentity();
            }
        }
        IJ.showProgress(++i, layers.size());
    }
}
Also used : NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) SIFT(mpicbg.ij.SIFT) FloatArray2DSIFT(mpicbg.imagefeatures.FloatArray2DSIFT) Rectangle(java.awt.Rectangle) ArrayList(java.util.ArrayList) Feature(mpicbg.imagefeatures.Feature) RigidModel2D(mpicbg.trakem2.transform.RigidModel2D) AbstractAffineModel2D(mpicbg.models.AbstractAffineModel2D) AffineModel2D(mpicbg.models.AffineModel2D) InterpolatedAffineModel2D(mpicbg.models.InterpolatedAffineModel2D) SimilarityModel2D(mpicbg.models.SimilarityModel2D) Point(mpicbg.models.Point) Layer(ini.trakem2.display.Layer) Point(mpicbg.models.Point) FloatArray2DSIFT(mpicbg.imagefeatures.FloatArray2DSIFT) PointMatch(mpicbg.models.PointMatch) AffineTransform(java.awt.geom.AffineTransform) TranslationModel2D(mpicbg.trakem2.transform.TranslationModel2D) Patch(ini.trakem2.display.Patch)

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