Skip to content
Snippets Groups Projects
Commit 3bbb8669 authored by Céline  TREBEAU's avatar Céline TREBEAU
Browse files

Perf

- addition of possible Exceptions in the process.
- Removal of unnecessary convert method.
- Optimization of GC process
parent 31ff6aa8
Branches
No related tags found
1 merge request!41Resolve "Consider rescaling (binning) large images"
......@@ -6,13 +6,13 @@
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
......@@ -28,69 +28,79 @@
*/
package fr.pasteur.ida.zellige.steps.selection.pretreatment;
import fr.pasteur.ida.zellige.steps.Utils;
import fr.pasteur.ida.zellige.steps.selection.exception.BinningFailedException;
import fr.pasteur.ida.zellige.steps.selection.util.Binning;
import fr.pasteur.ida.zellige.steps.selection.util.Unbinning;
import io.scif.img.ImgOpener;
import net.imglib2.RandomAccessible;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.algorithm.convolution.fast_gauss.FastGauss;
import net.imglib2.algorithm.fft2.FFTConvolution;
import net.imglib2.algorithm.gauss3.Gauss3;
import net.imagej.ImageJ;
import net.imglib2.*;
import net.imglib2.algorithm.stats.Normalize;
import net.imglib2.converter.Converters;
import net.imglib2.converter.RealTypeConverters;
import net.imglib2.converter.readwrite.RealFloatSamplerConverter;
import net.imglib2.img.Img;
import net.imglib2.img.ImgFactory;
import net.imglib2.img.array.ArrayImgFactory;
import net.imglib2.img.display.imagej.ImageJFunctions;
import net.imglib2.type.NativeType;
import net.imglib2.type.Type;
import net.imglib2.type.numeric.RealType;
import net.imglib2.type.numeric.complex.ComplexFloatType;
import net.imglib2.type.numeric.integer.UnsignedByteType;
import net.imglib2.type.numeric.real.FloatType;
import net.imglib2.util.ImgUtil;
import net.imglib2.util.RealSum;
import net.imglib2.view.IntervalView;
import net.imglib2.view.Views;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static fr.pasteur.ida.zellige.steps.Utils.setPosition;
import static fr.pasteur.ida.zellige.steps.Utils.setPositionAndGet;
import static fr.pasteur.ida.zellige.steps.selection.pretreatment.PretreatmentParameters.getBin;
public class Pretreatment< T extends RealType< T > & NativeType< T > >
{
private final static Logger LOGGER = LoggerFactory.getLogger( Pretreatment.class );
private final RandomAccessibleInterval< T > input;
// private final PretreatmentParameters pretreatmentParameters;
private final double radius;
private Img< FloatType > output;
Pretreatment( RandomAccessibleInterval< T > input, double radius )
public static < T extends RealType< T > & NativeType< T > > Img< FloatType >
run( Img< T > input, double radius )
{
this.input = input;
this.radius = radius;
}
Pretreatment< T > pretreatment = new Pretreatment<>();
return pretreatment.runSteps( input, radius );
}
public static < T extends RealType< T > & NativeType< T > > Img< FloatType >
run( RandomAccessibleInterval< T > input, double radius )
run( Img< T > input )
{
LOGGER.debug( "Starting process..." );
Pretreatment< T > pretreatment = new Pretreatment<>( input, radius );
pretreatment.run();
LOGGER.debug( "Process complete." );
return pretreatment.getOutput();
return run( input, 2 );
}
public static < T extends RealType< T > & NativeType< T > > Img< FloatType >
run( RandomAccessibleInterval< T > input )
private Img< FloatType > runSteps( Img< T > input, double radius )
{
LOGGER.debug( "Starting process..." );
Pretreatment< T > pretreatment = new Pretreatment<>( input, 2 );
pretreatment.run();
LOGGER.debug( "Process complete." );
return pretreatment.getOutput();
try
{
Img< T > temp = Binning.binning( input, getBin() ); // Binning op
if (temp == null)
{
throw new BinningFailedException();
}
Img< FloatType > output = gaussianBlurFilterDenoising( temp, temp.factory(), radius ); // Filtering op
// The denoised image is normalized between 0 and 255
output = normalizeImage( output, output.factory() ); // normalizing op
return output;
}
catch ( OutOfMemoryError oom )
{
LOGGER.error( "Out of memory", oom );
LOGGER.info( "The Input image is too large. Try Incrementing the Bin value or allow more memory to your Fiji" );
return null;
}
catch ( BinningFailedException bfe )
{
LOGGER.info("The binning process has failed. Please send a issue on gitlab");
return null;
}
}
/**
* Normalizes the pixel values of an Img between 0 and 255.
*
......@@ -100,7 +110,7 @@ public class Pretreatment< T extends RealType< T > & NativeType< T > >
* @return a new Img with normalize pixel intensity values.
*/
private static < T extends RealType< T > & NativeType< T > > Img< T > normalizeImage(
RandomAccessibleInterval< T > image, ImgFactory< T > factory )
RandomAccessibleInterval< T > image, ImgFactory< T > factory )
{
LOGGER.debug( "Staring normalization." );
Img< T > normalizedImage = factory.create( image.dimensionsAsLongArray() );
......@@ -110,75 +120,57 @@ public class Pretreatment< T extends RealType< T > & NativeType< T > >
T max = normalizedImage.firstElement().copy().createVariable();
max.setReal( 255 );
Normalize.normalize( normalizedImage, min, max );
LOGGER.debug( "End of normalization." );
LOGGER.debug( "Input normalized." );
return normalizedImage;
}
/**
* Applies the denoising step on the specified input according to the specified method
*
* @param input the noisy image as a {@link RandomAccessibleInterval}
* @return a denoised image as a {@link Img}
*/
Img< FloatType > denoisingStep( RandomAccessibleInterval< FloatType > input )
{
LOGGER.debug( "Starting denoising step..." );
RandomAccessibleInterval< FloatType > converted = Converters.convert( input, new RealFloatSamplerConverter<>() );
LOGGER.debug( "Denoising step complete, with gaussian filter" );
return gaussianBlurFilterDenoising( converted );
}
/**
* @param input - the source image as a {@link RandomAccessibleInterval}
* @param factory - the source and output factory
* @param sigma - an array containing the standard deviations for each dimension.
* @param <T> - source and output type
* @return - the filtered image as a {@link RandomAccessibleInterval}
*/
public static < T extends RealType< T > & NativeType< T > > Img< T >
gaussianConvolution( RandomAccessibleInterval< T > input, ImgFactory< T > factory, double[] sigma )
{
Img< T > output = factory.create( input );
RandomAccessible< T > infiniteInput = Views.extendValue( input, input.randomAccess().get().getRealFloat() );
Gauss3.gauss( sigma, infiniteInput, output );
return output;
}
void run()
{
// The input is converted into FloatType
RandomAccessibleInterval< FloatType > converted = Converters.convert( input, new RealFloatSamplerConverter<>() );
LOGGER.debug( "Input converted." );
//The choose method of denoising is applied
Img< FloatType > denoised = denoisingStep( converted );
// The denoised image is normalized between 0 and 255
this.output = normalizeImage( denoised, denoised.factory() );
LOGGER.debug( "Input normalized." );
}
/**
* Applies a gaussian filter to a noisy image
*
* @param input the noisy image as a {@link RandomAccessibleInterval}
* @param input the noisy image as a {@link RandomAccessibleInterval}
* @param factory the input factory
* @return a denoised image as a {@link Img}
*/
Img< FloatType > gaussianBlurFilterDenoising( RandomAccessibleInterval< FloatType > input )
{
ImgFactory< FloatType > factory = new ArrayImgFactory<>( new FloatType() );
return gaussianConvolution( input, factory, new double[]{ radius, radius, 1 } );
}
public RandomAccessibleInterval< T > getInput()
private static < T extends RealType< T > & NativeType< T > > Img< FloatType > gaussianBlurFilterDenoising( RandomAccessibleInterval< T > input, ImgFactory< T > factory, double radius )
{
return input;
ImgFactory< FloatType > newImgFactory = factory.imgFactory( new FloatType() );
Img< FloatType > output = newImgFactory.create( input.dimensionsAsLongArray() );
Utils.gaussianConvolution_( input, output, new double[]{ radius, radius, 1 } );
return output;
}
public Img< FloatType > getOutput()
public static void main( String[] args )
{
return output;
ImageJ ij = new ImageJ();
ij.launch( args );
final ImgOpener io = new ImgOpener();
@SuppressWarnings( "unchecked" ) final Img< UnsignedByteType > kernel = ( Img< UnsignedByteType > ) io.openImgs( "doc/Scan1_volume_crop.tif" ).get( 0 );
ImageJFunctions.show( kernel, "original" );
double time1 = System.currentTimeMillis();
int bin = 1;
Img< UnsignedByteType > output = Binning.binning( kernel, bin );
double time2 = System.currentTimeMillis();
LOGGER.debug( "Multithreading time = {}s", ( time2 - time1 ) / 1000 );
assert output != null;
ImageJFunctions.show( output, "output " );
Img< UnsignedByteType > i = kernel.factory().create( output.dimension( 0 ), output.dimension( 1 ) );
RandomAccess< UnsignedByteType > access = i.randomAccess();
RandomAccess< UnsignedByteType > cursor = output.randomAccess();
for ( int y = 0; y < i.dimension( 1 ); y++ )
{
for ( int x = 0; x < i.dimension( 0 ); x++ )
{
setPosition( access, x, y );
access.get().setReal( setPositionAndGet( cursor, x, y ).getRealDouble() );
}
}
Img< UnsignedByteType > output_unbinned = Unbinning.run( i, i.factory(), bin );
ImageJFunctions.show( output_unbinned, "unbinned 1" );
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment