Search in sources :

Example 6 with TranslationModel2D

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

the class MovingLeastSquaresTransform method init.

@Override
public final void init(final String data) throws NumberFormatException {
    matches.clear();
    final String[] fields = data.split("\\s+");
    if (fields.length > 3) {
        final int d = Integer.parseInt(fields[1]);
        if ((fields.length - 3) % (2 * d + 1) == 0) {
            if (d == 2) {
                if (fields[0].equals("translation"))
                    model = new TranslationModel2D();
                else if (fields[0].equals("rigid"))
                    model = new RigidModel2D();
                else if (fields[0].equals("similarity"))
                    model = new SimilarityModel2D();
                else if (fields[0].equals("affine"))
                    model = new AffineModel2D();
                else
                    throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
            } else if (d == 3) {
                if (fields[0].equals("affine"))
                    model = new AffineModel3D();
                else
                    throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
            } else
                throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
            alpha = Double.parseDouble(fields[2]);
            int i = 2;
            while (i < fields.length - 1) {
                final double[] p1 = new double[d];
                for (int k = 0; k < d; ++k) p1[k] = Double.parseDouble(fields[++i]);
                final double[] p2 = new double[d];
                for (int k = 0; k < d; ++k) p2[k] = Double.parseDouble(fields[++i]);
                final double weight = Double.parseDouble(fields[++i]);
                final PointMatch m = new PointMatch(new Point(p1), new Point(p2), weight);
                matches.add(m);
            }
        } else
            throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
    } else
        throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
}
Also used : Point(mpicbg.models.Point) Point(mpicbg.models.Point) PointMatch(mpicbg.models.PointMatch) RigidModel2D(mpicbg.models.RigidModel2D) AffineModel2D(mpicbg.models.AffineModel2D) TranslationModel2D(mpicbg.models.TranslationModel2D) SimilarityModel2D(mpicbg.models.SimilarityModel2D) AffineModel3D(mpicbg.models.AffineModel3D)

Example 7 with TranslationModel2D

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

the class MovingLeastSquaresTransform2 method init2.

