Search in sources :

Example 11 with Coordinate

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

the class FSLoader method generateMipMaps.

/**
 * Given an image and its source file name (without directory prepended), generate
 * a pyramid of images until reaching an image not smaller than 32x32 pixels.
 * <p>
 * Such images are stored as jpeg 85% quality in a folder named trakem2.mipmaps.
 * </p>
 * <p>
 * The Patch id and the right extension will be appended to the filename in all cases.
 * </p>
 * <p>
 * Any equally named files will be overwritten.
 * </p>
 */
protected boolean generateMipMaps(final Patch patch) {
    Utils.log2("mipmaps for " + patch);
    final String path = getAbsolutePath(patch);
    if (null == path) {
        Utils.log("generateMipMaps: null path for Patch " + patch);
        cannot_regenerate.add(patch);
        return false;
    }
    if (hs_unloadable.contains(patch)) {
        FilePathRepair.add(patch);
        return false;
    }
    synchronized (gm_lock) {
        try {
            if (null == dir_mipmaps)
                createMipMapsDir(null);
            if (null == dir_mipmaps || isURL(dir_mipmaps))
                return false;
        } catch (Exception e) {
            IJError.print(e);
        }
    }
    /**
     * Record Patch as modified
     */
    touched_mipmaps.add(patch);
    /**
     * Remove serialized features, if any
     */
    removeSerializedFeatures(patch);
    /**
     * Remove serialized pointmatches, if any
     */
    removeSerializedPointMatches(patch);
    /**
     * Alpha mask: setup to check if it was modified while regenerating.
     */
    final long alpha_mask_id = patch.getAlphaMaskId();
    final int resizing_mode = patch.getProject().getMipMapsMode();
    try {
        ImageProcessor ip;
        ByteProcessor alpha_mask = null;
        ByteProcessor outside_mask = null;
        int type = patch.getType();
        // Aggressive cache freeing
        releaseToFit(patch.getOWidth() * patch.getOHeight() * 4 + MIN_FREE_BYTES);
        // Obtain an image which may be coordinate-transformed, and an alpha mask.
        Patch.PatchImage pai = patch.createTransformedImage();
        if (null == pai || null == pai.target) {
            Utils.log("Can't regenerate mipmaps for patch " + patch);
            cannot_regenerate.add(patch);
            return false;
        }
        ip = pai.target;
        // can be null
        alpha_mask = pai.mask;
        // can be null
        outside_mask = pai.outside;
        pai = null;
        // Old style:
        // final String filename = new StringBuilder(new File(path).getName()).append('.').append(patch.getId()).append(mExt).toString();
        // New style:
        final String filename = createMipMapRelPath(patch, mExt);
        int w = ip.getWidth();
        int h = ip.getHeight();
        // sigma = sqrt(2^level - 0.5^2)
        // where 0.5 is the estimated sigma for a full-scale image
        // which means sigma = 0.75 for the full-scale image (has level 0)
        // prepare a 0.75 sigma image from the original
        double min = patch.getMin(), max = patch.getMax();
        // (The -1,-1 are flags really for "not set")
        if (-1 == min && -1 == max) {
            switch(type) {
                case ImagePlus.COLOR_RGB:
                case ImagePlus.COLOR_256:
                case ImagePlus.GRAY8:
                    patch.setMinAndMax(0, 255);
                    break;
                // Find and flow through to default:
                case ImagePlus.GRAY16:
                    ((ij.process.ShortProcessor) ip).findMinAndMax();
                    patch.setMinAndMax(ip.getMin(), ip.getMax());
                    break;
                case ImagePlus.GRAY32:
                    ((FloatProcessor) ip).findMinAndMax();
                    patch.setMinAndMax(ip.getMin(), ip.getMax());
                    break;
            }
            // may have changed
            min = patch.getMin();
            max = patch.getMax();
        }
        // Set for the level 0 image, which is a duplicate of the one in the cache in any case
        ip.setMinAndMax(min, max);
        // ImageJ no longer stretches the bytes for ByteProcessor with setMinAndmax
        if (ByteProcessor.class == ip.getClass()) {
            if (0 != min && 255 != max) {
                final byte[] b = (byte[]) ip.getPixels();
                final double scale = 255 / (max - min);
                for (int i = 0; i < b.length; ++i) {
                    final int val = b[i] & 0xff;
                    if (val < min)
                        b[i] = 0;
                    else
                        b[i] = (byte) Math.min(255, ((val - min) * scale));
                }
            }
        }
        // Proper support for LUT images: treat them as RGB
        if (ip.isColorLut() || type == ImagePlus.COLOR_256) {
            ip = ip.convertToRGB();
            type = ImagePlus.COLOR_RGB;
        }
        final int first_mipmap_level_saved = patch.getProject().getFirstMipMapLevelSaved();
        if (Loader.AREA_DOWNSAMPLING == resizing_mode) {
            long t0 = System.currentTimeMillis();
            final ImageBytes[] b = DownsamplerMipMaps.create(patch, type, ip, alpha_mask, outside_mask);
            long t1 = System.currentTimeMillis();
            for (int i = 0; i < b.length; ++i) {
                if (i < first_mipmap_level_saved) {
                    // Ignore level i
                    if (null != b[i])
                        CachingThread.storeForReuse(b[i].c);
                } else {
                    boolean written = mmio.save(getLevelDir(dir_mipmaps, i) + filename, b[i].c, b[i].width, b[i].height, 0.85f);
                    if (!written) {
                        Utils.log("Failed to save mipmap with area downsampling at level=" + i + " for patch " + patch);
                        cannot_regenerate.add(patch);
                        break;
                    }
                }
            }
            long t2 = System.currentTimeMillis();
            System.out.println("MipMaps with area downsampling: creation took " + (t1 - t0) + "ms, saving took " + (t2 - t1) + "ms, total: " + (t2 - t0) + "ms\n");
        } else if (Loader.GAUSSIAN == resizing_mode) {
            if (ImagePlus.COLOR_RGB == type) {
                // TODO releaseToFit proper
                releaseToFit(w * h * 4 * 10);
                final ColorProcessor cp = (ColorProcessor) ip;
                final FloatProcessorT2 red = new FloatProcessorT2(w, h, 0, 255);
                cp.toFloat(0, red);
                final FloatProcessorT2 green = new FloatProcessorT2(w, h, 0, 255);
                cp.toFloat(1, green);
                final FloatProcessorT2 blue = new FloatProcessorT2(w, h, 0, 255);
                cp.toFloat(2, blue);
                FloatProcessorT2 alpha;
                final FloatProcessorT2 outside;
                if (null != alpha_mask) {
                    alpha = new FloatProcessorT2(alpha_mask);
                } else {
                    alpha = null;
                }
                if (null != outside_mask) {
                    outside = new FloatProcessorT2(outside_mask);
                    if (null == alpha) {
                        alpha = outside;
                        alpha_mask = outside_mask;
                    }
                } else {
                    outside = null;
                }
                final String target_dir0 = getLevelDir(dir_mipmaps, 0);
                if (Thread.currentThread().isInterrupted())
                    return false;
                // Generate level 0 first:
                if (0 == first_mipmap_level_saved) {
                    boolean written;
                    if (null == alpha) {
                        written = mmio.save(cp, target_dir0 + filename, 0.85f, false);
                    } else {
                        written = mmio.save(target_dir0 + filename, P.asRGBABytes((int[]) cp.getPixels(), (byte[]) alpha_mask.getPixels(), null == outside ? null : (byte[]) outside_mask.getPixels()), w, h, 0.85f);
                    }
                    if (!written) {
                        Utils.log("Failed to save mipmap for COLOR_RGB, 'alpha = " + alpha + "', level = 0  for  patch " + patch);
                        cannot_regenerate.add(patch);
                    }
                }
                // Generate all other mipmap levels
                // TODO: for best performance, it should start from a direct Gaussian downscaling at the first level to write.
                // the scale level. Proper scale is: 1 / pow(2, k)
                int k = 0;
                do {
                    if (Thread.currentThread().isInterrupted())
                        return false;
                    // 1 - Prepare values for the next scaled image
                    k++;
                    // 2 - Check that the target folder for the desired scale exists
                    final String target_dir = getLevelDir(dir_mipmaps, k);
                    if (null == target_dir)
                        break;
                    // 3 - Blur the previous image to 0.75 sigma, and scale it
                    // will resize 'red' FloatProcessor in place.
                    final byte[] r = gaussianBlurResizeInHalf(red);
                    // idem
                    final byte[] g = gaussianBlurResizeInHalf(green);
                    // idem
                    final byte[] b = gaussianBlurResizeInHalf(blue);
                    // idem
                    final byte[] a = null == alpha ? null : gaussianBlurResizeInHalf(alpha);
                    if (null != outside) {
                        final byte[] o;
                        if (alpha != outside)
                            // idem
                            o = gaussianBlurResizeInHalf(outside);
                        else
                            o = a;
                        // If there was no alpha mask, alpha is the outside itself
                        for (int i = 0; i < o.length; i++) {
                            // TODO I am sure there is a bitwise operation to do this in one step. Some thing like: a[i] &= 127;
                            if ((o[i] & 0xff) != 255)
                                a[i] = 0;
                        }
                    }
                    w = red.getWidth();
                    h = red.getHeight();
                    // 4 - Compose ColorProcessor
                    if (first_mipmap_level_saved < k) {
                        // Skip saving this mipmap level
                        continue;
                    }
                    if (null == alpha) {
                        // 5 - Save as jpeg
                        if (!mmio.save(target_dir + filename, new byte[][] { r, g, b }, w, h, 0.85f)) {
                            Utils.log("Failed to save mipmap for COLOR_RGB, 'alpha = " + alpha + "', level = " + k + " for  patch " + patch);
                            cannot_regenerate.add(patch);
                            break;
                        }
                    } else {
                        if (!mmio.save(target_dir + filename, new byte[][] { r, g, b, a }, w, h, 0.85f)) {
                            Utils.log("Failed to save mipmap for COLOR_RGB, 'alpha = " + alpha + "', level = " + k + " for  patch " + patch);
                            cannot_regenerate.add(patch);
                            break;
                        }
                    }
                } while (// not smaller than 32x32
                w >= 32 && h >= 32);
            } else {
                long t0 = System.currentTimeMillis();
                // Greyscale:
                releaseToFit(w * h * 4 * 10);
                if (Thread.currentThread().isInterrupted())
                    return false;
                final FloatProcessorT2 fp = new FloatProcessorT2((FloatProcessor) ip.convertToFloat());
                if (ImagePlus.GRAY8 == type) {
                    // for 8-bit, the min,max has been applied when going to FloatProcessor
                    // just set it
                    fp.setMinMax(0, 255);
                } else {
                    fp.setMinAndMax(patch.getMin(), patch.getMax());
                }
                // fp.debugMinMax(patch.toString());
                FloatProcessorT2 alpha, outside;
                if (null != alpha_mask) {
                    alpha = new FloatProcessorT2(alpha_mask);
                } else {
                    alpha = null;
                }
                if (null != outside_mask) {
                    outside = new FloatProcessorT2(outside_mask);
                    if (null == alpha) {
                        alpha = outside;
                        alpha_mask = outside_mask;
                    }
                } else {
                    outside = null;
                }
                // the scale level. Proper scale is: 1 / pow(2, k)
                int k = 0;
                do {
                    if (Thread.currentThread().isInterrupted())
                        return false;
                    if (0 != k) {
                        // not doing so at the end because it would add one unnecessary blurring
                        gaussianBlurResizeInHalf(fp);
                        if (null != alpha) {
                            gaussianBlurResizeInHalf(alpha);
                            if (alpha != outside && outside != null) {
                                gaussianBlurResizeInHalf(outside);
                            }
                        }
                    }
                    w = fp.getWidth();
                    h = fp.getHeight();
                    // 1 - check that the target folder for the desired scale exists
                    final String target_dir = getLevelDir(dir_mipmaps, k);
                    if (null == target_dir)
                        break;
                    if (k < first_mipmap_level_saved) {
                        // Skip saving this mipmap level
                        k++;
                        continue;
                    }
                    if (null != alpha) {
                        // If there was no alpha mask, alpha is the outside itself
                        if (!mmio.save(target_dir + filename, new byte[][] { fp.getScaledBytePixels(), P.merge(alpha.getBytePixels(), null == outside ? null : outside.getBytePixels()) }, w, h, 0.85f)) {
                            Utils.log("Failed to save mipmap for GRAY8, 'alpha = " + alpha + "', level = " + k + " for  patch " + patch);
                            cannot_regenerate.add(patch);
                            break;
                        }
                    } else {
                        // 3 - save as 8-bit jpeg
                        if (!mmio.save(target_dir + filename, new byte[][] { fp.getScaledBytePixels() }, w, h, 0.85f)) {
                            Utils.log("Failed to save mipmap for GRAY8, 'alpha = " + alpha + "', level = " + k + " for  patch " + patch);
                            cannot_regenerate.add(patch);
                            break;
                        }
                    }
                    // 4 - prepare values for the next scaled image
                    k++;
                } while (// not smaller than 32x32
                fp.getWidth() >= 32 && fp.getHeight() >= 32);
                long t1 = System.currentTimeMillis();
                System.out.println("MipMaps took " + (t1 - t0));
            }
        } else {
            Utils.log("ERROR: unknown image resizing mode for mipmaps: " + resizing_mode);
        }
        return true;
    } catch (Throwable e) {
        Utils.log("*** ERROR: Can't generate mipmaps for patch " + patch);
        IJError.print(e);
        cannot_regenerate.add(patch);
        return false;
    } finally {
        // flush any cached tiles
        flushMipMaps(patch.getId());
        // flush any cached layer screenshots
        if (null != patch.getLayer()) {
            try {
                patch.getLayer().getParent().removeFromOffscreens(patch.getLayer());
            } catch (Exception e) {
                IJError.print(e);
            }
        }
        // gets executed even when returning from the catch statement or within the try/catch block
        synchronized (gm_lock) {
            regenerating_mipmaps.remove(patch);
        }
        // Has the alpha mask changed?
        if (patch.getAlphaMaskId() != alpha_mask_id) {
            Utils.log2("Alpha mask changed: resubmitting mipmap regeneration for " + patch);
            regenerateMipMaps(patch);
        }
    }
}
Also used : ByteProcessor(ij.process.ByteProcessor) FloatProcessor(ij.process.FloatProcessor) TimeoutException(java.util.concurrent.TimeoutException) ExecutionException(java.util.concurrent.ExecutionException) ImageProcessor(ij.process.ImageProcessor) ColorProcessor(ij.process.ColorProcessor) Patch(ini.trakem2.display.Patch) FloatProcessorT2(ini.trakem2.imaging.FloatProcessorT2)

