%classpath config resolver scijava.public https://maven.scijava.org/content/groups/public %classpath add mvn net.imagej imagej 2.0.0-rc-71 ij = new net.imagej.ImageJ() import net.imglib2.img.Img import net.imglib2.img.array.ArrayImgFactory import net.imglib2.type.numeric.integer.UnsignedByteType // will create a window showing a black 400x320 image long[] dimensions = [400, 320] final Img< UnsignedByteType > img = new ArrayImgFactory<>( new UnsignedByteType() ).create( dimensions ) import net.imglib2.img.Img import net.imglib2.img.array.ArrayImgFactory import net.imglib2.type.numeric.integer.UnsignedByteType import io.scif.img.IO // save path for an image of Lena path = "https://samples.fiji.sc/new-lenna.jpg" // load image final Img< UnsignedByteType > img = IO.openImg( path, new ArrayImgFactory<>( new UnsignedByteType() ) ); import net.imglib2.img.array.ArrayImgs long[] dimensions = [400, 320] img = ArrayImgs.unsignedBytes(dimensions) r = img.randomAccess() random = new Random() 1000.times { x = ( int ) ( random.nextFloat() * img.max( 0 ) ) y = ( int ) ( random.nextFloat() * img.max( 1 ) ) r.setPosition( x, 0 ) r.setPosition( y, 1 ) t = r.get() t.set( 255 ) } img import java.util.Random import net.imglib2.* construct01 = new Object() { def void draw( final RandomAccessibleInterval< T > img, final T value ) { // get the number of dimensions final int n = img.numDimensions() // Taking a general Interval means that we no longer can assume // that the interval starts at coordinates (0,0,…,0). Thus we need // to make a final modification to correctly draw between min and max of the interval. final long[] min = new long[ n ] img.min( min ) final long[] scale = new long[ n ] for ( int d = 0; d < n; ++d ) { scale[ d ] = img.max( d ) - min[ d ] } final long[] pos = new long[ n ] // create a RandomAccess to the image (now the generic type, T) // Img implements the RandomAccessible interface, // thus we can use randomAccess() to obtain one final RandomAccess< T > r = img.randomAccess() final Random random = new Random() for ( int i = 0; i < 1000; ++i ) { // loop over all dimensions when setting the position of the RandomAccess for ( int d = 0; d < n; ++d ) { pos[ d ] = min[ d ] + ( long ) ( random.nextFloat() * scale[ d ] ) } // set the position r.setPosition( pos ) // get() the pixel at that coordinate and // set the pixel value via this reference r.get().set( value ) } } } import net.imglib2.type.numeric.real.FloatType import net.imglib2.img.array.ArrayImgs long[] dimensions = [400, 320, 5] img = ArrayImgs.floats(dimensions) construct01.draw( img, new FloatType(255f)) // call draw() method img import io.scif.img.IO // load an image of diatoms path = "https://wsr.imagej.net/images/Diatoms.jpg" diatoms = IO.open(path) import net.imglib2.Cursor import net.imglib2.img.Img // we get a Cursor from the image cursor = diatoms.cursor() int max = 0 // we iterate over the image while ( cursor.hasNext() ) { // get the value at the current position t = cursor.next() // check that if greater than max; if so, set to max max = Math.max( t.get(), max ) } "maximum = " + max import net.imglib2.* construct02 = new Object() { // IterableInterval is the most general type to use, but must be Comparable // the return value of findmax is a Cursor, holds value and coordinates public static < T extends Comparable> Cursor< T > findmax( final IterableInterval< T > iterable ) { final Cursor< T > cursor = iterable.cursor() cursor.fwd() Cursor< T > max = cursor.copyCursor() while ( cursor.hasNext() ) { // to remember the maximum, we simply take a new copy // of the iterating cursor whenever a better max value is found if ( cursor.next().compareTo( max.get() ) > 0 ) { max = cursor.copyCursor() } } return max } } // use findmax and get the maximum value and coordinates from the resulting Cursor, // using the dimension-by-dimension getLongPosition() of the Localizable interface max = construct02.findmax( diatoms ) "max = " + max.get().get() + " found at (" + max.getLongPosition( 0 ) + ", " + max.getLongPosition( 1 ) + ")" import io.scif.img.ImgOpener // define the file to open path = "https://samples.fiji.sc/tutorials/DrosophilaWing.tif" // create the ImgOpener. The type (e.g. ArrayImg, PlanarImg, CellImg) is // automatically determined. For a small image that fits in memory, this // should open as an ArrayImg. imgOpener = new ImgOpener() // open with ImgOpener. image = imgOpener.openImgs(path).get(0) import io.scif.config.SCIFIOConfig import io.scif.config.SCIFIOConfig.ImgMode // create the SCIFIOConfig. This gives us configuration control over how // the ImgOpener will open its datasets. config = new SCIFIOConfig() // If we know what type of Img we want, we can encourage their use through // an SCIFIOConfig instance. CellImgs dynamically load image regions and are // useful when an image won't fit in memory config.imgOpenerSetImgModes( ImgMode.CELL ) // open with ImgOpener as a CellImg imageCell = imgOpener.openImg( path, config ) import net.imglib2.img.cell.CellImgFactory import net.imglib2.type.numeric.real.FloatType // create the ImgFactory based on cells (cellsize = 5x5x5...x5) that will // instantiate the Img imgFactory = new CellImgFactory<>( new FloatType(), 5 ) // create an 3d-Img with dimensions 20x30x40 (here cellsize is 5x5x5)Ø long[] dimensions = [20, 30, 40] img1 = imgFactory.create( dimensions ) import net.imglib2.img.Img; import net.imglib2.img.ImgFactory; // create another image with the same size // note that the input provides the size for the new image as it implements // the Interval interface img2 = imgFactory.create( img1 ) import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType import net.imglib2.view.Views // open file as float with ImgOpener img = new ImgOpener().openImg( "https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType() ) // use a View to define an interval (min and max coordinate, inclusive) to display long[] min = [200, 200] long[] max = [500, 350] view = Views.interval( img, min, max) import net.imglib2.view.Views // display the same area rotated by 90 degrees (x-axis (0) and y-axis (1) switched) viewRotated = Views.rotate(view, 0, 1) import io.scif.img.ImgIOException import net.imglib2.Cursor import net.imglib2.img.Img import net.imglib2.type.Type /** * Generic, type-agnostic method to create an identical copy of an Img * * @param input - the Img to copy * @return - the copy of the Img */ construct03 = new Object() { public < T extends Type< T > > Img< T > copyImage( final Img< T > input ) { // create a new Image with the same properties // note that the input provides the size for the new image as it implements // the Interval interface output = input.factory().create( input ) // create a cursor for both images cursorInput = input.cursor() cursorOutput = output.cursor() // iterate over the input while ( cursorInput.hasNext()) { // move both cursors forward by one pixel cursorInput.fwd() cursorOutput.fwd() // set the value of this pixel of the output image to the same as the input, // every Type supports T.set( T type ) cursorOutput.get().set( cursorInput.get() ) } // return the copy return output } } import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType // open with ImgOpener as a FloatType img = new ImgOpener().openImg( "https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType() ) // copy the image, as it is a generic method it also works with FloatType duplicate = construct03.copyImage( img ) import net.imglib2.Cursor import net.imglib2.img.Img import net.imglib2.img.ImgFactory import net.imglib2.type.Type /** * WARNING: This method makes a mistake on purpose! */ construct04 = new Object() { public < T extends Type< T >> Img< T > copyImageWrong( final Img< T > input, final ImgFactory< T > imgFactory ) { // create a new Image with the same dimensions but the other imgFactory // note that the input provides the size for the new image as it // implements the Interval interface output = imgFactory.create( input ) // create a cursor for both images cursorInput = input.cursor() cursorOutput = output.cursor() // iterate over the input cursor while ( cursorInput.hasNext()) { // move both forward cursorInput.fwd() cursorOutput.fwd() // set the value of this pixel of the output image, every Type supports T.set( T type ) cursorOutput.get().set( cursorInput.get() ) } // return the copy return output } } import io.scif.img.ImgOpener import net.imglib2.img.Img import net.imglib2.img.array.ArrayImgFactory import net.imglib2.img.cell.CellImgFactory import net.imglib2.type.numeric.real.FloatType // open with ImgOpener. In addition to using ImgOptions, we can directly // pass an ImgFactory to the ImgOpener. This bypasses the Img selection // heuristic and allows custom ImgFactory implementations to be used img = (Img< FloatType >) new ImgOpener().openImg( "https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new ArrayImgFactory<>(new FloatType()) ) // copy the image into a CellImg with a cellsize of 20x20 duplicate = construct04.copyImageWrong( img, new CellImgFactory<>( new FloatType(), 20 ) ) import net.imglib2.Cursor import net.imglib2.RandomAccess import net.imglib2.img.Img import net.imglib2.img.ImgFactory import net.imglib2.type.Type /** * This method copies the image correctly, using a RandomAccess. */ construct05 = new Object() { public < T extends Type< T >> Img< T > copyImageCorrect( final Img< T > input, final ImgFactory< T > imgFactory ) { // create a new Image with the same dimensions but the other imgFactory // note that the input provides the size for the new image by implementing the Interval interface Img< T > output = imgFactory.create( input ) // create a cursor that automatically localizes itself on every move Cursor< T > cursorInput = input.localizingCursor() RandomAccess< T > randomAccess = output.randomAccess() // iterate over the input cursor while ( cursorInput.hasNext()) { // move input cursor forward cursorInput.fwd() // set the output cursor to the position of the input cursor randomAccess.setPosition( cursorInput ) // set the value of this pixel of the output image, every Type supports T.set( T type ) randomAccess.get().set( cursorInput.get() ) } // return the copy return output } } import io.scif.img.ImgOpener import net.imglib2.img.Img import net.imglib2.img.array.ArrayImgFactory import net.imglib2.img.cell.CellImgFactory import net.imglib2.type.numeric.real.FloatType // open with ImgOpener. In addition to using ImgOptions, we can directly // pass an ImgFactory to the ImgOpener. This bypasses the Img selection // heuristic and allows custom ImgFactory implementations to be used img = (Img< FloatType >) new ImgOpener().openImg( "https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new ArrayImgFactory<>( new FloatType() ) ) // copy the image into a CellImg with a cellsize of 20x20 duplicate = construct05.copyImageCorrect( img, new CellImgFactory<>( new FloatType(), 20 ) ) import net.imglib2.IterableInterval import net.imglib2.RandomAccessible import net.imglib2.type.Type /** * Copy from a source that is just RandomAccessible to an IterableInterval. Latter one defines * size and location of the copy operation. It will query the same pixel locations of the * IterableInterval in the RandomAccessible. It is up to the developer to ensure that these * coordinates match. * * Note that both, input and output could be Views, Img or anything that implements * those interfaces. * * @param source - a RandomAccess as source that can be infinite * @param target - an IterableInterval as target */ construct06 = new Object() { public < T extends Type< T > > void copy( final RandomAccessible< T > source, final IterableInterval< T > target ) { // create a cursor that automatically localizes itself on every move targetCursor = target.localizingCursor() sourceRandomAccess = source.randomAccess() // iterate over the input cursor while ( targetCursor.hasNext()) { // move input cursor forward targetCursor.fwd() // set the output cursor to the position of the input cursor sourceRandomAccess.setPosition( targetCursor ) // set the value of this pixel of the output image, every Type supports T.set( T type ) targetCursor.get().set( sourceRandomAccess.get() ) } } } import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType // open with ImgOpener as a float img = new ImgOpener().openImg("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()) // copy & display an image duplicate = img.factory().create( img ) construct06.copy( img, duplicate ) duplicate import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType import net.imglib2.view.Views // open with ImgOpener as a float img = new ImgOpener().openImg("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()) // use a View to define an interval as source for copying // Views.offsetInterval() does not only define where it is, but also adds a translation // so that the minimal coordinate (upper left) of the view maps to (0,0) long[] offset = [100, 100] long[] dimension = [250, 150] viewSource = Views.offsetInterval( img, offset, dimension) // and as target long[] targetOffset = [500, 200] long[] targetDimension = [250, 150] viewTarget = Views.offsetInterval( img, targetOffset, targetDimension) // now we make the target iterable // (which is possible because it is a RandomAccessibleInterval) iterableTarget = Views.iterable( viewTarget ) // copy it into the original image (overwriting part of img) construct06.copy( viewSource, iterableTarget ) // show the original image img import net.imglib2.type.Type construct01 = new Object() { /** * Compute the min and max for any {@link Iterable}, like an {@link Img}. * * The only functionality we need for that is to iterate. Therefore we need no {@link Cursor} * that can localize itself, neither do we need a {@link RandomAccess}. So we simply use the * most simple interface in the hierarchy. * * @param input - the input that has to just be {@link Iterable} * @param min - the type that will have min * @param max - the type that will have max */ public & Type> void computeMinMax(Iterable input, T min, T max) { // create a cursor for the image (the order does not matter) Iterator iterator = input.iterator() // initialize min and max with the first image value T type = iterator.next() min.set(type) max.set(type) // loop over the rest of the data and determine min and max value while (iterator.hasNext()) { // we need this type more than once type = iterator.next() if (type.compareTo(min) < 0) { min.set( type ) } if (type.compareTo(max) > 0) { max.set(type) } } } } import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType /** * Perform a generic min & max search * * @author Stephan Preibisch & Stephan Saalfeld * */ // open with ImgOpener img = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) // create two empty variables min = img.firstElement().createVariable() max = img.firstElement().createVariable() // compute min and max of the Image construct01.computeMinMax(img, min, max) ["minimum Value (img)": min.getRealDouble(), "maximum Value (img)": max.getRealDouble()] import java.util.ArrayList import net.imglib2.type.numeric.real.FloatType /** * Perform a generic min & max search * * @author Stephan Preibisch & Stephan Saalfeld * */ // it will work as well on a normal ArrayList ArrayList list = new ArrayList() // put values 0 to 10 into the ArrayList for (int i = 0; i <= 10; ++i) { list.add(new FloatType(i)) } // create two empty variables min = new FloatType() max = new FloatType() // compute min and max of the ArrayList construct01.computeMinMax(list, min, max) ["minimum Value (arraylist)": min.getRealDouble(), "maximum Value (arraylist)": max.getRealDouble()] import net.imglib2.type.Type import net.imglib2.IterableInterval import net.imglib2.Point import net.imglib2.Cursor /** * Perform a generic min/max search. * * @author Stephan Preibisch & Stephan Saalfeld * */ construct02 = new Object() { /** * Compute the location of the minimal and maximal intensity for any IterableInterval, * like an {@link Img}. * * The functionality we need is to iterate and retrieve the location. Therefore we need a * Cursor that can localize itself. * Note that we do not use a LocalizingCursor as localization just happens from time to time. * * @param input - the input that has to just be {@link IterableInterval} * @param minLocation - the location for the minimal value * @param maxLocation - the location of the maximal value */ public & Type> void computeMinMaxLocation(IterableInterval input, Point minLocation, Point maxLocation) { // create a cursor for the image (the order does not matter) final Cursor cursor = input.cursor() // initialize min and max with the first image value T type = cursor.next() T min = type.copy() T max = type.copy() // loop over the rest of the data and determine min and max value while (cursor.hasNext()) { // we need this type more than once type = cursor.next() if (type.compareTo(min) < 0) { min.set(type) minLocation.setPosition(cursor) } if (type.compareTo(max) > 0) { max.set(type) maxLocation.setPosition(cursor) } } } } import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType import net.imglib2.Point // open with ImgOpener img = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) // create two location objects locationMin = new Point(img.numDimensions()) locationMax = new Point(img.numDimensions()) // compute location of min and max construct02.computeMinMaxLocation(img, locationMin, locationMax) ["location of minimum Value (img)": locationMin.toString(), "location of maximum Value (img)": locationMax.toString()] import net.imglib2.type.numeric.RealType import net.imglib2.util.RealSum /** * Perform a generic computation of average intensity * * @author Stephan Preibisch & Stephan Saalfeld * */ construct03 = new Object() { /** * Compute the average intensity for an {@link Iterable}. * * @param input - the input data * @return - the average as double */ public > double computeAverage(Iterable input) { // Count all values using the RealSum class. // It prevents numerical instabilities when adding up millions of pixels realSum = new RealSum() count = 0 for (T type : input) { realSum.add(type.getRealDouble()) ++count } return realSum.getSum() / count } } import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType // open with ImgOpener img = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) // compute average of the image avg = construct03.computeAverage(img) "average Value: " + avg import java.util.Random import net.imglib2.Point import net.imglib2.RandomAccessibleInterval import net.imglib2.algorithm.region.hypersphere.HyperSphere import net.imglib2.algorithm.region.hypersphere.HyperSphereCursor import net.imglib2.exception.ImgLibException import net.imglib2.type.numeric.RealType import net.imglib2.util.Util /** * Example 4a - Drawing a sphere full of spheres * * @author Stephan Preibisch & Stephan Saalfeld * */ construct01 = new Object() { /** * Draws a sphere that contains lots of small spheres into the center of the * interval. * * @param value type * @param randomAccessible - the image data to write to * @param minValue - the minimal intensity of one of the small spheres * @param maxValue - the maximal intensity of one of the small spheres */ public > void drawSpheres(final RandomAccessibleInterval randomAccessible, final double minValue, final double maxValue) { // the number of dimensions int numDimensions = randomAccessible.numDimensions() // define the center and radius Point center = new Point(randomAccessible.numDimensions()) int minSize = randomAccessible.dimension(0) for (int d = 0; d < numDimensions; ++d) { int size = randomAccessible.dimension(d) int half = size / 2 center.setPosition(half, d) minSize = Math.min(minSize, size) } // define the maximal radius of the small spheres final int maxRadius = 5 // compute the radius of the large sphere so that we do not draw // outside of the defined interval final long radiusLargeSphere = minSize / 2 - maxRadius - 1 // instantiate a random number generator final Random rnd = new Random() // define a hypersphere (n-dimensional sphere) HyperSphere hyperSphere = new HyperSphere(randomAccessible, center, radiusLargeSphere) // create a cursor on the hypersphere HyperSphereCursor cursor = hyperSphere.cursor() while (cursor.hasNext()) { cursor.fwd() // the random radius of the current small hypersphere final int radius = rnd.nextInt(maxRadius) + 1 // instantiate a small hypersphere at the location of the current pixel in the large hypersphere HyperSphere smallSphere = new HyperSphere(randomAccessible, cursor, radius) // define the random intensity for this small sphere final double randomValue = rnd.nextDouble() // take only every 4^dimension'th pixel by chance so that it is not too crowded if (Math.round(randomValue * 100) % Util.pow(4, numDimensions) == 0) { // scale to right range randomValue = rnd.nextDouble() * (maxValue - minValue) + minValue // set the value to all pixels in the small sphere if the intensity is brighter than the existing one for (final T value : smallSphere) { value.setReal(Math.max(randomValue, value.getRealDouble())) } } } } } import net.imglib2.type.numeric.integer.UnsignedByteType import net.imglib2.img.Img import net.imglib2.img.ImgFactory import net.imglib2.img.array.ArrayImgFactory import net.imglib2.view.Views long[] dims = [256, 256, 256] ImgFactory imgFactory = new ArrayImgFactory<>( new UnsignedByteType() ) Img img = imgFactory.create( dims ) // draw a small sphere for every pixel of a larger sphere int minv = 0 int maxv = 255 construct01.drawSpheres(img, minv, maxv) // Display the middle slice Views.hyperSlice(img, 2, 128) import net.imglib2.Cursor import net.imglib2.Interval import net.imglib2.RandomAccessibleInterval import net.imglib2.algorithm.gauss.Gauss import net.imglib2.algorithm.neighborhood.Neighborhood import net.imglib2.algorithm.neighborhood.RectangleShape import net.imglib2.algorithm.region.hypersphere.HyperSphere import net.imglib2.img.Img import net.imglib2.img.ImgFactory import net.imglib2.img.array.ArrayImgFactory import net.imglib2.type.NativeType import net.imglib2.type.logic.BitType import net.imglib2.type.numeric.RealType import net.imglib2.util.Intervals import net.imglib2.view.Views construct02 = new Object() { /** * Checks all pixels in the image if they are a local minima and draws a circle into the output if they are * * @param value type * @param * @param source - the image data to work on * @param imageFactory - the factory for the output img * @param outputType - the output type * @return - an Img with circles on locations of a local minimum */ public static , U extends RealType> Img findAndDisplayLocalMinima( RandomAccessibleInterval source, ImgFactory imageFactory) { // Create a new image for the output Img output = imageFactory.create(source) // define an interval that is one pixel smaller on each side in each dimension, // so that the search in the 8-neighborhood (3x3x3...x3) never goes outside // of the defined interval Interval interval = Intervals.expand(source, -1) // create a view on the source with this interval source = Views.interval(source, interval) // create a Cursor that iterates over the source and checks in an 8-neighborhood if it is a minima final Cursor center = Views.iterable(source).cursor() // instantiate a RectangleShape to access rectangular local neighborhoods // of radius 1 (that is 3x3x...x3 neighborhoods), skipping the center pixel // (this corresponds to an 8-neighborhood in 2d or 26-neighborhood in 3d, ...) final RectangleShape shape = new RectangleShape(1, true) // iterate over the set of neighborhoods in the image for (final Neighborhood localNeighborhood : shape.neighborhoods(source)) { // what is the value that we investigate? // (the center cursor runs over the image in the same iteration order as neighborhood) final T centerValue = center.next() // keep this boolean true as long as no other value in the local neighborhood // is larger or equal boolean isMinimum = true // check if all pixels in the local neighborhood that are smaller for (final T value : localNeighborhood) { // test if the center is smaller than the current pixel value if (centerValue.compareTo(value) >= 0) { isMinimum = false break } } if (isMinimum) { // draw a sphere of radius one in the new image HyperSphere hyperSphere = new HyperSphere(output, center, 1) // set every value inside the sphere to 1 for (U value : hyperSphere) { value.setOne() } } } return output } } import io.scif.img.ImgOpener import net.imglib2.img.Img import net.imglib2.algorithm.gauss.Gauss import net.imglib2.type.logic.BitType import net.imglib2.img.array.ArrayImgFactory import net.imglib2.type.numeric.real.FloatType img = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif").get(0) // first we do a small in-place gaussian smoothing with a sigma of 1.0 double[] sigmas = [1.0, 1.0] Gauss.inDoubleInPlace(sigmas, img) // find local minima and paint them into another image as spheres featureMap = construct02.findAndDisplayLocalMinima(img, new ArrayImgFactory<>( new BitType() ) ) import io.scif.img.ImgOpener import net.imglib2.RandomAccessible import net.imglib2.img.Img import net.imglib2.type.numeric.real.FloatType import net.imglib2.view.Views import net.imglib2.FinalInterval import net.imglib2.outofbounds.OutOfBoundsConstantValueFactory import net.imglib2.view.ExtendedRandomAccessibleInterval enum ExtendType { EXTEND_VALUE_0, EXTEND_VALUE_128, EXTEND_RANDOM_256, EXTEND_MIRROR_SINGLE, EXTEND_MIRROR_DOUBLE, EXTEND_PERIODIC, EXTEND_RANDOM_CUSTOM } // open with ImgOpener as a FloatType image = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWingSmall.tif", new FloatType()).get(0) // in order to visualize them, we have to define a new interval // on them which can be displayed min = new long[image.numDimensions()] max = new long[image.numDimensions()] for ( int d = 0; d < image.numDimensions(); ++d ) { // we add/subtract another 30 pixels here to illustrate // that it is really infinite and does not only work once min[d] = -image.dimension( d ) - 90 max[d] = image.dimension( d ) * 2 - 1 + 90 } // define the Interval on the infinite random accessibles interval = new FinalInterval(min, max) // change this variable to switch for different kind of out-of-bounds display imgs = [:] for (type in [ExtendType.EXTEND_VALUE_0, ExtendType.EXTEND_VALUE_128, ExtendType.EXTEND_RANDOM_256, ExtendType.EXTEND_MIRROR_SINGLE, ExtendType.EXTEND_MIRROR_DOUBLE, ExtendType.EXTEND_PERIODIC, ExtendType.EXTEND_RANDOM_CUSTOM]) { switch (type) { case ExtendType.EXTEND_VALUE_0: // create an infinite view where all values outside of the Interval are 0 infinite = Views.extendValue(image, new FloatType(0)) s = Views.interval(infinite, interval) break case ExtendType.EXTEND_VALUE_128: // create an infinite view where all values outside of the Interval are 128 infinite = Views.extendValue(image, new FloatType(128)) s = Views.interval(infinite, interval) break case ExtendType.EXTEND_RANDOM_256: // create an infinite view where all outside values are random in a range of 0-255 infinite = Views.extendRandom(image, 0, 255); s = Views.interval(infinite, interval) break case ExtendType.EXTEND_MIRROR_SINGLE: // create an infinite view where all values outside of the Interval are // the mirrored content, the mirror is the last pixel infinite = Views.extendMirrorSingle(image); s = Views.interval(infinite, interval) break case ExtendType.EXTEND_MIRROR_DOUBLE: // create an infinite view where all values outside of the Interval are // the mirrored content, the mirror is BEHIND the last pixel, // i.e. the first and last pixel are always duplicated infinite = Views.extendMirrorDouble(image); s = Views.interval(infinite, interval) break case ExtendType.EXTEND_PERIODIC: // all values outside of the Interval periodically repeat the image content // (like the Fourier space assumes) infinite = Views.extendPeriodic(image); s = Views.interval(infinite, interval) break case ExtendType.EXTEND_RANDOM_CUSTOM: // if you implemented your own strategy that you want to instantiate, it will look like this infinite = new ExtendedRandomAccessibleInterval>( image, new OutOfBoundsConstantValueFactory>(new FloatType(196))); s = Views.interval(infinite, interval) break default: infinite = Views.extendValue(image, new FloatType(0)) s = Views.interval(infinite, interval) } imgs.put(type.toString(), s) } ij.notebook().display([imgs]) import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType import net.imglib2.algorithm.gauss.Gauss import net.imglib2.img.Img // open with ImgOpener as a FloatType Img image = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) // perform gaussian convolution with float precision sigma = new double[image.numDimensions()] for (int d = 0; d < image.numDimensions(); ++d) { sigma[d] = 8.0 } output = Gauss.toFloat(sigma, image) import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType import net.imglib2.view.Views import net.imglib2.img.array.ArrayImgFactory import net.imglib2.algorithm.gauss3.Gauss3 // open with ImgOpener as a FloatType image = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) // first extend the image to infinity, zeropad infiniteImg = Views.extendValue(image, new FloatType()) // now we convolve the whole image manually in-place // note that it is basically the same as the call above, just called in a more generic way // // sigma .. the sigma // infiniteImg ... the RandomAccessible that is the source for the convolution // image ... defines the RandomAccessibleInterval that is the target of the convolution Gauss3.gauss(sigma, infiniteImg, image) image import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType import net.imglib2.view.Views import net.imglib2.algorithm.gauss3.Gauss3 import net.imglib2.util.Intervals // open with ImgOpener as a FloatType image = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) // we need to extend it nevertheless as the algorithm needs more pixels from around // the convolved area and we are not sure how much exactly (although we could compute // it with some effort from the sigma). // Here we let the Views framework take care of the details. The Gauss convolution // knows which area of the source image is required, and if the extension is not needed, // it will operate on the original image with no runtime overhead. infiniteImg = Views.extendMirrorSingle(image) // define the area of the image which we want to compute interval = Intervals.createMinMax(100, 30, 500, 250) region = Views.interval(image, interval) // call the gauss, we convolve only a region and write it back to the exact same coordinates Gauss3.gauss(sigma, infiniteImg, region) image import io.scif.img.ImgOpener import net.imglib2.type.numeric.real.FloatType import net.imglib2.view.Views import net.imglib2.algorithm.gauss3.Gauss3 import net.imglib2.util.Intervals // open with ImgOpener as a FloatType image = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) double[] sigma = new double[image.numDimensions() - 1] for (int d = 0; d < sigma.length; ++d) { sigma[d] = 16.0 } // iterate over all dimensions, take always a hyperslice for (int dim = 0; dim < image.numDimensions(); ++dim) // iterate over all possible hyperslices { for (long pos = 0; pos < image.dimension(dim); ++pos) // convolve a subset of the 1-dimensional views { long s = pos / 30 if (s % 2 == 1) { // get the n-1 dimensional "slice" view = Views.hyperSlice(image, dim, pos) // compute the gauss in-place on the view Gauss3.gauss(sigma, Views.extendMirrorSingle(view), view) } } } image import net.imglib2.type.numeric.RealType import net.imglib2.type.numeric.real.FloatType import net.imglib2.util.RealSum utility = new Object() { /** * Computes the sum of all pixels in an iterable using RealSum * * @param value type * @param iterable - the image data * @return - the sum of values */ public > double sumImage(final Iterable iterable) { final RealSum sum = new RealSum() for (final T type : iterable) { sum.add(type.getRealDouble()) } return sum.getSum() } /** * Norms all image values so that their sum is 1 * * @param iterable - the image data */ public void norm(final Iterable iterable) { final double sum = sumImage(iterable) for (final FloatType type : iterable) { type.setReal(type.get() / sum) } } } // NB: The imglib2-algorithm-gpl component is licensed under the GPL; // therefore, this code snippet is also licensed under the GPL! %classpath add mvn net.imglib2 imglib2-algorithm-gpl 0.2.3 // NB: Unfortunately, due to a bug in BeakerX, the above throws NullPointerException. :-( import io.scif.img.ImgOpener import net.imglib2.img.Img import net.imglib2.type.numeric.real.FloatType //import net.imglib2.algorithm.fft2.FFTConvolution import net.imglib2.view.Views import net.imglib2.RandomAccessibleInterval // open image and kernel with ImgOpener as a FloatType image = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) kernel = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/kernelRing.tif",new FloatType()).get(0) // normalize the kernel, otherwise we add energy to the image utility.norm(kernel) // compute & show fourier convolution (in-place) //fft2 = new FFTConvolution(image, kernel) //fft2.convolve() //image import net.imglib2.type.numeric.RealType import net.imglib2.type.numeric.real.FloatType import net.imglib2.util.RealSum utility = new Object() { /** * Computes the sum of all pixels in an iterable using RealSum * * @param value type * @param iterable - the image data * @return - the sum of values */ public > double sumImage(final Iterable iterable) { final RealSum sum = new RealSum() for (final T type : iterable) { sum.add(type.getRealDouble()) } return sum.getSum() } /** * Norms all image values so that their sum is 1 * * @param iterable - the image data */ public void norm(final Iterable iterable) { final double sum = sumImage(iterable) for (final FloatType type : iterable) { type.setReal(type.get() / sum) } } } // NB: The imglib2-algorithm-gpl component is licensed under the GPL; // therefore, this code snippet is also licensed under the GPL! %classpath add mvn net.imglib2 imglib2-algorithm-gpl 0.2.3 // NB: Unfortunately, due to a bug in BeakerX, the above throws NullPointerException. :-( import io.scif.img.ImgOpener import net.imglib2.type.numeric.complex.ComplexFloatType import net.imglib2.type.numeric.real.FloatType import net.imglib2.algorithm.fft.FourierConvolution import net.imglib2.algorithm.fft.FourierTransform import net.imglib2.algorithm.fft.InverseFourierTransform // open image and kernel with ImgOpener as a FloatType image = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) template = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/WingTemplate.tif", new FloatType()).get(0) fft = new FourierTransform(template, new ComplexFloatType()) fft.process() templateFFT = fft.getResult() // complex invert the kernel ComplexFloatType c = new ComplexFloatType() for (ComplexFloatType t : templateFFT) { c.set(t) t.complexConjugate() c.mul(t) t.div(c) } // compute inverse fourier transform of the template ifft = new InverseFourierTransform(templateFFT, fft); ifft.process() templateInverse = ifft.getResult() // normalize the inverse template utility.norm(templateInverse) // compute fourier convolution of the inverse template and the image output = FourierConvolution.convolve(image, templateInverse) import net.imglib2.type.Type import net.imglib2.RealRandomAccessible import net.imglib2.RealInterval import net.imglib2.img.ImgFactory import net.imglib2.img.Img mag = new Object() { /** * Compute a magnified version of a given real interval * * @param value type * @param source - the input data * @param interval - the real interval on the source that should be * magnified * @param factory - the image factory for the output image * @param magnification - the ratio of magnification * @return - an Img that contains the magnified image content */ public > Img magnify( RealRandomAccessible source, RealInterval interval, ImgFactory factory, double magnification) { numDimensions = interval.numDimensions() // compute the number of pixels of the output and the size of the real interval pixelSize = new long[numDimensions] intervalSize = new double[numDimensions] for (int d = 0; d < numDimensions; ++d) { intervalSize[d] = interval.realMax(d) - interval.realMin(d) pixelSize[d] = Math.round(intervalSize[d] * magnification) + 1 } // create the output image output = factory.create(pixelSize) // cursor to iterate over all pixels cursor = output.localizingCursor() // create a RealRandomAccess on the source (interpolator) realRandomAccess = source.realRandomAccess() // the temporary array to compute the position tmp = new double[numDimensions] // for all pixels of the output image while (cursor.hasNext()) { cursor.fwd() // compute the appropriate location of the interpolator for (int d = 0; d < numDimensions; ++d) { tmp[d] = cursor.getDoublePosition(d) / output.realMax(d) * intervalSize[d] + interval.realMin(d) } // set the position realRandomAccess.setPosition(tmp) // set the new value cursor.get().set(realRandomAccess.get()) } return output } } import io.scif.img.ImgOpener import net.imglib2.FinalRealInterval import net.imglib2.type.numeric.real.FloatType import net.imglib2.interpolation.randomaccess.LanczosInterpolatorFactory import net.imglib2.interpolation.randomaccess.NLinearInterpolatorFactory import net.imglib2.interpolation.randomaccess.NearestNeighborInterpolatorFactory import net.imglib2.img.array.ArrayImgFactory import net.imglib2.view.Views enum InterpolationType { NEAREST_NEIGHBOR_INTERPOLATION, NLINEAR_INTERPOLATION, LANCZOS_INTERPOLATION } // open with ImgOpener as a FloatType image = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) // define the area in the interpolated image double[] min = [105.12, 40.43] double[] max = [129.56, 74.933] interval = new FinalRealInterval(min, max) imgs = [:] for (interpolant_type in [InterpolationType.NEAREST_NEIGHBOR_INTERPOLATION, InterpolationType.NLINEAR_INTERPOLATION, InterpolationType.LANCZOS_INTERPOLATION]) { // create a RandomAccessible using the factory and views method // it is important to extend the image first, the interpolation scheme might // grep pixels outside of the boundaries even when locations inside are queried // as they integrate pixel information in a local neighborhood - the size of // this neighborhood depends on which interpolator is used switch (interpolant_type) { case InterpolationType.NEAREST_NEIGHBOR_INTERPOLATION: // create an InterpolatorFactory RealRandomAccessible using nearst neighbor interpolation nn_inter_factory = new NearestNeighborInterpolatorFactory() nn_interpolant = Views.interpolate(Views.extendMirrorSingle(image), nn_inter_factory) img = mag.magnify(nn_interpolant, interval, new ArrayImgFactory<>( new FloatType() ), 10) break case InterpolationType.NLINEAR_INTERPOLATION: // create an InterpolatorFactory RealRandomAccessible using linear interpolation linear_inter_factory = new NLinearInterpolatorFactory() nlinear_interpolant = Views.interpolate(Views.extendMirrorSingle(image), linear_inter_factory) img = mag.magnify(nlinear_interpolant, interval, new ArrayImgFactory<>( new FloatType() ), 10) break case InterpolationType.LANCZOS_INTERPOLATION: // create an InterpolatorFactory RealRandomAccessible using lanczos interpolation lanczos_inter_factory = new LanczosInterpolatorFactory() lanczos_interpolant = Views.interpolate(Views.extendMirrorSingle(image), lanczos_inter_factory) img = mag.magnify(lanczos_interpolant, interval, new ArrayImgFactory<>( new FloatType() ), 10) break default: nn_inter_factory = new NearestNeighborInterpolatorFactory() nn_interpolant = Views.interpolate(Views.extendMirrorSingle(image), nn_inter_factory) img = mag.magnify(nn_interpolant, interval, new ArrayImgFactory<>( new FloatType() ), 10) } imgs.put(interpolant_type.toString(), img) } ij.notebook().display([imgs]) import net.imglib2.RealInterval import net.imglib2.RealPointSampleList import net.imglib2.type.numeric.real.FloatType import net.imglib2.RealPoint obj = new Object() { /** * Create a number of n-dimensional random points in a certain interval * having a random intensity 0...1 * * @param interval - the interval in which points are created * @param numPoints - the amount of points * * @return a RealPointSampleList (which is an IterableRealInterval) */ public RealPointSampleList createRandomPoints(RealInterval interval, int numPoints) { // the number of dimensions numDimensions = interval.numDimensions() // a random number generator Random rnd = new Random(System.currentTimeMillis()) // a list of Samples with coordinates RealPointSampleList elements = new RealPointSampleList(numDimensions) for (int i = 0; i < numPoints; ++i) { RealPoint point = new RealPoint(numDimensions) for (int d = 0; d < numDimensions; ++d) { point.setPosition( rnd.nextDouble() * (interval.realMax(d) - interval.realMin(d)) + interval.realMin(d), d ) // add a new element with a random intensity in the range 0...1 elements.add(point, new FloatType(rnd.nextFloat())) } } return elements } } import net.imglib2.FinalInterval import net.imglib2.IterableRealInterval import net.imglib2.type.numeric.real.FloatType import net.imglib2.neighborsearch.NearestNeighborSearch import net.imglib2.neighborsearch.NearestNeighborSearchOnKDTree import net.imglib2.KDTree import net.imglib2.interpolation.neighborsearch.NearestNeighborSearchInterpolatorFactory import net.imglib2.view.Views long[] range = [375, 200] // the interval in which to create random points interval = new FinalInterval(range) // create an IterableRealInterval IterableRealInterval realInterval = obj.createRandomPoints(interval, 250) // using nearest neighbor search we will be able to return a value an any position in space search = new NearestNeighborSearchOnKDTree(new KDTree(realInterval)) // make it into RealRandomAccessible using nearest neighbor search realRandomAccessible = Views.interpolate(search, new NearestNeighborSearchInterpolatorFactory()) // convert it into a RandomAccessible which can be displayed randomAccessible = Views.raster(realRandomAccessible) // set the initial interval as area to view view = Views.interval(randomAccessible, interval) import net.imglib2.img.array.ArrayImgFactory import net.imglib2.type.numeric.real.FloatType import net.imglib2.algorithm.gauss.Gauss import net.imglib2.Point // compute a gauss on it convolved = new ArrayImgFactory<>(new FloatType()).create(interval) double[] size = [3, 3] Gauss.inFloat(size, view, interval, convolved, new Point(view.numDimensions() ), convolved.factory()) // display the convolved view convolved import net.imglib2.Interval import net.imglib2.RealInterval import net.imglib2.RealPointSampleList import net.imglib2.type.numeric.real.FloatType import net.imglib2.type.numeric.RealType import net.imglib2.RealPoint import net.imglib2.RealRandomAccessible import net.imglib2.type.Type import net.imglib2.KDTree import net.imglib2.RandomAccessibleInterval import net.imglib2.neighborsearch.KNearestNeighborSearch import net.imglib2.neighborsearch.KNearestNeighborSearchOnKDTree import net.imglib2.neighborsearch.NearestNeighborSearchOnKDTree import net.imglib2.interpolation.neighborsearch.InverseDistanceWeightingInterpolatorFactory import net.imglib2.interpolation.neighborsearch.NearestNeighborSearchInterpolatorFactory import net.imglib2.view.Views obj = new Object() { /** * Sample a number of n-dimensional random points in a certain interval having a * random intensity 0...1 * * @param interval - the interval in which points are created * @param numPoints - the amount of points * * @return a RealPointSampleList (which is an IterableRealInterval) */ public > RealPointSampleList sampleRandomPoints(RealRandomAccessible input, RealInterval interval, int numPoints) { // the number of dimensions numDimensions = interval.numDimensions() // a random number generator rnd = new Random(1332441549191l) // a list of Samples with coordinates elements = new RealPointSampleList(numDimensions) // a random accessible in the image data to grep the right value realRandomAccess = input.realRandomAccess() for (int i = 0; i < numPoints; ++i) { point = new RealPoint( numDimensions) for (int d = 0; d < numDimensions; ++d) { point.setPosition(rnd.nextDouble() * (interval.realMax(d) - interval.realMin(d)) + interval.realMin(d), d) } realRandomAccess.setPosition(point) // add a new element with a random intensity in the range 0...1 elements.add(point, realRandomAccess.get().copy()) } return elements } /** * Sample randomly n points from the input and display the interpolated result using nearest neighbors * * @param input - the input data * @param interval - the size of the input (where to collect random samples) * @param numPoints - how many points to sample * * @return - a RandomAccessibleInterval of the same size as the input, rendered from the sparse data */ public > RandomAccessibleInterval randomSampling(RealRandomAccessible input, Interval interval, int numPoints) { // create an IterableRealInterval realInterval = sampleRandomPoints(input, interval, numPoints) // using nearest neighbor search we will be able to return a value an any position in space search = new NearestNeighborSearchOnKDTree(new KDTree(realInterval)) // make it into RealRandomAccessible using nearest neighbor search realRandomAccessible = Views.interpolate(search, new NearestNeighborSearchInterpolatorFactory()) // convert it into a RandomAccessible which can be displayed randomAccessible = Views.raster(realRandomAccessible) // set the initial interval as area to view return Views.interval(randomAccessible, interval) } /** * Sample randomly n points from the input and display the interpolated result using * distance-weighted interpolation of 20 nearest neighbors * * @param input - the input data * @param interval - the size of the input (where to collect random samples) * @param numPoints - how many points to sample * * @return - a RandomAccessibleInterval of the same size as the input, rendered from the sparse data */ public > RandomAccessibleInterval randomSamplingKNearest(RealRandomAccessible input, Interval interval, int numPoints) { // create an IterableRealInterval realInterval = sampleRandomPoints(input, interval, numPoints) // using nearest neighbor search we will be able to return a value an any position in space search = new KNearestNeighborSearchOnKDTree(new KDTree (realInterval), Math.min(20, (int)realInterval.size())) // make it into RealRandomAccessible using nearest neighbor search realRandomAccessible= Views.interpolate(search, new InverseDistanceWeightingInterpolatorFactory()) // convert it into a RandomAccessible which can be displayed randomAccessible = Views.raster(realRandomAccessible) // set the initial interval as area to view return Views.interval(randomAccessible, interval) } } import net.imglib2.type.numeric.real.FloatType import io.scif.img.ImgOpener // open sample image with ImgOpener as FloatType img = new ImgOpener().openImgs("https://samples.fiji.sc/tutorials/DrosophilaWing.tif", new FloatType()).get(0) import net.imglib2.type.numeric.real.FloatType import net.imglib2.view.Views import net.imglib2.interpolation.randomaccess.NLinearInterpolatorFactory // use linear interpolation to convert the input into a RealRandomAccessible realRandomAccessible = Views.interpolate(Views.extendMirrorSingle(img), new NLinearInterpolatorFactory()) // You can change this variable to other number numPoints = 4096 randomNNSample = obj.randomSampling(realRandomAccessible, img, numPoints) randomKNNSample = obj.randomSamplingKNearest(realRandomAccessible, img, numPoints)