public void init2(final String s) throws Exception {
    // WARNING: assumes all whitespace is single
    final int len = s.length();
    int i = 0;
    // Advance to the first white space
    while (' ' != s.charAt(++i)) {
    }
    // Interpret model by the last letter of the name
    final char modelLastChar = s.charAt(i - 1);
    // Determine dimension 2 or 3
    final int n = (s.charAt(i + 1)) - 48;
    switch(n) {
        case 3:
            model = new AffineModel3D();
            break;
        case 2:
            switch(modelLastChar) {
                case // translation
                'n':
                    model = new TranslationModel2D();
                    break;
                case // rigid
                'd':
                    model = new RigidModel2D();
                    break;
                case // similarity
                'y':
                    model = new SimilarityModel2D();
                    break;
                case // affine
                'e':
                    model = new AffineModel2D();
                    break;
                default:
                    throw new Exception("Unknown model " + s.substring(0, i));
            }
            break;
        default:
            throw new NumberFormatException("Unsupported model dimensions: " + n + " for " + this.getClass().getCanonicalName());
    }
    // 'i' is at whitespace before n
    // Move i to whitespace before alpha
    i += 2;
    // Mark last char before whitespace
    int cut = i - 1;
    // 'i' ends up at the whitespace after alpha
    while (' ' != s.charAt(++i)) {
    }
    // Parse alpha
    float[] f = new float[1];
    parse(s, cut, i - 1, f, 0);
    this.alpha = f[0];
    // Count numbers by counting one whitespace before each number
    int nVals = 0;
    for (int k = i; k < len; ++k) {
        if (' ' == s.charAt(k))
            ++nVals;
    }
    // The size of a unit of numbers
    final int cell = n + n + 1;
    // Detect inconsistency:
    if (0 != nVals % cell) {
        throw new NumberFormatException("Inappropriate parameters for " + this.getClass().getCanonicalName());
    }
    // Create arrays
    this.p = new float[n][nVals / cell];
    this.q = new float[n][this.p[0].length];
    this.w = new float[this.p[0].length];
    // Mark the whitespace char before the first number
    cut = i - 1;
    // Start parsing from the end
    i = len - 1;
    int count = 0;
    if (2 == n) {
        while (i > cut) {
            // Determine which array from {p,q,w} and which position in the array, using n and count:
            switch(// n for dimensions, +1 for the weight
            count % cell) {
                case 0:
                    f = this.w;
                    break;
                case 1:
                    f = this.q[1];
                    break;
                case 2:
                    f = this.q[0];
                    break;
                case 3:
                    f = this.p[1];
                    break;
                case 4:
                    f = this.p[0];
                    break;
            }
            i = parse(s, cut, i, f, this.w.length - (count / cell) - 1);
            ++count;
        }
    } else {
        while (i > cut) {
            // Determine which array from {p,q,w} and which position in the array, using n and count:
            switch(// n for dimensions, +1 for the weight
            count % (n + n + 1)) {
                case 0:
                    f = this.w;
                    break;
                case 1:
                    f = this.q[2];
                    break;
                case 2:
                    f = this.q[1];
                    break;
                case 3:
                    f = this.q[0];
                    break;
                case 4:
                    f = this.p[2];
                    break;
                case 5:
                    f = this.p[1];
                    break;
                case 6:
                    f = this.p[0];
                    break;
            }
            i = parse(s, cut, i, f, this.w.length - (count / cell) - 1);
            ++count;
        }
    }
}
Also used : RigidModel2D(mpicbg.models.RigidModel2D) AffineModel2D(mpicbg.models.AffineModel2D) TranslationModel2D(mpicbg.models.TranslationModel2D) SimilarityModel2D(mpicbg.models.SimilarityModel2D) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) IllDefinedDataPointsException(mpicbg.models.IllDefinedDataPointsException) AffineModel3D(mpicbg.models.AffineModel3D)

Example 8 with TranslationModel2D

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

the class StitchingTEM method montageWithPhaseCorrelation.

/**
 * Perform montage based on phase correlation
 * @param col collection of patches
 * @param param phase correlation parameters
 */