Example 12 with Coordinate

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

the class DistortionCorrectionTask method run.

public static final void run(final CorrectDistortionFromSelectionParam p, final List<Patch> patches, final Displayable active, final Layer layer, final Worker worker) {
    /* no multiple inheritance, so p cannot be an Align.ParamOptimize, working around legacy by copying data into one ... */
    final Align.ParamOptimize ap = new Align.ParamOptimize();
    ap.sift.set(p.sift);
    ap.desiredModelIndex = p.desiredModelIndex;
    ap.expectedModelIndex = p.expectedModelIndex;
    ap.maxEpsilon = p.maxEpsilon;
    ap.minInlierRatio = p.minInlierRatio;
    ap.rod = p.rod;
    ap.identityTolerance = p.identityTolerance;
    ap.lambda = p.lambdaRegularize;
    ap.maxIterations = p.maxIterationsOptimize;
    ap.maxPlateauwidth = p.maxPlateauwidthOptimize;
    ap.minNumInliers = p.minNumInliers;
    ap.regularize = p.regularize;
    ap.regularizerModelIndex = p.regularizerIndex;
    ap.rejectIdentity = p.rejectIdentity;
    /**
     * Get all patches that will be affected.
     */
    final List<Patch> allPatches = new ArrayList<Patch>();
    for (final Layer l : layer.getParent().getLayers().subList(p.firstLayerIndex, p.lastLayerIndex + 1)) for (final Displayable d : l.getDisplayables(Patch.class)) allPatches.add((Patch) d);
    /**
     * Unset the coordinate transforms of all patches if desired.
     */
    if (p.clearTransform) {
        if (worker != null)
            worker.setTaskName("Clearing present transforms");
        setCoordinateTransform(allPatches, null, Runtime.getRuntime().availableProcessors());
        Display.repaint();
    }
    if (worker != null)
        worker.setTaskName("Establishing SIFT correspondences");
    final List<AbstractAffineTile2D<?>> tiles = new ArrayList<AbstractAffineTile2D<?>>();
    final List<AbstractAffineTile2D<?>> fixedTiles = new ArrayList<AbstractAffineTile2D<?>>();
    final List<Patch> fixedPatches = new ArrayList<Patch>();
    if (active != null && active instanceof Patch)
        fixedPatches.add((Patch) active);
    Align.tilesFromPatches(ap, patches, fixedPatches, tiles, fixedTiles);
    final List<AbstractAffineTile2D<?>[]> tilePairs = new ArrayList<AbstractAffineTile2D<?>[]>();
    if (p.tilesAreInPlace)
        AbstractAffineTile2D.pairOverlappingTiles(tiles, tilePairs);
    else
        AbstractAffineTile2D.pairTiles(tiles, tilePairs);
    AbstractAffineTile2D<?> fixedTile = null;
    if (fixedTiles.size() > 0)
        fixedTile = fixedTiles.get(0);
    else
        fixedTile = tiles.get(0);
    Align.connectTilePairs(ap, tiles, tilePairs, p.maxNumThreadsSift, p.multipleHypotheses);
    /**
     * Shift all local coordinates into the original image frame
     */
    for (final AbstractAffineTile2D<?> tile : tiles) {
        final Rectangle box = tile.getPatch().getCoordinateTransformBoundingBox();
        for (final PointMatch m : tile.getMatches()) {
            final double[] l = m.getP1().getL();
            final double[] w = m.getP1().getW();
            l[0] += box.x;
            l[1] += box.y;
            w[0] = l[0];
            w[1] = l[1];
        }
    }
    if (Thread.currentThread().isInterrupted())
        return;
    final List<Set<Tile<?>>> graphs = AbstractAffineTile2D.identifyConnectedGraphs(tiles);
    if (graphs.size() > 1)
        Utils.log("Could not interconnect all images with correspondences.  ");
    final List<AbstractAffineTile2D<?>> interestingTiles;
    /**
     * Find largest graph.
     */
    Set<Tile<?>> largestGraph = null;
    for (final Set<Tile<?>> graph : graphs) if (largestGraph == null || largestGraph.size() < graph.size())
        largestGraph = graph;
    interestingTiles = new ArrayList<AbstractAffineTile2D<?>>();
    for (final Tile<?> t : largestGraph) interestingTiles.add((AbstractAffineTile2D<?>) t);
    if (Thread.currentThread().isInterrupted())
        return;
    Utils.log("Estimating lens model:");
    /* initialize with pure affine */
    Align.optimizeTileConfiguration(ap, interestingTiles, fixedTiles);
    /* measure the current error */
    double e = 0;
    int n = 0;
    for (final AbstractAffineTile2D<?> t : interestingTiles) for (final PointMatch pm : t.getMatches()) {
        e += pm.getDistance();
        ++n;
    }
    e /= n;
    double dEpsilon_i = 0;
    double epsilon_i = e;
    double dEpsilon_0 = 0;
    NonLinearTransform lensModel = null;
    Utils.log("0: epsilon = " + e);
    /* Store original point locations */
    final HashMap<Point, Point> originalPoints = new HashMap<Point, Point>();
    for (final AbstractAffineTile2D<?> t : interestingTiles) for (final PointMatch pm : t.getMatches()) originalPoints.put(pm.getP1(), pm.getP1().clone());
    /* ad hoc conditions to terminate iteration:
		 * small improvement ( 1/1000) relative to first iteration
		 * less than 20 iterations
		 * at least 2 iterations */
    for (int i = 1; i < 20 && (i < 2 || dEpsilon_i <= dEpsilon_0 / 1000); ++i) {
        if (Thread.currentThread().isInterrupted())
            return;
        /* Some data shuffling for the lens correction interface */
        final List<PointMatchCollectionAndAffine> matches = new ArrayList<PointMatchCollectionAndAffine>();
        for (final AbstractAffineTile2D<?>[] tilePair : tilePairs) {
            final AffineTransform a = tilePair[0].createAffine();
            a.preConcatenate(tilePair[1].getModel().createInverseAffine());
            final Collection<PointMatch> commonMatches = new ArrayList<PointMatch>();
            tilePair[0].commonPointMatches(tilePair[1], commonMatches);
            final Collection<PointMatch> originalCommonMatches = new ArrayList<PointMatch>();
            for (final PointMatch pm : commonMatches) originalCommonMatches.add(new PointMatch(originalPoints.get(pm.getP1()), originalPoints.get(pm.getP2())));
            matches.add(new PointMatchCollectionAndAffine(a, originalCommonMatches));
        }
        if (worker != null)
            worker.setTaskName("Estimating lens distortion correction");
        lensModel = Distortion_Correction.createInverseDistortionModel(matches, p.dimension, p.lambda, (int) fixedTile.getWidth(), (int) fixedTile.getHeight());
        /* update local points */
        for (final AbstractAffineTile2D<?> t : interestingTiles) for (final PointMatch pm : t.getMatches()) {
            final Point currentPoint = pm.getP1();
            final Point originalPoint = originalPoints.get(currentPoint);
            final double[] l = currentPoint.getL();
            final double[] lo = originalPoint.getL();
            l[0] = lo[0];
            l[1] = lo[1];
            lensModel.applyInPlace(l);
        }
        /* re-optimize */
        Align.optimizeTileConfiguration(ap, interestingTiles, fixedTiles);
        /* measure the current error */
        e = 0;
        n = 0;
        for (final AbstractAffineTile2D<?> t : interestingTiles) for (final PointMatch pm : t.getMatches()) {
            e += pm.getDistance();
            ++n;
        }
        e /= n;
        dEpsilon_i = e - epsilon_i;
        epsilon_i = e;
        if (i == 1)
            dEpsilon_0 = dEpsilon_i;
        Utils.log(i + ": epsilon = " + e);
        Utils.log(i + ": delta epsilon = " + dEpsilon_i);
    }
    if (lensModel != null) {
        if (p.visualize) {
            if (Thread.currentThread().isInterrupted())
                return;
            if (worker != null)
                worker.setTaskName("Visualizing lens distortion correction");
            lensModel.visualizeSmall(p.lambda);
        }
        if (worker != null)
            worker.setTaskName("Applying lens distortion correction");
        appendCoordinateTransform(allPatches, lensModel, Runtime.getRuntime().availableProcessors());
        Utils.log("Done.");
    } else
        Utils.log("No lens model found.");
}
Also used : Set(java.util.Set) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Rectangle(java.awt.Rectangle) PointMatchCollectionAndAffine(lenscorrection.Distortion_Correction.PointMatchCollectionAndAffine) Displayable(ini.trakem2.display.Displayable) Align(mpicbg.trakem2.align.Align) AbstractAffineTile2D(mpicbg.trakem2.align.AbstractAffineTile2D) Tile(mpicbg.models.Tile) Point(mpicbg.models.Point) Layer(ini.trakem2.display.Layer) Point(mpicbg.models.Point) PointMatch(mpicbg.models.PointMatch) AffineTransform(java.awt.geom.AffineTransform) Patch(ini.trakem2.display.Patch)

