diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/AmplitudeBackgroundForeGroundClassification.java b/src/main/java/fr/pasteur/ida/zellige/utils/MaximumAmplitudeClassification.java similarity index 67% rename from src/main/java/fr/pasteur/ida/zellige/utils/AmplitudeBackgroundForeGroundClassification.java rename to src/main/java/fr/pasteur/ida/zellige/utils/MaximumAmplitudeClassification.java index f5662990e8e5dd85e39ea068e7f3cfc5ad2b99cc..c88407aec5e9d71aa9d9064943cc49fe2110e254 100644 --- a/src/main/java/fr/pasteur/ida/zellige/utils/AmplitudeBackgroundForeGroundClassification.java +++ b/src/main/java/fr/pasteur/ida/zellige/utils/MaximumAmplitudeClassification.java @@ -22,26 +22,37 @@ import net.imglib2.view.Views; import java.util.List; /** - * This class makes it possible to get a binary classification of the pixels (background/ foreground) according to their amplitude and their neighborhood. + * This class makes it possible to get a binary classification of the pixels (background/ foreground) according to their amplitude and their amplitude's neighborhood. * First, the amplitude of all local maximums is computed and stored as an {@link Img}. This {@link Img} is cut into squares (15x15) then depending on the number of pixels contained in * each square, the latter will be classified as background or foreground. */ -public class AmplitudeBackgroundForeGroundClassification +public class MaximumAmplitudeClassification { - public static < T extends RealType< T > & NativeType< T > > Img< FloatType > find( final Img< T > source, double amplitudeThreshold, double sizePercent ) + /** + * + * @param input - the input image as a {@link Img} + * @param amplitudeThreshold - the parameter user value to apply to the first mode of the image histogram. + * @param sizePercent the minimum percentage of pixels for isolated pixel elimination + * @param <T> - the type of the input + * @return a binary image of background foreground classification + */ + public static < T extends RealType< T > & NativeType< T > > Img< FloatType > find( final Img< T > input, double amplitudeThreshold, double sizePercent ) { // Prepare output. - - Img< BitType > amplitude = new ArrayImgFactory<>( new BitType() ).create( source ); - MaximumAmplitude< T > maximumAmplitude = new MaximumAmplitude<>( source, amplitude, amplitudeThreshold ); - final ImgFactory< FloatType > factory = Util.getArrayOrCellImgFactory( source, new FloatType() ); - Img< FloatType > output = factory.create( source ); - new computeBackgroundForegroundGrid( maximumAmplitude.getAmplitude(), output, sizePercent ); + Img< BitType > amplitude = new ArrayImgFactory<>( new BitType() ).create( input ); + MaximumAmplitude< T > maximumAmplitude = new MaximumAmplitude<>( input, amplitude, amplitudeThreshold ); + final ImgFactory< FloatType > factory = Util.getArrayOrCellImgFactory( input, new FloatType() ); + Img< FloatType > output = factory.create( input ); + new BackgroundForegroundGrid( maximumAmplitude.getAmplitude(), output, sizePercent ); ImageJFunctions.show( output, "new class amplitude" ); return output; } + /** + * This class generate a binary image according to a percentage of the smallest mode value of the input image + * @param <T> the type of the input {@link Img} + */ private static final class MaximumAmplitude< T extends RealType< T > & NativeType< T > > { private final Img< T > input; @@ -56,6 +67,13 @@ public class AmplitudeBackgroundForeGroundClassification run(); } + /** + * + * @param max the image containing only the values of local maximums + * @param min the image containing only the values of local minimums + * @param <T> the type of both images {@link Img} + * @return an image containing the value of the maximums amplitude + */ private static < T extends RealType< T > & NativeType< T > > Img< T > getAmplitude( Img< T > max, RandomAccessibleInterval< T > min ) { @@ -87,6 +105,13 @@ public class AmplitudeBackgroundForeGroundClassification return amp; } + /** + * + * @param maxValue the intensity value at local maximum positioned at minAccess location + * @param minAccess - the random access positioned at the same specific local maximum location + * @param <T> the type of the {@link RandomAccess} + * @return the chosen amplitude value of the local maximum positioned at minAccess location + */ private static < T extends RealType< T > & NativeType< T > > double getAmplitude( float maxValue, RandomAccess< T > minAccess ) { double up = findValueUp( minAccess, maxValue ); @@ -100,6 +125,13 @@ public class AmplitudeBackgroundForeGroundClassification return ( result ); } + /** + * + * @param minAccess the random access of the local minimum image + * @param maxValue the intensity value of the local maximum located at minAccess position + * @param <T> the type of the {@link RandomAccess} + * @return the amplitude value above the local maximum location in the Z dimension + */ private static < T extends RealType< T > & NativeType< T > > double findValueUp( RandomAccess< T > minAccess, float maxValue ) { @@ -116,6 +148,13 @@ public class AmplitudeBackgroundForeGroundClassification return maxValue; } + /** + * + * @param minAccess the random access of the local minimum image + * @param maxValue the intensity value of the local maximum located at minAccess position + * @param <T> the type of the {@link RandomAccess} + * @return the amplitude value below the local maximum location in the Z dimension + */ private static < T extends RealType< T > & NativeType< T > > double findValueDown( RandomAccess< T > minAccess, float maxValue ) { @@ -149,14 +188,23 @@ public class AmplitudeBackgroundForeGroundClassification } } - - private static final class computeBackgroundForegroundGrid + /** + * This class allows the elimination of isolated pixels. the image is containing the amplitude values of each local maximums is split into {15 x 15 x 1} sections, + * and the sections containing less than the size percent value are set to zero. + */ + private static final class BackgroundForegroundGrid { private final Img< BitType > source; private final Img< FloatType > output; private final double sizePercent; - private computeBackgroundForegroundGrid( final Img< BitType > source, Img< FloatType > output, double sizePercent ) + /** + * + * @param source - the input as a 2D {@link Img<BitType> } + * @param output - the output as a 2D {@link Img<FloatType> } + * @param sizePercent - the minimum percentage of positive pixels + */ + private BackgroundForegroundGrid( final Img< BitType > source, Img< FloatType > output, double sizePercent ) { this.source = source; this.output = output; @@ -164,6 +212,13 @@ public class AmplitudeBackgroundForeGroundClassification run(); } + /** + * + * @param intervalView a sub 2D image + * @param sizePercent the minimum percentage of pixels for isolated pixel elimination + * @param <T> the type of the sub image + * @return true if the sub image does contain enough foreground pixels false otherwise + */ public static < T extends RealType< T > & NativeType< T > > boolean isForeground( IntervalView< T > intervalView, double sizePercent ) { double sum = 0; @@ -179,6 +234,9 @@ public class AmplitudeBackgroundForeGroundClassification return ( sum ) > ( intervalView.dimension( 0 ) * intervalView.dimension( 1 ) * sizePercent ); } + /** + * + */ public void run() { long X = source.dimension( 0 ); @@ -195,9 +253,13 @@ public class AmplitudeBackgroundForeGroundClassification viewOutput.forEach( pixel -> pixel.setReal( foreground ) ); } // Slight dilatation in z dimension - Utils.gaussConvolution( output.copy(), output, new double[]{ 0, 0, 1 } ); + Utils.gaussConvolution( output.copy(), output, new double[]{ 0, 0, 0.5 } ); } + /** + * + * @return the smoothed amplitude classified image + */ public Img< FloatType > getOutput() { return output;