diff --git a/src/main/java/fr/pasteur/ida/zellige/utils/AmplitudeBackgroundForeGroundClassification.java b/src/main/java/fr/pasteur/ida/zellige/utils/AmplitudeBackgroundForeGroundClassification.java
new file mode 100644
index 0000000000000000000000000000000000000000..42d92821a709e67c0dfca51b845507f3eea3d8e9
--- /dev/null
+++ b/src/main/java/fr/pasteur/ida/zellige/utils/AmplitudeBackgroundForeGroundClassification.java
@@ -0,0 +1,205 @@
+package fr.pasteur.ida.zellige.utils;
+
+import fr.pasteur.ida.zellige.surfaceConstruction.construction.SurfacesExtraction;
+import net.imglib2.Cursor;
+import net.imglib2.Interval;
+import net.imglib2.RandomAccess;
+import net.imglib2.RandomAccessibleInterval;
+import net.imglib2.algorithm.binary.Thresholder;
+import net.imglib2.algorithm.util.Grids;
+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.logic.BitType;
+import net.imglib2.type.numeric.RealType;
+import net.imglib2.type.numeric.real.FloatType;
+import net.imglib2.util.Util;
+import net.imglib2.view.IntervalView;
+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.
+ * 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 static < T extends RealType< T > & NativeType< T > > Img< FloatType > find( final Img< T > source, 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 );
+        ImageJFunctions.show( output, "new class amplitude" );
+        return output;
+    }
+
+    private static final class MaximumAmplitude< T extends RealType< T > & NativeType< T > >
+    {
+        private final Img< T > input;
+        private final double amplitudeThreshold;
+        private Img< BitType > amplitude;
+
+        public MaximumAmplitude( Img< T > input, Img< BitType > amplitude, double amplitudeThreshold )
+        {
+            this.input = input;
+            this.amplitude = amplitude;
+            this.amplitudeThreshold = amplitudeThreshold;
+            run();
+        }
+
+        private static < T extends RealType< T > & NativeType< T > > Img< T > getAmplitude(
+                Img< T > max, RandomAccessibleInterval< T > min )
+        {
+            Img< T > amp = max.factory().create( max );
+            RandomAccess< T > maxAccess = max.randomAccess();
+            RandomAccess< T > minAccess = min.randomAccess();
+            RandomAccess< T > ampAccess = amp.randomAccess();
+            for ( int x = 0; x <= SurfacesExtraction.getX() - 1; x++ )
+            {
+                maxAccess.setPosition( x, 0 );
+                for ( int y = 0; y <= SurfacesExtraction.getY() - 1; y++ )
+                {
+                    maxAccess.setPosition( y, 1 );
+                    for ( int z = 0; z <= SurfacesExtraction.getZ() - 1; z++ )
+
+                    {
+                        maxAccess.setPosition( z, 2 );
+                        float maxValue = maxAccess.get().getRealFloat();
+                        if ( maxValue != 0 )
+                        {
+                            minAccess.setPosition( maxAccess );
+                            double amplitude = getAmplitude( maxValue, minAccess );
+                            ampAccess.setPosition( maxAccess );
+                            ampAccess.get().setReal( amplitude );
+                        }
+                    }
+                }
+            }
+            return amp;
+        }
+
+        private static < T extends RealType< T > & NativeType< T > > double getAmplitude( float maxValue, RandomAccess< T > minAccess )
+        {
+            double up = findValueUp( minAccess, maxValue );
+            double down = findValueDown( minAccess, maxValue );
+            double result = Math.max( Math.abs( maxValue - up ), Math.abs( maxValue - down ) );
+            if ( result == 0 )
+            {
+                return maxValue;
+
+            }
+            return ( result );
+        }
+
+        private static < T extends RealType< T > & NativeType< T > > double findValueUp(
+                RandomAccess< T > minAccess, float maxValue )
+        {
+            int start = minAccess.getIntPosition( 2 );
+            for ( int z = start - 1; z >= 0; z-- )
+            {
+                minAccess.setPosition( z, 2 );
+                double value = minAccess.get().getRealDouble();
+                if ( value != 0 )
+                {
+                    return value;
+                }
+            }
+            return maxValue;
+        }
+
+        private static < T extends RealType< T > & NativeType< T > > double findValueDown(
+                RandomAccess< T > minAccess, float maxValue )
+        {
+            int start = minAccess.getIntPosition( 2 );
+            for ( int z = start + 1; z <= SurfacesExtraction.getZ() - 1; z++ )
+            {
+                minAccess.setPosition( z, 2 );
+                double value = minAccess.get().getRealDouble();
+                if ( value != 0 )
+                {
+                    return value;
+                }
+            }
+            return maxValue;
+        }
+
+        public void run()
+        {
+            Img< T > maximums = LocalMaximumDetection.findMaximums( input, input.factory() );
+            Img< T > minimums = LocalMinimumDetection.findMinimums( input, input.factory() );
+            Img< T > amp = getAmplitude( maximums, minimums );
+            T TMax = Threshold.getFirstMaxValue( maximums, false );
+            TMax.mul( amplitudeThreshold );
+            this.amplitude = Thresholder.threshold( amp.copy(), TMax, true, 2 );
+
+        }
+
+        public Img< BitType > getAmplitude()
+        {
+            return amplitude;
+        }
+    }
+
+
+    private static final class computeBackgroundForegroundGrid
+    {
+        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 )
+        {
+            this.source = source;
+            this.output = output;
+            this.sizePercent = sizePercent;
+            run();
+        }
+
+        public void run()
+        {
+            long X = source.dimension( 0 );
+            long Y = source.dimension( 1 );
+            long Z = source.dimension( 2 );
+            List< Interval > intervals = Grids.collectAllContainedIntervals( new long[]{ X, Y, Z },
+                    new int[]{ 15, 15, 1 } );
+
+            for ( Interval interval : intervals )
+            {
+                IntervalView< BitType > viewSource = Views.offsetInterval( source, interval );
+                IntervalView< FloatType > viewOutput = Views.offsetInterval( output, interval );
+                int foreground = isForeground( viewSource, sizePercent ) ? 1 : 0;
+                viewOutput.forEach( pixel -> pixel.setReal( foreground ) );
+            }
+        }
+        public static < T extends RealType< T > & NativeType< T > > boolean isForeground( IntervalView< T > intervalView, double sizePercent )
+        {
+            double sum = 0;
+            Cursor< T > cursor = intervalView.cursor();
+            while ( cursor.hasNext() )
+            {
+                cursor.fwd();
+                if ( cursor.get().getRealDouble() != 0 )
+                {
+                    sum++;
+                }
+            }
+            return ( sum ) > ( intervalView.dimension( 0 ) * intervalView.dimension( 1 ) * sizePercent );
+        }
+
+
+        public Img< FloatType > getOutput()
+        {
+            return output;
+        }
+    }
+
+}