Example 13 with Coordinate

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

the class AreaUtils method singularInterpolation.

/**
 * Extract the Area of the image for the given pixel value.
 *  ThresholdToSelection is way faster than this, just use it.
 *  It's BROKEN do not use.
 */
/*
	static public final Area extractArea(final ImageProcessor ip, final float val) {
		final int height = ip.getHeight();
		final int width = ip.getWidth();

		final Area area = new Area();
		final ArrayList<Area> segments = new ArrayList<Area>();
		final Rectangle box = new Rectangle(0, 0, 1, 1);

		for (int y=0; y<height; y++) {
			float prev = ip.getPixelValue(0, y);
			box.x = 0;
			box.y = y;
			box.width = val == prev ? 1 : 0;

			for (int x=1; x<width; x++) {

				float pix = ip.getPixelValue(x, y);

				if (val == pix) {
					if (pix == prev) {
						box.width++;
						continue;
					}
					// Else, add previous one
					segments.add(new Area(box));
					// ... and start a new box
					box.x = x;
					box.y = y;
					box.width = 1;
					prev = pix;
				}
			}

			// At end of line, add the last
			segments.add(new Area(box));

			// Join a few
			if (segments.size() > 32) {
				final Area a = new Area(segments.get(0));
				final int len = segments.size();
				for (int i=1; i<len; i++) a.add(segments.get(i));
				area.add(a);
				segments.clear();
			}
		}

		if (segments.size() > 0) {
			final Area a = new Area(segments.get(0));
			final int len = segments.size();
			for (int i=1; i<len; i++) a.add(segments.get(i));
			area.add(a);
		}

		return area;
	}
	*/
