Search in sources :

Example 21 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class IJTools method extractHyperstack.

/**
 * Extract a full ImageJ hyperstack for a specific region, for specified ranges of z-slices and time points.
 *
 * @param server server from which to extract pixels
 * @param request region and downsample value; if null, the entire image is used
 * @param zStart starting z-slice index (0-based index)
 * @param zEnd ending z-slice index (exclusive)
 * @param tStart starting timepoint index (0-based index)
 * @param tEnd ending timepoint index (exclusive)
 * @return the ImageJ hyperstack
 * @throws IOException
 */
public static ImagePlus extractHyperstack(ImageServer<BufferedImage> server, RegionRequest request, int zStart, int zEnd, int tStart, int tEnd) throws IOException {
    if (request == null)
        request = RegionRequest.createInstance(server);
    int nChannels = -1;
    int nZ = zEnd - zStart;
    int nT = tEnd - tStart;
    double downsample = request.getDownsample();
    ImageStack stack = null;
    Calibration cal = null;
    for (int t = tStart; t < tEnd; t++) {
        for (int z = zStart; z < zEnd; z++) {
            RegionRequest request2 = RegionRequest.createInstance(server.getPath(), downsample, request.getX(), request.getY(), request.getWidth(), request.getHeight(), z, t);
            ImagePlus imp = IJTools.convertToImagePlus(server, request2).getImage();
            if (stack == null) {
                stack = new ImageStack(imp.getWidth(), imp.getHeight());
            }
            // Append to original image stack
            for (int i = 1; i <= imp.getStack().getSize(); i++) {
                stack.addSlice(imp.getStack().getSliceLabel(i), imp.getStack().getProcessor(i));
            }
            // Get the last calibration
            cal = imp.getCalibration();
            nChannels = imp.getNChannels();
        }
    }
    PixelCalibration pixelCalibration = server.getPixelCalibration();
    if (cal != null && !Double.isNaN(pixelCalibration.getZSpacingMicrons())) {
        cal.pixelDepth = pixelCalibration.getZSpacingMicrons();
        cal.setZUnit("um");
    }
    String name = ServerTools.getDisplayableImageName(server);
    ImagePlus imp = new ImagePlus(name, stack);
    CompositeImage impComp = null;
    if (imp.getType() != ImagePlus.COLOR_RGB && nChannels > 1) {
        impComp = new CompositeImage(imp, CompositeImage.COMPOSITE);
        imp = impComp;
    }
    imp.setCalibration(cal);
    imp.setDimensions(nChannels, nZ, nT);
    // Set colors, if necesssary
    if (impComp != null) {
        for (int c = 0; c < nChannels; c++) {
            impComp.setChannelLut(LUT.createLutFromColor(ColorToolsAwt.getCachedColor(server.getChannel(c).getColor())), c + 1);
        }
    }
    return imp;
}
Also used : ImageStack(ij.ImageStack) CompositeImage(ij.CompositeImage) Calibration(ij.measure.Calibration) PixelCalibration(qupath.lib.images.servers.PixelCalibration) PixelCalibration(qupath.lib.images.servers.PixelCalibration) RegionRequest(qupath.lib.regions.RegionRequest) ImagePlus(ij.ImagePlus)

Example 22 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class SLICSuperpixelsPlugin method getPreferredDownsample.

private static double getPreferredDownsample(final ImageData<BufferedImage> imageData, final ParameterList params) {
    PixelCalibration cal = imageData.getServer().getPixelCalibration();
    boolean hasPixelSizeMicrons = cal.hasPixelSizeMicrons();
    double spacingPixels = hasPixelSizeMicrons ? params.getDoubleParameterValue("spacingMicrons") / cal.getAveragedPixelSizeMicrons() : params.getDoubleParameterValue("spacingPixels");
    // We aim to have about PREFERRED_PIXEL_SPACING spacing, so need to downsample the image accordingly
    double downsample = Math.max(1, Math.round(spacingPixels / PREFERRED_PIXEL_SPACING));
    return downsample;
}
Also used : PixelCalibration(qupath.lib.images.servers.PixelCalibration)

Example 23 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class IJTools method estimateDownsampleFactor.

/**
 * Estimate the downsample factor for an image region extracted from an image server, based upon
 * the ratio of pixel sizes if possible or ratio of dimensions if necessary.
 * <p>
 * Note that the ratio of dimensions is only suitable if the full image has been extracted!
 *
 * @param imp
 * @param server
 * @return
 */
