Search in sources :

Example 1 with TransformMesh

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

the class Blending method blendPatches.

public static final void blendPatches(final Set<Patch> patches, final boolean respect_current_mask) {
    ExecutorService exe = null;
    try {
        if (null == patches || patches.size() < 2)
            return;
        final Layer layer = patches.iterator().next().getLayer();
        for (final Patch p : patches) {
            if (null != p.getCoordinateTransform()) {
                Utils.log("CANNOT blend: at least one image has a coordinate transform.\nBlending of coordinate-transformed images will be enabled in the near future.");
                return;
            }
            if (p.getLayer() != layer) {
                Utils.log("CANNOT blend: all images must belong to the same layer!\n  Otherwise the overlap cannot be computed.");
                return;
            }
        }
        final HashMap<Patch, TransformMesh> meshes = new HashMap<Patch, TransformMesh>();
        for (final Patch p : patches) {
            meshes.put(p, null == p.getCoordinateTransform() ? null : new TransformMesh(p.getCoordinateTransform(), p.getMeshResolution(), p.getOWidth(), p.getOHeight()));
        }
        exe = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        final List<Future<?>> futures = Collections.synchronizedList(new ArrayList<Future<?>>());
        final List<Future<?>> futures2 = Collections.synchronizedList(new ArrayList<Future<?>>());
        // Cache the indices that determine overlap order within the layer
        final HashMap<Patch, Integer> indices = new HashMap<Patch, Integer>();
        int i = 0;
        for (final Displayable d : layer.getDisplayables()) {
            if (d.getClass() == Patch.class && patches.contains((Patch) d)) {
                indices.put((Patch) d, i);
            }
            i += 1;
        }
        for (final Patch p : patches) {
            if (Thread.currentThread().isInterrupted())
                break;
            futures.add(exe.submit(new Runnable() {

                @Override
                public void run() {
                    final int pLayerIndex = indices.get(p);
                    final Set<Patch> overlapping = new HashSet<Patch>();
                    for (final Patch op : patches) {
                        if (indices.get(op) < pLayerIndex)
                            overlapping.add(op);
                    }
                    if (setBlendingMask(p, overlapping, meshes, respect_current_mask)) {
                        futures2.add(p.updateMipMaps());
                    }
                }
            }, null));
        }
        // join all:
        Utils.waitIfAlive(futures, false);
        Utils.waitIfAlive(futures2, false);
    } catch (final Exception e) {
        IJError.print(e);
    } finally {
        if (null != exe)
            exe.shutdown();
        Display.repaint();
    }
}
Also used : Displayable(ini.trakem2.display.Displayable) HashMap(java.util.HashMap) Layer(ini.trakem2.display.Layer) NoninvertibleModelException(mpicbg.models.NoninvertibleModelException) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) ExecutorService(java.util.concurrent.ExecutorService) Future(java.util.concurrent.Future) Patch(ini.trakem2.display.Patch) TransformMesh(mpicbg.trakem2.transform.TransformMesh) HashSet(java.util.HashSet)

Example 2 with TransformMesh

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

the class NonLinearTransformMode method mousePressed.

@Override
public void mousePressed(final MouseEvent me, final int x_p, final int y_p, final double magnification) {
    /* find if clicked on a point */
    p_clicked = null;
    double min = Double.MAX_VALUE;
    final Point mouse = new Point(new double[] { x_p, y_p });
    final double a = 64.0 / magnification / magnification;
    for (final Point p : points) {
        final double sd = Point.squareDistance(p, mouse);
        if (sd < min && sd < a) {
            p_clicked = p;
            min = sd;
        }
    }
    if (me.isShiftDown()) {
        if (null == p_clicked) {
            /* add one */
            try {
                if (points.size() > 0) {
                    /*
						 * Create a pseudo-invertible (TransformMesh) for the screen.
						 */
                    final CoordinateTransform mlst = createCT();
                    final SimilarityModel2D toWorld = new SimilarityModel2D();
                    toWorld.set(1.0 / magnification, 0, srcRect.x, srcRect.y);
                    final SimilarityModel2D toScreen = toWorld.createInverse();
                    final mpicbg.models.CoordinateTransformList<mpicbg.models.CoordinateTransform> ctl = new mpicbg.models.CoordinateTransformList<mpicbg.models.CoordinateTransform>();
                    ctl.add(toWorld);
                    ctl.add(mlst);
                    ctl.add(toScreen);
                    final CoordinateTransformMesh ctm = new CoordinateTransformMesh(ctl, 32, (int) Math.ceil(srcRect.width * magnification), (int) Math.ceil(srcRect.height * magnification));
                    final double[] l = mouse.getL();
                    toScreen.applyInPlace(l);
                    ctm.applyInverseInPlace(l);
                    toWorld.applyInPlace(l);
                }
                points.add(mouse);
                p_clicked = mouse;
            } catch (final Exception e) {
                Utils.log("Could not add point");
                e.printStackTrace();
            }
        } else if (Utils.isControlDown(me)) {
            // remove it
            points.remove(p_clicked);
            p_clicked = null;
        }
    }
}
Also used : CoordinateTransformMesh(mpicbg.models.CoordinateTransformMesh) CoordinateTransformList(mpicbg.trakem2.transform.CoordinateTransformList) Point(mpicbg.models.Point) SimilarityModel2D(mpicbg.models.SimilarityModel2D) CoordinateTransform(mpicbg.trakem2.transform.CoordinateTransform) NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) NoninvertibleModelException(mpicbg.models.NoninvertibleModelException) IllDefinedDataPointsException(mpicbg.models.IllDefinedDataPointsException)