/**
 * Interpolate areas only if they are made of a single shape each.
 *  Assumes that areas are in the same coordinate system.
 * @throws Exception
 */
public static final Area[] singularInterpolation(final Area a1, final Area a2, final int nInterpolates) throws Exception {
    if (!a1.isSingular() || !a2.isSingular()) {
        return null;
    }
    final VectorString2D vs1 = M.asVectorString2D(M.getPolygons(a1).iterator().next(), 0);
    final VectorString2D vs2 = M.asVectorString2D(M.getPolygons(a2).iterator().next(), 1);
    final Editions ed = new Editions(vs1, vs2, Math.min(vs1.getAverageDelta(), vs2.getAverageDelta()), true);
    final double[][][] d = SkinMaker.getMorphedPerimeters(vs1, vs2, nInterpolates, ed);
    final Area[] a = new Area[d.length];
    for (int i = 0; i < d.length; i++) {
        final double[] x = d[i][0];
        final double[] y = d[i][1];
        final int[] xi = new int[x.length];
        final int[] yi = new int[y.length];
        for (int k = 0; k < x.length; k++) {
            xi[k] = (int) x[k];
            yi[k] = (int) y[k];
        }
        a[i] = new Area(new Polygon(xi, yi, xi.length));
    }
    return a;
}
Also used : Area(java.awt.geom.Area) Editions(ini.trakem2.vector.Editions) VectorString2D(ini.trakem2.vector.VectorString2D) Polygon(java.awt.Polygon)