public static double estimateDownsampleFactor(final ImagePlus imp, final ImageServer<?> server) {
    // Try to get the downsample factor from pixel size;
    // if that doesn't work, resort to trying to get it from the image dimensions
    double downsampleFactor;
    Calibration cal = imp.getCalibration();
    double xMicrons = IJTools.tryToParseMicrons(cal.pixelWidth, cal.getXUnit());
    double yMicrons = IJTools.tryToParseMicrons(cal.pixelHeight, cal.getYUnit());
    boolean ijHasMicrons = !Double.isNaN(xMicrons) && !Double.isNaN(yMicrons);
    PixelCalibration pixelCalibration = server.getPixelCalibration();
    if (pixelCalibration.hasPixelSizeMicrons() && ijHasMicrons) {
        double downsampleX = xMicrons / pixelCalibration.getPixelWidthMicrons();
        double downsampleY = yMicrons / pixelCalibration.getPixelHeightMicrons();
        if (GeneralTools.almostTheSame(downsampleX, downsampleY, 0.001))
            logger.debug("ImageJ downsample factor is being estimated from pixel sizes");
        else
            logger.warn("ImageJ downsample factor is being estimated from pixel sizes (and these don't seem to match! {} and {})", downsampleX, downsampleY);
        downsampleFactor = (downsampleX + downsampleY) / 2.0;
    } else {
        double downsampleX = (double) server.getWidth() / imp.getWidth();
        double downsampleY = (double) server.getHeight() / imp.getHeight();
        if (GeneralTools.almostTheSame(downsampleX, downsampleY, 0.001))
            logger.warn("ImageJ downsample factor is being estimated from image dimensions - assumes that ImagePlus corresponds to the full image server");
        else
            logger.warn("ImageJ downsample factor is being estimated from image dimensions - assumes that ImagePlus corresponds to the full image server (and these don't seem to match! {} and {})", downsampleX, downsampleY);
        downsampleFactor = (downsampleX + downsampleY) / 2.0;
    }
    return downsampleFactor;
}
Also used : Calibration(ij.measure.Calibration) PixelCalibration(qupath.lib.images.servers.PixelCalibration) PixelCalibration(qupath.lib.images.servers.PixelCalibration)

Example 24 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class TestBioFormatsImageServer method printSummary.

/**
 * Print a readable summary of an {@code ImageServer} along with some key metadata.
 *
 * @param server
 */
void printSummary(final ImageServer<?> server) {
    PixelCalibration cal = server.getPixelCalibration();
    logger.info(String.format("%s: %d x %d (c=%d, z=%d, t=%d), bpp=%d, mag=%.2f, downsamples=[%s], res=[%.4f,%.4f,%.4f]", server.getPath(), server.getWidth(), server.getHeight(), server.nChannels(), server.nZSlices(), server.nTimepoints(), server.getPixelType(), server.getMetadata().getMagnification(), GeneralTools.arrayToString(Locale.getDefault(Locale.Category.FORMAT), server.getPreferredDownsamples(), 4), cal.getPixelWidthMicrons(), cal.getPixelHeightMicrons(), cal.getZSpacingMicrons()));
}
Also used : PixelCalibration(qupath.lib.images.servers.PixelCalibration)

Example 25 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class TestBioFormatsImageServer method testProject.

