Search in sources :

Example 31 with Patch

use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.

the class ExportARGB method makeFlatImageARGBFromOriginals.

/**
 * Limited to 2GB arrays for the requested image.
 *
 * @param patches
 * @param roi
 * @param backgroundValue
 * @param scale
 * @return
 */
public static final Pair<ColorProcessor, ByteProcessor> makeFlatImageARGBFromOriginals(final List<Patch> patches, final Rectangle roi, final double backgroundValue, final double scale) {
    final ColorProcessor target = new ColorProcessor((int) (roi.width * scale), (int) (roi.height * scale));
    target.setInterpolationMethod(ImageProcessor.BILINEAR);
    final ByteProcessor targetMask = new ByteProcessor(target.getWidth(), target.getHeight());
    targetMask.setInterpolationMethod(ImageProcessor.NEAREST_NEIGHBOR);
    for (final Patch patch : patches) {
        final Patch.PatchImage pai = patch.createTransformedImage();
        final ColorProcessor fp = (ColorProcessor) pai.target.convertToRGB();
        final ByteProcessor alpha;
        System.out.println("IMAGE:" + patch.getTitle());
        System.out.println("mask: " + pai.mask);
        System.out.println("outside: " + pai.outside);
        if (null == pai.mask) {
            if (null == pai.outside) {
                alpha = new ByteProcessor(fp.getWidth(), fp.getHeight());
                // fully opaque
                Arrays.fill((byte[]) alpha.getPixels(), (byte) 255);
            } else {
                alpha = pai.outside;
            }
        } else {
            alpha = pai.mask;
        }
        // The affine to apply
        final AffineTransform atc = new AffineTransform();
        atc.scale(scale, scale);
        atc.translate(-roi.x, -roi.y);
        final AffineTransform at = new AffineTransform();
        at.preConcatenate(atc);
        at.concatenate(patch.getAffineTransform());
        final AffineModel2D aff = new AffineModel2D();
        aff.set(at);
        final CoordinateTransformMesh mesh = new CoordinateTransformMesh(aff, patch.getMeshResolution(), fp.getWidth(), fp.getHeight());
        final TransformMeshMappingWithMasks<CoordinateTransformMesh> mapping = new TransformMeshMappingWithMasks<CoordinateTransformMesh>(mesh);
        fp.setInterpolationMethod(ImageProcessor.BILINEAR);
        // no interpolation
        alpha.setInterpolationMethod(ImageProcessor.NEAREST_NEIGHBOR);
        mapping.map(fp, alpha, target, targetMask);
    }
    return new Pair<ColorProcessor, ByteProcessor>(target, targetMask);
}
Also used : ByteProcessor(ij.process.ByteProcessor) ColorProcessor(ij.process.ColorProcessor) CoordinateTransformMesh(mpicbg.models.CoordinateTransformMesh) AffineTransform(java.awt.geom.AffineTransform) Patch(ini.trakem2.display.Patch) Pair(mpicbg.trakem2.util.Pair)

Example 32 with Patch

use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.

the class ExportUnsignedShort method exportTiles.

/**
 * Create constant size tiles that carpet the areas of the {@code layer} where there are images;
 * these tiles are returned in a lazy sequence of {@link Callable} objects that create a tripled
 * consisting of the {@link ShortProcessor} and the X and Y pixel coordinates of that tile.
 *
 * @param layer The layer to export images for
 * @param tileWidth The width of the tiles to export
 * @param tileHeight
 * @return A lazy sequence of {@link Callable} instances, each holding a {@link Triple} that specifies the ShortProcessor,
 * the X and the Y (both in world pixel uncalibrated coordinates).
 */