Example 14 with Coordinate

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

the class Search method createCoordinate.

private Coordinate<Displayable> createCoordinate(final Displayable d) {
    Rectangle r = d.getBoundingBox();
    Layer la = d instanceof ZDisplayable ? ((ZDisplayable) d).getFirstLayer() : d.getLayer();
    if (null == la) {
        Display display = Display.getFront(d.getProject());
        if (null == display)
            la = d.getProject().getRootLayerSet().getLayer(0);
        else
            la = display.getLayer();
    }
    return new Coordinate<Displayable>(r.x + r.width / 2, r.y + r.height / 2, la, d);
}
Also used : ZDisplayable(ini.trakem2.display.ZDisplayable) Coordinate(ini.trakem2.display.Coordinate) Rectangle(java.awt.Rectangle) Layer(ini.trakem2.display.Layer) Display(ini.trakem2.display.Display)

Example 15 with Coordinate

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

the class Project method saveTask.

public Bureaucrat saveTask(final String command) {
    return Bureaucrat.createAndStart(new Worker.Task("Saving") {

        public void exec() {
            if (command.equals("Save")) {
                save();
            } else if (command.equals("Save as...")) {
                XMLOptions options = new XMLOptions();
                options.overwriteXMLFile = false;
                options.export_images = false;
                options.include_coordinate_transform = true;
                options.patches_dir = null;
                // Will open a file dialog
                loader.saveAs(project, options);
                restartAutosaving();
            // 
            } else if (command.equals("Save as... without coordinate transforms")) {
                YesNoDialog yn = new YesNoDialog("WARNING", "You are about to save an XML file that lacks the information for the coordinate transforms of each image.\n" + "These transforms are referred to with the attribute 'ct_id' of each 't2_patch' entry in the XML document,\n" + "and the data for the transform is stored in an individual file under the folder 'trakem2.cts/'.\n" + " \n" + "It is advised to keep a complete XML file with all coordinate transforms included along with this new copy.\n" + "Please check NOW that you have such a complete XML copy.\n" + " \n" + "Proceed?");
                if (!yn.yesPressed())
                    return;
                saveWithoutCoordinateTransforms();
            // 
            } else if (command.equals("Delete stale files...")) {
                setTaskName("Deleting stale files");
                GenericDialog gd = new GenericDialog("Delete stale files");
                gd.addMessage("You are about to remove all files under the folder 'trakem2.cts/' which are not referred to from the\n" + "currently loaded project. If you have sibling XML files whose 't2_patch' entries (the images) refer,\n" + "via 'ct_id' attributes, to coordinate transforms in 'trakem2.cts/' that this current XML doesn't,\n" + "they may be LOST FOREVER. Unless you have a version of the XML file with the coordinate transforms\n" + "written in it, as can be obtained by using the 'Project - Save' command.\n" + " \n" + "The same is true for the .zip files that store alpha masks, under folder 'trakem2.masks/'\n" + "and which are referred to from the 'alpha_mask_id' attribute of 't2_patch' entries.\n" + " \n" + "Do you have such complete XML file? Check *NOW*.\n" + " \n" + "Proceed with deleting:");
                gd.addCheckbox("Delete stale coordinate transform files", true);
                gd.addCheckbox("Delete stale alpha mask files", true);
                gd.showDialog();
                if (gd.wasCanceled())
                    return;
                project.getLoader().deleteStaleFiles(gd.getNextBoolean(), gd.getNextBoolean());
            }
        }
    }, project);
}
Also used : YesNoDialog(ini.trakem2.display.YesNoDialog) GenericDialog(ij.gui.GenericDialog) Worker(ini.trakem2.utils.Worker) XMLOptions(ini.trakem2.persistence.XMLOptions)

Aggregations

ArrayList (java.util.ArrayList)14 Layer (ini.trakem2.display.Layer)10 HashMap (java.util.HashMap)10 Rectangle (java.awt.Rectangle)9 Patch (ini.trakem2.display.Patch)8 AffineTransform (java.awt.geom.AffineTransform)7 Map (java.util.Map)7 Displayable (ini.trakem2.display.Displayable)6 NoninvertibleTransformException (java.awt.geom.NoninvertibleTransformException)6 TreeMap (java.util.TreeMap)6 Worker (ini.trakem2.utils.Worker)5 Area (java.awt.geom.Area)5 HashSet (java.util.HashSet)5 GenericDialog (ij.gui.GenericDialog)4 Calibration (ij.measure.Calibration)4 ByteProcessor (ij.process.ByteProcessor)4 File (java.io.File)4 Future (java.util.concurrent.Future)4 ImagePlus (ij.ImagePlus)3 ColorProcessor (ij.process.ColorProcessor)3