Example 3 with TransformMesh

use of mpicbg.trakem2.transform.TransformMesh 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 4 with TransformMesh

use of mpicbg.trakem2.transform.TransformMesh 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 5 with TransformMesh

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

the class Patch method toPixelCoordinate.

/**
 * @see Patch#toPixelCoordinate(double, double)
 * @param world_x The X of the world coordinate (in pixels, uncalibrated)
 * @param world_y The Y of the world coordinate (in pixels, uncalibrated)
 * @param aff The {@link AffineTransform} of the {@link Patch}.
 * @param ct The {@link CoordinateTransform} of the {@link Patch}, if any (can be null).
 * @param meshResolution The precision demanded for approximating a transform with a {@link TransformMesh}.
 * @param o_width The width of the image underlying the {@link Patch}.
 * @param o_height The height of the image underlying the {@link Patch}.
 * @return A {@code double[]} array with the x,y values.
 * @throws NoninvertibleTransformException
 */
public static final double[] toPixelCoordinate(final double world_x, final double world_y, final AffineTransform aff, final CoordinateTransform ct, final int meshResolution, final int o_width, final int o_height) throws NoninvertibleTransformException {
    // Inverse the affine
    final double[] d = new double[] { world_x, world_y };
    aff.inverseTransform(d, 0, d, 0, 1);
    // Inverse the coordinate transform
    if (null != ct) {
        final double[] f = new double[] { d[0], d[1] };
        final mpicbg.models.InvertibleCoordinateTransform t = mpicbg.models.InvertibleCoordinateTransform.class.isAssignableFrom(ct.getClass()) ? (mpicbg.models.InvertibleCoordinateTransform) ct : new mpicbg.trakem2.transform.TransformMesh(ct, meshResolution, o_width, o_height);
        try {
            t.applyInverseInPlace(f);
        } catch (final NoninvertibleModelException e) {
        }
        d[0] = f[0];
        d[1] = f[1];
    }
    return d;
}
Also used : NoninvertibleModelException(mpicbg.models.NoninvertibleModelException) TransformMesh(mpicbg.trakem2.transform.TransformMesh)

Aggregations

TransformMesh (mpicbg.trakem2.transform.TransformMesh)9 CoordinateTransformMesh (mpicbg.models.CoordinateTransformMesh)8 CoordinateTransform (mpicbg.trakem2.transform.CoordinateTransform)8 Rectangle (java.awt.Rectangle)6 ImageProcessor (ij.process.ImageProcessor)4 AffineTransform (java.awt.geom.AffineTransform)4 NoninvertibleTransformException (java.awt.geom.NoninvertibleTransformException)4 NoninvertibleModelException (mpicbg.models.NoninvertibleModelException)4 CoordinateTransformList (mpicbg.trakem2.transform.CoordinateTransformList)4 TransformMeshMapping (mpicbg.trakem2.transform.TransformMeshMapping)4 ByteProcessor (ij.process.ByteProcessor)3 Area (java.awt.geom.Area)3 AffineModel2D (mpicbg.trakem2.transform.AffineModel2D)3 ImagePlus (ij.ImagePlus)2 Roi (ij.gui.Roi)2 ShapeRoi (ij.gui.ShapeRoi)2 Patch (ini.trakem2.display.Patch)2 Point (mpicbg.models.Point)2 ImageProcessorWithMasks (mpicbg.trakem2.transform.TransformMeshMappingWithMasks.ImageProcessorWithMasks)2 ThresholdToSelection (ij.plugin.filter.ThresholdToSelection)1