public static final Iterable<Callable<ExportedTile>> exportTiles(final Layer layer, final int tileWidth, final int tileHeight, final boolean visible_only) {
    final ArrayList<Displayable> patches = layer.getDisplayables(Patch.class, visible_only);
    // If the Layer lacks images, return an empty sequence.
    if (patches.isEmpty()) {
        return Collections.emptyList();
    }
    /* calculate intensity transfer */
    final ArrayList<PatchIntensityRange> patchIntensityRanges = new ArrayList<PatchIntensityRange>();
    double min_ = Double.MAX_VALUE;
    double max_ = -Double.MAX_VALUE;
    for (final Displayable d : patches) {
        final Patch patch = (Patch) d;
        final PatchIntensityRange pir = new PatchIntensityRange(patch);
        if (pir.min < min_)
            min_ = pir.min;
        if (pir.max > max_)
            max_ = pir.max;
        patchIntensityRanges.add(pir);
    }
    final double min = min_;
    final double max = max_;
    /* Create lazy sequence that creates Callable instances. */
    final Rectangle box = layer.getMinimalBoundingBox(Patch.class, visible_only).intersection(layer.getParent().get2DBounds());
    final int nCols = (int) Math.ceil(box.width / (double) tileWidth);
    final int nRows = (int) Math.ceil(box.height / (double) tileHeight);
    final double minI = -min * 65535.0 / (max - min);
    final double maxI = (1.0 - min) * 65535.0 / (max - min);
    return new Iterable<Callable<ExportedTile>>() {

        @Override
        public Iterator<Callable<ExportedTile>> iterator() {
            return new Iterator<Callable<ExportedTile>>() {

                // Internal state
                private int row = 0, col = 0, x0 = box.x, y0 = box.y;

                private final ArrayList<PatchIntensityRange> ps = new ArrayList<PatchIntensityRange>();

                {
                    // Constructor body. Prepare to be able to answer "hasNext()"
                    findNext();
                }

                private final void findNext() {
                    // Iterate until finding a tile that intersects one or more patches
                    ps.clear();
                    while (true) {
                        if (nRows == row) {
                            // End of domain
                            break;
                        }
                        x0 = box.x + col * tileWidth;
                        y0 = box.y + row * tileHeight;
                        final Rectangle tileBounds = new Rectangle(x0, y0, tileWidth, tileHeight);
                        for (final PatchIntensityRange pir : patchIntensityRanges) {
                            if (pir.patch.getBoundingBox().intersects(tileBounds)) {
                                ps.add(pir);
                            }
                        }
                        // Prepare next iteration
                        col += 1;
                        if (nCols == col) {
                            col = 0;
                            row += 1;
                        }
                        if (ps.size() > 0) {
                            // Ready for next iteration
                            break;
                        }
                    }
                }

                @Override
                public boolean hasNext() {
                    return ps.size() > 0;
                }

                @Override
                public Callable<ExportedTile> next() {
                    // Capture state locally
                    final ArrayList<PatchIntensityRange> pirs = new ArrayList<PatchIntensityRange>(ps);
                    final int x = x0;
                    final int y = y0;
                    // Advance
                    findNext();
                    return new Callable<ExportedTile>() {

                        @Override
                        public ExportedTile call() throws Exception {
                            final ShortProcessor sp = new ShortProcessor(tileWidth, tileHeight);
                            sp.setMinAndMax(minI, maxI);
                            for (final PatchIntensityRange pir : pirs) {
                                map(new PatchTransform(pir), x, y, mapIntensities(pir, min, max), sp);
                            }
                            return new ExportedTile(sp, x, y, minI, maxI);
                        }
                    };
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    };
}
Also used : Displayable(ini.trakem2.display.Displayable) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) Callable(java.util.concurrent.Callable) ShortProcessor(ij.process.ShortProcessor) Iterator(java.util.Iterator) Patch(ini.trakem2.display.Patch)

Example 33 with Patch

use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.

the class ExportUnsignedShort method exportTEST.

public static final void exportTEST(final Layer layer, final int tileWidth, final int tileHeight) {
    /* calculate intensity transfer */
    final ArrayList<Displayable> patches = layer.getDisplayables(Patch.class);
    final ArrayList<PatchIntensityRange> patchIntensityRanges = new ArrayList<PatchIntensityRange>();
    double min = Double.MAX_VALUE;
    double max = -Double.MAX_VALUE;
    for (final Displayable d : patches) {
        final Patch patch = (Patch) d;
        final PatchIntensityRange pir = new PatchIntensityRange(patch);
        if (pir.min < min)
            min = pir.min;
        if (pir.max > max)
            max = pir.max;
        patchIntensityRanges.add(pir);
    }
    /* render tiles */
    /* TODO Do not render them into a stack but save them as files */
    final ImageStack stack = new ImageStack(tileWidth, tileHeight);
    ImagePlus imp = null;
    final double minI = -min * 65535.0 / (max - min);
    final double maxI = (1.0 - min) * 65535.0 / (max - min);
    // ij.IJ.log("min, max: " + min + ", " + max + ",    minI, maxI: " + minI + ", " + maxI);
    final int nc = (int) Math.ceil(layer.getLayerWidth() / tileWidth);
    final int nr = (int) Math.ceil(layer.getLayerHeight() / tileHeight);
    for (int r = 0; r < nr; ++r) {
        final int y0 = r * tileHeight;
        for (int c = 0; c < nc; ++c) {
            final int x0 = c * tileWidth;
            final Rectangle box = new Rectangle(x0, y0, tileWidth, tileHeight);
            final ShortProcessor sp = new ShortProcessor(tileWidth, tileHeight);
            sp.setMinAndMax(minI, maxI);
            for (final PatchIntensityRange pir : patchIntensityRanges) {
                if (pir.patch.getBoundingBox().intersects(box))
                    map(new PatchTransform(pir), x0, y0, mapIntensities(pir, min, max), sp);
            }
            stack.addSlice(r + ", " + c, sp);
            if (null == imp && stack.getSize() > 1) {
                imp = new ImagePlus("tiles", stack);
                imp.show();
            }
            if (null != imp) {
                imp.setSlice(stack.getSize());
                imp.updateAndDraw();
            }
        }
    }
    if (null == imp) {
        // single-slice, non-StackWindow
        new ImagePlus("tiles", stack).show();
    }
}
Also used : Displayable(ini.trakem2.display.Displayable) ImageStack(ij.ImageStack) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) ImagePlus(ij.ImagePlus) ShortProcessor(ij.process.ShortProcessor) Patch(ini.trakem2.display.Patch)

Example 34 with Patch

use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.

the class MatchIntensities method run.

/**
 * @param layers
 * @param radius
 * @param scale
 * @param numCoefficients
 * @param lambda1
 * @param lambda2
 * @param neighborWeight
 * @param roi
 */
public <M extends Model<M> & Affine1D<M>> void run(final List<Layer> layers, final int radius, final double scale, final int numCoefficients, final double lambda1, final double lambda2, final double neighborWeight, final Rectangle roi) throws InterruptedException, ExecutionException {
    final int firstLayerIndex = layerset.getLayerIndex(layers.get(0).getId());
    final int lastLayerIndex = layerset.getLayerIndex(layers.get(layers.size() - 1).getId());
    // final PointMatchFilter filter = new RansacRegressionFilter();
    final PointMatchFilter filter = new RansacRegressionReduceFilter();
    /* collect patches */
    Utils.log("Collecting patches ... ");
    final ArrayList<Patch> patches = new ArrayList<Patch>();
    for (final Layer layer : layers) patches.addAll((Collection) layer.getDisplayables(Patch.class, roi));
    /* delete existing intensity coefficients */
    Utils.log("Clearing existing intensity maps ... ");
    for (final Patch p : patches) p.clearIntensityMap();
    /* generate coefficient tiles for all patches
		 * TODO consider offering alternative models */
    final HashMap<Patch, ArrayList<Tile<? extends M>>> coefficientsTiles = (HashMap) generateCoefficientsTiles(patches, new InterpolatedAffineModel1D<InterpolatedAffineModel1D<AffineModel1D, TranslationModel1D>, IdentityModel>(new InterpolatedAffineModel1D<AffineModel1D, TranslationModel1D>(new AffineModel1D(), new TranslationModel1D(), lambda1), new IdentityModel(), lambda2), numCoefficients * numCoefficients);
    /* completed patches */
    final HashSet<Patch> completedPatches = new HashSet<Patch>();
    /* collect patch pairs */
    Utils.log("Collecting patch pairs ... ");
    final ArrayList<ValuePair<Patch, Patch>> patchPairs = new ArrayList<ValuePair<Patch, Patch>>();
    for (final Patch p1 : patches) {
        completedPatches.add(p1);
        final Rectangle box1 = p1.getBoundingBox().intersection(roi);
        final ArrayList<Patch> p2s = new ArrayList<Patch>();
        /* across adjacent layers */
        final int layerIndex = layerset.getLayerIndex(p1.getLayer().getId());
        for (int i = Math.max(firstLayerIndex, layerIndex - radius); i <= Math.min(lastLayerIndex, layerIndex + radius); ++i) {
            final Layer layer = layerset.getLayer(i);
            if (layer != null)
                p2s.addAll((Collection) layer.getDisplayables(Patch.class, box1));
        }
        for (final Patch p2 : p2s) {
            /*
				 * if this patch had been processed earlier, all matches are
				 * already in
				 */
            if (completedPatches.contains(p2))
                continue;
            patchPairs.add(new ValuePair<Patch, Patch>(p1, p2));
        }
    }
    final int numThreads = Integer.parseInt(layerset.getProperty("n_mipmap_threads", Integer.toString(Runtime.getRuntime().availableProcessors())));
    Utils.log("Matching intensities using " + numThreads + " threads ... ");
    final ExecutorService exec = Executors.newFixedThreadPool(numThreads);
    final ArrayList<Future<?>> futures = new ArrayList<Future<?>>();
    for (final ValuePair<Patch, Patch> patchPair : patchPairs) {
        futures.add(exec.submit(new Matcher(roi, patchPair, (HashMap) coefficientsTiles, filter, scale, numCoefficients)));
    }
    for (final Future<?> future : futures) future.get();
    /* connect tiles within patches */
    Utils.log("Connecting coefficient tiles in the same patch  ... ");
    for (final Patch p1 : completedPatches) {
        /* get the coefficient tiles */
        final ArrayList<Tile<? extends M>> p1CoefficientsTiles = coefficientsTiles.get(p1);
        for (int y = 1; y < numCoefficients; ++y) {
            final int yr = numCoefficients * y;
            final int yr1 = yr - numCoefficients;
            for (int x = 0; x < numCoefficients; ++x) {
                identityConnect(p1CoefficientsTiles.get(yr1 + x), p1CoefficientsTiles.get(yr + x), neighborWeight);
            }
        }
        for (int y = 0; y < numCoefficients; ++y) {
            final int yr = numCoefficients * y;
            for (int x = 1; x < numCoefficients; ++x) {
                final int yrx = yr + x;
                identityConnect(p1CoefficientsTiles.get(yrx), p1CoefficientsTiles.get(yrx - 1), neighborWeight);
            }
        }
    }
    /* optimize */
    Utils.log("Optimizing ... ");
    final TileConfiguration tc = new TileConfiguration();
    for (final ArrayList<Tile<? extends M>> coefficients : coefficientsTiles.values()) {
        // for ( final Tile< ? > t : coefficients )
        // if ( t.getMatches().size() == 0 )
        // IJ.log( "bang" );
        tc.addTiles(coefficients);
    }
    try {
        tc.optimize(0.01f, iterations, iterations, 0.75f);
    } catch (final NotEnoughDataPointsException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (final IllDefinedDataPointsException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    /* save coefficients */
    final double[] ab = new double[2];
    final FSLoader loader = (FSLoader) layerset.getProject().getLoader();
    final String itsDir = loader.getUNUIdFolder() + "trakem2.its/";
    for (final Entry<Patch, ArrayList<Tile<? extends M>>> entry : coefficientsTiles.entrySet()) {
        final FloatProcessor as = new FloatProcessor(numCoefficients, numCoefficients);
        final FloatProcessor bs = new FloatProcessor(numCoefficients, numCoefficients);
        final Patch p = entry.getKey();
        final double min = p.getMin();
        final double max = p.getMax();
        final ArrayList<Tile<? extends M>> tiles = entry.getValue();
        for (int i = 0; i < numCoefficients * numCoefficients; ++i) {
            final Tile<? extends M> t = tiles.get(i);
            final Affine1D<?> affine = t.getModel();
            affine.toArray(ab);
            /* coefficients mapping into existing [min, max] */
            as.setf(i, (float) ab[0]);
            bs.setf(i, (float) ((max - min) * ab[1] + min - ab[0] * min));
        }
        final ImageStack coefficientsStack = new ImageStack(numCoefficients, numCoefficients);
        coefficientsStack.addSlice(as);
        coefficientsStack.addSlice(bs);
        final String itsPath = itsDir + FSLoader.createIdPath(Long.toString(p.getId()), "it", ".tif");
        new File(itsPath).getParentFile().mkdirs();
        IJ.saveAs(new ImagePlus("", coefficientsStack), "tif", itsPath);
    }
    /* update mipmaps */
    for (final Patch p : patches) p.getProject().getLoader().decacheImagePlus(p.getId());
    final ArrayList<Future<Boolean>> mipmapFutures = new ArrayList<Future<Boolean>>();
    for (final Patch p : patches) mipmapFutures.add(p.updateMipMaps());
    for (final Future<Boolean> f : mipmapFutures) f.get();
    Utils.log("Matching intensities done.");
}
Also used : NotEnoughDataPointsException(mpicbg.models.NotEnoughDataPointsException) HashMap(java.util.HashMap) ValuePair(net.imglib2.util.ValuePair) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) InterpolatedAffineModel1D(mpicbg.models.InterpolatedAffineModel1D) IdentityModel(mpicbg.models.IdentityModel) TranslationModel1D(mpicbg.models.TranslationModel1D) HashSet(java.util.HashSet) FloatProcessor(ij.process.FloatProcessor) ImageStack(ij.ImageStack) IllDefinedDataPointsException(mpicbg.models.IllDefinedDataPointsException) Tile(mpicbg.models.Tile) Layer(ini.trakem2.display.Layer) ImagePlus(ij.ImagePlus) Point(mpicbg.models.Point) FSLoader(ini.trakem2.persistence.FSLoader) ExecutorService(java.util.concurrent.ExecutorService) Collection(java.util.Collection) InterpolatedAffineModel1D(mpicbg.models.InterpolatedAffineModel1D) AffineModel1D(mpicbg.models.AffineModel1D) Future(java.util.concurrent.Future) TileConfiguration(mpicbg.models.TileConfiguration) Patch(ini.trakem2.display.Patch) File(java.io.File)

Example 35 with Patch

use of ini.trakem2.display.Patch in project TrakEM2 by trakem2.

the class Render method main.

public static final void main(final String... args) {
    new ImageJ();
    final double scale = 0.05;
    // final double scale = 1;
    final int numCoefficients = 4;
    final Project project = Project.openFSProject("/home/saalfeld/tmp/bock-lens-correction/subproject.xml", false);
    final Layer layer = project.getRootLayerSet().getLayer(0);
    final ArrayList<Patch> patches = (ArrayList) layer.getDisplayables(Patch.class);
    final Patch patch1 = patches.get(0);
    final Patch patch2 = patches.get(2);
    final Rectangle box = patch1.getBoundingBox().intersection(patch2.getBoundingBox());
    // final Rectangle box = patch1.getBoundingBox();
    final int w = (int) (box.width * scale + 0.5);
    final int h = (int) (box.height * scale + 0.5);
    final FloatProcessor pixels1 = new FloatProcessor(w, h);
    final FloatProcessor weights1 = new FloatProcessor(w, h);
    final ColorProcessor coefficients1 = new ColorProcessor(w, h);
    final FloatProcessor pixels2 = new FloatProcessor(w, h);
    final FloatProcessor weights2 = new FloatProcessor(w, h);
    final ColorProcessor coefficients2 = new ColorProcessor(w, h);
    render(patch1, numCoefficients, numCoefficients, pixels1, weights1, coefficients1, box.x, box.y, scale);
    render(patch2, numCoefficients, numCoefficients, pixels2, weights2, coefficients2, box.x, box.y, scale);
    final ImageStack stack = new ImageStack(w, h);
    stack.addSlice(pixels1);
    stack.addSlice(pixels2);
    stack.addSlice(weights1);
    stack.addSlice(weights2);
    stack.addSlice(coefficients1.convertToFloatProcessor());
    stack.addSlice(coefficients2.convertToFloatProcessor());
    new ImagePlus("", stack).show();
}
Also used : FloatProcessor(ij.process.FloatProcessor) ImageStack(ij.ImageStack) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) Layer(ini.trakem2.display.Layer) ImagePlus(ij.ImagePlus) Point(mpicbg.models.Point) ImageJ(ij.ImageJ) Project(ini.trakem2.Project) ColorProcessor(ij.process.ColorProcessor) Patch(ini.trakem2.display.Patch)

Aggregations

Patch (ini.trakem2.display.Patch)69 ArrayList (java.util.ArrayList)46 Layer (ini.trakem2.display.Layer)39 ImagePlus (ij.ImagePlus)34 Rectangle (java.awt.Rectangle)28 Point (mpicbg.models.Point)26 HashSet (java.util.HashSet)24 Displayable (ini.trakem2.display.Displayable)23 AffineTransform (java.awt.geom.AffineTransform)20 Loader (ini.trakem2.persistence.Loader)15 File (java.io.File)15 Future (java.util.concurrent.Future)15 NotEnoughDataPointsException (mpicbg.models.NotEnoughDataPointsException)15 PointMatch (mpicbg.models.PointMatch)14 Worker (ini.trakem2.utils.Worker)13 HashMap (java.util.HashMap)13 ExecutorService (java.util.concurrent.ExecutorService)12 ImageProcessor (ij.process.ImageProcessor)11 AffineModel2D (mpicbg.models.AffineModel2D)11 GenericDialog (ij.gui.GenericDialog)10