public static void montageWithPhaseCorrelation(final Collection<Patch> col, final PhaseCorrelationParam param) {
    if (null == col || col.size() < 1)
        return;
    final ArrayList<Patch> al = new ArrayList<Patch>(col);
    final ArrayList<AbstractAffineTile2D<?>> tiles = new ArrayList<AbstractAffineTile2D<?>>();
    final ArrayList<AbstractAffineTile2D<?>> fixed_tiles = new ArrayList<AbstractAffineTile2D<?>>();
    for (final Patch p : al) {
        // Pre-check: just a warning
        final int aff_type = p.getAffineTransform().getType();
        switch(p.getAffineTransform().getType()) {
            case AffineTransform.TYPE_IDENTITY:
            case AffineTransform.TYPE_TRANSLATION:
                // ok
                break;
            default:
                Utils.log2("WARNING: patch with a non-translation transform: " + p);
                break;
        }
        // create tiles
        final TranslationTile2D tile = new TranslationTile2D(new TranslationModel2D(), p);
        tiles.add(tile);
        if (p.isLocked2()) {
            Utils.log("Added fixed (locked) tile " + p);
            fixed_tiles.add(tile);
        }
    }
    // Get acceptable values
    double cc_scale = param.cc_scale;
    if (cc_scale < 0 || cc_scale > 1) {
        Utils.log("Unacceptable cc_scale of " + param.cc_scale + ". Using 1 instead.");
        cc_scale = 1;
    }
    float overlap = param.overlap;
    if (overlap < 0 || overlap > 1) {
        Utils.log("Unacceptable overlap of " + param.overlap + ". Using 1 instead.");
        overlap = 1;
    }
    for (int i = 0; i < al.size(); i++) {
        final Patch p1 = al.get(i);
        final Rectangle r1 = p1.getBoundingBox();
        // find overlapping, add as connections
        for (int j = i + 1; j < al.size(); j++) {
            if (Thread.currentThread().isInterrupted())
                return;
            final Patch p2 = al.get(j);
            final Rectangle r2 = p2.getBoundingBox();
            if (r1.intersects(r2)) {
                // Skip if it's a diagonal overlap
                final int dx = Math.abs(r1.x - r2.x);
                final int dy = Math.abs(r1.y - r2.y);
                if (dx > r1.width / 2 && dy > r1.height / 2) {
                    // skip diagonal match
                    Utils.log2("Skipping diagonal overlap between " + p1 + " and " + p2);
                    continue;
                }
                p1.getProject().getLoader().releaseToFit((long) (p1.getWidth() * p1.getHeight() * 25));
                final double[] R;
                if (1 == overlap) {
                    R = correlate(p1, p2, overlap, cc_scale, TOP_BOTTOM, 0, 0, param.min_R);
                    if (SUCCESS == R[2]) {
                        addMatches(tiles.get(i), tiles.get(j), R[0], R[1]);
                    }
                } else {
                    switch(getClosestOverlapLocation(p1, p2)) {
                        case // p1 overlaps p2 from the left
                        0:
                            R = correlate(p1, p2, overlap, cc_scale, LEFT_RIGHT, 0, 0, param.min_R);
                            if (SUCCESS == R[2]) {
                                addMatches(tiles.get(i), tiles.get(j), R[0], R[1]);
                            }
                            break;
                        case // p1 overlaps p2 from the top
                        1:
                            R = correlate(p1, p2, overlap, cc_scale, TOP_BOTTOM, 0, 0, param.min_R);
                            if (SUCCESS == R[2]) {
                                addMatches(tiles.get(i), tiles.get(j), R[0], R[1]);
                            }
                            break;
                        case // p1 overlaps p2 from the right
                        2:
                            R = correlate(p2, p1, overlap, cc_scale, LEFT_RIGHT, 0, 0, param.min_R);
                            if (SUCCESS == R[2]) {
                                addMatches(tiles.get(j), tiles.get(i), R[0], R[1]);
                            }
                            break;
                        case // p1 overlaps p2 from the bottom
                        3:
                            R = correlate(p2, p1, overlap, cc_scale, TOP_BOTTOM, 0, 0, param.min_R);
                            if (SUCCESS == R[2]) {
                                addMatches(tiles.get(j), tiles.get(i), R[0], R[1]);
                            }
                            break;
                        default:
                            Utils.log("Unknown overlap direction!");
                            continue;
                    }
                }
            }
        }
    }
    if (param.remove_disconnected || param.hide_disconnected) {
        for (final Iterator<AbstractAffineTile2D<?>> it = tiles.iterator(); it.hasNext(); ) {
            final AbstractAffineTile2D<?> t = it.next();
            if (null != t.getMatches() && t.getMatches().isEmpty()) {
                if (param.hide_disconnected)
                    t.getPatch().setVisible(false);
                else if (param.remove_disconnected)
                    t.getPatch().remove(false);
                it.remove();
            }
        }
    }
    // Optimize tile configuration by removing bad matches
    optimizeTileConfiguration(tiles, fixed_tiles, param);
    for (final AbstractAffineTile2D<?> t : tiles) t.getPatch().setAffineTransform(t.getModel().createAffine());
    try {
        Display.repaint(al.get(0).getLayer());
    } catch (final Exception e) {
    }
}
Also used : TranslationTile2D(mpicbg.trakem2.align.TranslationTile2D) AbstractAffineTile2D(mpicbg.trakem2.align.AbstractAffineTile2D) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) Point(mpicbg.models.Point) TranslationModel2D(mpicbg.models.TranslationModel2D) Patch(ini.trakem2.display.Patch)

Example 9 with TranslationModel2D

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

the class Distortion_Correction method extractSIFTPointsThreaded.