void testProject(Project<BufferedImage> project) {
    // We're not really testing Bio-Formats... and the messages can get in the way
    DebugTools.enableIJLogging(false);
    DebugTools.setRootLevel("error");
    List<ProjectImageEntry<BufferedImage>> entries = project.getImageList();
    System.out.println("Testing project with " + entries.size() + " entries: " + Project.getNameFromURI(project.getURI()));
    for (ProjectImageEntry<BufferedImage> entry : entries) {
        // String serverPath = entry.getServerPath();
        // System.out.println("Opening: " + serverPath);
        // String pathFile = BioFormatsImageServer.splitFilePathAndSeriesName(serverPath)[0];
        // if (!new File(pathFile).exists()) {
        // System.err.println("File does not exist for server path " + serverPath + " - will skip");
        // }
        BioFormatsImageServer server = null;
        BufferedImage img = null;
        BufferedImage imgThumbnail = null;
        ImagePlus imp = null;
        int tileSize = 256;
        int z = 0;
        int t = 0;
        try {
            // Create the server
            server = (BioFormatsImageServer) entry.getServerBuilder().build();
            // server = (BioFormatsImageServer)ImageServerProvider.buildServer(serverPath, BufferedImage.class, "--classname", BioFormatsServerBuilder.class.getName());
            // Read a thumbnail
            imgThumbnail = server.getDefaultThumbnail(server.nZSlices() / 2, 0);
            // Read from the center of the image
            int w = server.getWidth() < tileSize ? server.getWidth() : tileSize;
            int h = server.getHeight() < tileSize ? server.getHeight() : tileSize;
            z = (int) (server.nZSlices() / 2);
            t = (int) (server.nTimepoints() / 2);
            RegionRequest request = RegionRequest.createInstance(server.getPath(), 1, (server.getWidth() - w) / 2, (server.getHeight() - h) / 2, w, h, z, t);
            img = server.readBufferedImage(request);
            // (Skip if we have multiple series, as the setFlattenedResolutions() status can cause confusion)
            if (server.getPreferredDownsamples().length == 1 || !server.containsSubImages()) {
                ImporterOptions options = new ImporterOptions();
                int series = server.getSeries();
                options.setId(server.getFile().getAbsolutePath());
                options.setOpenAllSeries(false);
                options.setSeriesOn(series, true);
                options.setCrop(true);
                options.setCropRegion(server.getSeries(), new Region(request.getX(), request.getY(), request.getWidth(), request.getHeight()));
                try {
                    ImagePlus[] imps = BF.openImagePlus(options);
                    assert imps.length == 1;
                    imp = imps[0];
                } catch (Exception e) {
                    logger.warn("Unable to open with ImageJ: " + server, e);
                }
            } else {
                logger.warn("Multiple multi-resolution series in file - skipping ImageJ check");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Check if we got a server at all
        assertNotNull(server);
        // Check if we got an image
        assertNotNull(img);
        // Get the thumbnail
        assertNotNull(imgThumbnail);
        // Check channel numbers
        assertEquals(img.getRaster().getNumBands(), server.nChannels());
        assertEquals(imgThumbnail.getRaster().getNumBands(), server.nChannels());
        // Check pixel sizes
        if (imp != null) {
            PixelCalibration cal = server.getPixelCalibration();
            if ("micron".equals(imp.getCalibration().getXUnit()))
                assertEquals(imp.getCalibration().pixelWidth, cal.getPixelWidthMicrons(), 0.00001);
            else
                assertTrue(Double.isNaN(cal.getPixelWidthMicrons()));
            if ("micron".equals(imp.getCalibration().getXUnit()))
                assertEquals(imp.getCalibration().pixelHeight, cal.getPixelHeightMicrons(), 0.00001);
            else
                assertTrue(Double.isNaN(cal.getPixelHeightMicrons()));
            // Check z-slices, if appropriate
            if (server.nZSlices() > 1) {
                if ("micron".equals(imp.getCalibration().getZUnit()))
                    assertEquals(imp.getCalibration().pixelDepth, cal.getZSpacingMicrons(), 0.00001);
                else
                    assertTrue(Double.isNaN(cal.getZSpacingMicrons()));
            }
            // Check dimensions by comparison with ImageJ
            assertEquals(img.getWidth(), imp.getWidth());
            assertEquals(img.getHeight(), imp.getHeight());
            assertEquals(server.nChannels(), imp.getNChannels());
            assertEquals(server.nTimepoints(), imp.getNFrames());
            assertEquals(server.nZSlices(), imp.getNSlices());
            // Check actual pixel values
            float[] samples = null;
            float[] samplesIJ = null;
            for (int c = 0; c < server.nChannels(); c++) {
                samples = img.getRaster().getSamples(0, 0, img.getWidth(), img.getHeight(), c, samples);
                imp.setPosition(c + 1, z + 1, t + 1);
                samplesIJ = (float[]) imp.getProcessor().convertToFloatProcessor().getPixels();
                // I am having some trouble comparing the full array with Java 10... trouble appears on IJ side..?
                assertEquals(samples[0], samplesIJ[0], (float) 0.00001);
            // assertArrayEquals(samples, samplesIJ, (float)0.00001);
            }
        }
        printSummary(server);
    }
}
Also used : PixelCalibration(qupath.lib.images.servers.PixelCalibration) ImagePlus(ij.ImagePlus) BufferedImage(java.awt.image.BufferedImage) ImporterOptions(loci.plugins.in.ImporterOptions) Region(loci.common.Region) ProjectImageEntry(qupath.lib.projects.ProjectImageEntry) RegionRequest(qupath.lib.regions.RegionRequest)

Aggregations

PixelCalibration (qupath.lib.images.servers.PixelCalibration)31 BufferedImage (java.awt.image.BufferedImage)9 ArrayList (java.util.ArrayList)8 ROI (qupath.lib.roi.interfaces.ROI)8 RegionRequest (qupath.lib.regions.RegionRequest)7 MeasurementList (qupath.lib.measurements.MeasurementList)6 PathObject (qupath.lib.objects.PathObject)6 Calibration (ij.measure.Calibration)5 PathCellObject (qupath.lib.objects.PathCellObject)5 ParameterList (qupath.lib.plugins.parameters.ParameterList)5 List (java.util.List)4 Collection (java.util.Collection)3 HashMap (java.util.HashMap)3 Map (java.util.Map)3 ImagePlus (ij.ImagePlus)2 ByteProcessor (ij.process.ByteProcessor)2 FloatProcessor (ij.process.FloatProcessor)2 ImageProcessor (ij.process.ImageProcessor)2 Graphics2D (java.awt.Graphics2D)2 LinkedHashMap (java.util.LinkedHashMap)2