protected static void extractSIFTPointsThreaded(final int index, final List<Feature>[] siftFeatures, final List<PointMatch>[] inliers, final AbstractAffineModel2D<?>[] models) {
    // save all matching candidates
    final List<PointMatch>[] candidates = new List[siftFeatures.length - 1];
    final Thread[] threads = MultiThreading.newThreads();
    // start at second
    final AtomicInteger ai = new AtomicInteger(0);
    for (int ithread = 0; ithread < threads.length; ++ithread) {
        threads[ithread] = new Thread() {

            @Override
            public void run() {
                setPriority(Thread.NORM_PRIORITY);
                for (int j = ai.getAndIncrement(); j < candidates.length; j = ai.getAndIncrement()) {
                    final int i = (j < index ? j : j + 1);
                    candidates[j] = FloatArray2DSIFT.createMatches(siftFeatures[index], siftFeatures[i], 1.5f, null, Float.MAX_VALUE, 0.5f);
                }
            }
        };
    }
    MultiThreading.startAndJoin(threads);
    // get rid of the outliers and save the rigid transformations to match
    // the inliers
    final AtomicInteger ai2 = new AtomicInteger(0);
    for (int ithread = 0; ithread < threads.length; ++ithread) {
        threads[ithread] = new Thread() {

            @Override
            public void run() {
                setPriority(Thread.NORM_PRIORITY);
                for (int i = ai2.getAndIncrement(); i < candidates.length; i = ai2.getAndIncrement()) {
                    final List<PointMatch> tmpInliers = new ArrayList<PointMatch>();
                    // RigidModel2D m =
                    // RigidModel2D.estimateBestModel(candidates.get(i),
                    // tmpInliers, sp.min_epsilon, sp.max_epsilon,
                    // sp.min_inlier_ratio);
                    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;
                    }
                    boolean modelFound = false;
                    try {
                        modelFound = m.filterRansac(candidates[i], tmpInliers, 1000, sp.maxEpsilon, sp.minInlierRatio, 10);
                    } catch (final NotEnoughDataPointsException e) {
                        modelFound = false;
                    }
                    if (modelFound)
                        IJ.log("Model found:\n  " + candidates[i].size() + " candidates\n  " + tmpInliers.size() + " inliers\n  " + String.format("%.2f", m.getCost()) + "px average displacement");
                    else
                        IJ.log("No Model found.");
                    inliers[index * (sp.numberOfImages - 1) + i] = tmpInliers;
                    models[index * (sp.numberOfImages - 1) + i] = m;
                // System.out.println("**** MODEL ADDED: " +
                // (index*(sp.numberOfImages-1)+i));
                }
            }
        };
    }
    MultiThreading.startAndJoin(threads);
}
Also used : NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) AbstractAffineModel2D(mpicbg.models.AbstractAffineModel2D) PointMatch(mpicbg.models.PointMatch) RigidModel2D(mpicbg.models.RigidModel2D) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) 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 10 with TranslationModel2D

use of mpicbg.models.TranslationModel2D 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)

Aggregations

TranslationModel2D (mpicbg.models.TranslationModel2D)12 AffineModel2D (mpicbg.models.AffineModel2D)9 RigidModel2D (mpicbg.models.RigidModel2D)9 SimilarityModel2D (mpicbg.models.SimilarityModel2D)9 ArrayList (java.util.ArrayList)8 Point (mpicbg.models.Point)7 NotEnoughDataPointsException (mpicbg.models.NotEnoughDataPointsException)6 PointMatch (mpicbg.models.PointMatch)6 AbstractAffineModel2D (mpicbg.models.AbstractAffineModel2D)4 Patch (ini.trakem2.display.Patch)3 Rectangle (java.awt.Rectangle)3 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)3 Triple (mpicbg.trakem2.util.Triple)3 ByteProcessor (ij.process.ByteProcessor)2 Layer (ini.trakem2.display.Layer)2 HashMap (java.util.HashMap)2 List (java.util.List)2 Map (java.util.Map)2 AbstractModel (mpicbg.models.AbstractModel)2 AffineModel3D (mpicbg.models.AffineModel3D)2