Histogram for discrete random values.

The class wraps histogram for discrete stochastic function, which is represented by integer array, where indexes of the array are treated as values of the stochastic function, but array values are treated as "probabilities" (total amount of hits).

Sample usage:

// create histogram Histogram histogram = new Histogram( new int[10] { 0, 0, 1, 3, 6, 8, 11, 0, 0, 0 } ); // get mean and standard deviation values Console.WriteLine( "mean = " + histogram.Mean + ", std.dev = " + histogram.StdDev );
Beispiel #1
0
        public void SetHistogram( Histogram histogram )
        {
            this.histogram = histogram;

            histogramControl.Values = histogram.Values;
            int length = histogram.Values.Length;

            Text = string.Format( "Histogram - {0} values", length );
            statsBox.Text = string.Format( "Min: {0}   Max: {1}   Mean: {2:F2}   Std.Dev.: {3:F2}",
                histogram.Min, histogram.Max, histogram.Mean, histogram.StdDev );

            // set form size
            int formWidth  = System.Math.Min( 800, length ) + 40;
            int formHeight = HistogramHeight + 120;

            this.Size = new Size( formWidth, formHeight );

            // set histogram control size
            int width = length + 2;
            int height = HistogramHeight + 2;

            int x = ( width > mainPanel.ClientSize.Width ) ? 0 : ( mainPanel.ClientSize.Width - width ) / 2;
            int y = ( height > mainPanel.ClientSize.Height ) ? 0 : ( mainPanel.ClientSize.Height - height ) / 2;

            histogramControl.SuspendLayout( );
            histogramControl.Size = new Size( width, height );
            histogramControl.Location = new System.Drawing.Point( x, y );
            histogramControl.ResumeLayout( );
        }
        public static unsafe void DrawHistogram(Bitmap edgeDetectedBitmap, Histogram histogram)
        {
            var pallete = edgeDetectedBitmap.Palette;
             var palleteEntries = pallete.Entries;
             palleteEntries[250] = Color.Magenta;
             palleteEntries[251] = Color.Yellow;
             palleteEntries[252] = Color.Cyan;
             palleteEntries[253] = Color.Lime;
             palleteEntries[254] = Color.Red;
             palleteEntries[255] = Color.White;
             edgeDetectedBitmap.Palette = pallete;

             var histogramHeight = Math.Min(100, edgeDetectedBitmap.Height);
             var rect = new Rectangle(Point.Empty, edgeDetectedBitmap.Size);
             var bitmapData = edgeDetectedBitmap.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);
             var histogramMax = histogram.Values.Max();
             for (var x = 0; x < edgeDetectedBitmap.Width; x++) {
            var barHeight = histogram.Values[x] * histogramHeight / histogramMax;
            Console.WriteLine(barHeight);
            var pCurrentPixel = (byte*)bitmapData.Scan0.ToPointer() + x;
            for (var y = 0; y < barHeight; y++) {
               *pCurrentPixel = 255;
               pCurrentPixel += bitmapData.Stride;
            }
             }
             edgeDetectedBitmap.UnlockBits(bitmapData);
        }
        // Switch channel
        public void SwitchChannel(int channel)
        {
            if ((channel >= 0) && (channel <= 2))
            {
                if (!stat.IsGrayscale)
                {
                    histogram.Color = colors[channel];
                    activeHistogram = (channel == 0) ? stat.Red : (channel == 1) ? stat.Green : stat.Blue;
                }
            }
            else if (channel == 3)
            {
                if (stat.IsGrayscale)
                {
                    histogram.Color = colors[3];
                    activeHistogram = stat.Gray;
                }
            }

            if (activeHistogram != null)
            {
                histogram.Values = activeHistogram.Values;

                meanLabel.Text   = activeHistogram.Mean.ToString("F2");
                stdDevLabel.Text = activeHistogram.StdDev.ToString("F2");
                medianLabel.Text = activeHistogram.Median.ToString();
                minLabel.Text    = activeHistogram.Min.ToString();
                maxLabel.Text    = activeHistogram.Max.ToString();
            }
        }
Beispiel #4
0
 // return pixele index with maximum point
 private int getMaxValue(Histogram hist)
 {
     int max = -1; //init
     int index = 0;//init
     for (int i = 0; i < 255; i++)
         if (hist.Values[i] > max)
         {
             max = hist.Values[i];
             index = i;
         }
     return index;
 }
Beispiel #5
0
        // Set image statistics to display
        public void SetImageStatistics( ImageStatistics stats )
        {
            this.stats = stats;

            if ( stats.IsGrayscale )
            {
                activeHistogram = stats.Gray;
                histogram.Color = Color.Black;
                channelCombo.Enabled = false;

                ShowInfoForActiveHistogram( );
            }
            else
            {
                channelCombo.Enabled = true;
                channelCombo.SelectedIndex = 0;
                SelectChannel( 0 );
            }
        }
Beispiel #6
0
        // Show histogram for the specified RGB channel
        private void SelectChannel( int c )
        {
            switch ( c )
            {
                case 0:
                    activeHistogram = stats.Red;
                    histogram.Color = Color.Red;
                    break;
                case 1:
                    activeHistogram = stats.Green;
                    histogram.Color = Color.Green;
                    break;
                case 2:
                    activeHistogram = stats.Blue;
                    histogram.Color = Color.Blue;
                    break;
            }

            ShowInfoForActiveHistogram( );
        }
Beispiel #7
0
        public ImageInfo(string path)
        {
            _disposed = false;

            // image info
            _hist = null;
            _imf = null;
            _imb = null;
            _height = _width = 0;

            this._path = path;
            try
            {
                System.Drawing.Image image = System.Drawing.Image.FromFile(this._path);

                oirgIm2grayCropped(image); // creates _imGray
                image.Dispose();

                _width = _imGray.Width;
                _height= _imGray.Height;
            }
            catch (Exception e) { throw e; }
        }
Beispiel #8
0
 /// <summary>
 /// return a full depp copy
 /// </summary>
 /// <param name="from">Source</param>
 /// <returns>Copyed reference</returns>
 private Histogram copyHist(Histogram from)
 {
     int[] values = new int[from.Values.Length];
     from.Values.CopyTo(values, 0);
     Histogram to = new Histogram(values);
     to.Update();
     return to;
 }
        /// <summary>
        /// Gather statistics about specified image.
        /// </summary>
        /// 
        /// <param name="image">Unmanaged image to process.</param>
        /// 
        private void ProcessImage( UnmanagedImage image )
        {
            CheckSourceFormat( image.PixelFormat );

            // get image dimension
            int width  = image.Width;
            int height = image.Height;

            pixels = pixelsWithoutBlack = 0;

            // check pixel format
            if ( grayscale = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) )
            {
                // alloc arrays
                int[] g   = new int[256];
                int[] gwb = new int[256];

                byte value;
                int  offset = image.Stride - width;

                // do the job
                unsafe
                {
                    byte * p = (byte*) image.ImageData.ToPointer( );

                    // for each pixel
                    for ( int y = 0; y < height; y++ )
                    {
                        // for each pixel
                        for ( int x = 0; x < width; x++, p++ )
                        {
                            // get pixel value
                            value = *p;

                            g[value]++;
                            pixels++;

                            if ( value != 0 )
                            {
                                gwb[value]++;
                                pixelsWithoutBlack++;
                            }
                        }
                        p += offset;
                    }
                }

                // create historgram for gray level
                gray = new Histogram( g );
                grayWithoutBlack = new Histogram( gwb );
            }
            else
            {
                // alloc arrays
                int[]	r = new int[256];
                int[]	g = new int[256];
                int[]	b = new int[256];

                int[]	rwb = new int[256];
                int[]	gwb = new int[256];
                int[]	bwb = new int[256];

                byte rValue, gValue, bValue;
                int  pixelSize = ( image.PixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4;
                int  offset = image.Stride - width * pixelSize;

                // do the job
                unsafe
                {
                    byte * p = (byte*) image.ImageData.ToPointer( );

                    // for each line
                    for ( int y = 0; y < height; y++ )
                    {
                        // for each pixel
                        for ( int x = 0; x < width; x++, p += pixelSize )
                        {
                            // get pixel values
                            rValue = p[RGB.R];
                            gValue = p[RGB.G];
                            bValue = p[RGB.B];

                            r[rValue]++;
                            g[gValue]++;
                            b[bValue]++;
                            pixels++;

                            if ( ( rValue != 0 ) || ( gValue != 0 ) || ( bValue != 0 ) )
                            {
                                rwb[rValue]++;
                                gwb[gValue]++;
                                bwb[bValue]++;
                                pixelsWithoutBlack++;
                            }
                        }
                        p += offset;
                    }
                }

                // create histograms
                red   = new Histogram( r );
                green = new Histogram( g );
                blue  = new Histogram( b );

                redWithoutBlack   = new Histogram( rwb );
                greenWithoutBlack = new Histogram( gwb );
                blueWithoutBlack  = new Histogram( bwb );
            }
        }
        /// <summary>
        /// Gather horizontal intensity statistics for specified image.
        /// </summary>
        /// 
        /// <param name="image">Source image.</param>
        /// 
        private void ProcessImage( UnmanagedImage image )
        {
            PixelFormat pixelFormat = image.PixelFormat;
            // get image dimension
            int width  = image.Width;
            int height = image.Height;

            // do the job
            unsafe
            {
                // check pixel format
                if ( pixelFormat == PixelFormat.Format8bppIndexed )
                {
                    // 8 bpp grayscale image
                    byte* p = (byte*) image.ImageData.ToPointer( );
                    int offset = image.Stride - width;

                    // histogram array
                    int[] g = new int[width];

                    // for each pixel
                    for ( int y = 0; y < height; y++ )
                    {
                        // for each pixel
                        for ( int x = 0; x < width; x++, p++ )
                        {
                            g[x] += *p;
                        }
                        p += offset;
                    }

                    // create historgram for gray level
                    gray = new Histogram( g );
                }
                else if ( pixelFormat == PixelFormat.Format16bppGrayScale )
                {
                    // 16 bpp grayscale image
                    int basePtr = (int) image.ImageData.ToPointer( );
                    int stride = image.Stride;

                    // histogram array
                    int[] g = new int[width];

                    // for each pixel
                    for ( int y = 0; y < height; y++ )
                    {
                        ushort* p = (ushort*) ( basePtr + stride * y );

                        // for each pixel
                        for ( int x = 0; x < width; x++, p++ )
                        {
                            g[x] += *p;
                        }
                    }

                    // create historgram for gray level
                    gray = new Histogram( g );
                }
                else if (
                    ( pixelFormat == PixelFormat.Format24bppRgb ) ||
                    ( pixelFormat == PixelFormat.Format32bppRgb ) ||
                    ( pixelFormat == PixelFormat.Format32bppArgb ) )
                {
                    // 24/32 bpp color image
                    byte* p = (byte*) image.ImageData.ToPointer( );
                    int pixelSize = ( pixelFormat == PixelFormat.Format24bppRgb ) ? 3 : 4;
                    int offset = image.Stride - width * pixelSize;

                    // histogram arrays
                    int[] r = new int[width];
                    int[] g = new int[width];
                    int[] b = new int[width];

                    // for each line
                    for ( int y = 0; y < height; y++ )
                    {
                        // for each pixel
                        for ( int x = 0; x < width; x++, p += pixelSize )
                        {
                            r[x] += p[RGB.R];
                            g[x] += p[RGB.G];
                            b[x] += p[RGB.B];
                        }
                        p += offset;
                    }

                    // create histograms
                    red   = new Histogram( r );
                    green = new Histogram( g );
                    blue  = new Histogram( b );
                }
                else if (
                    ( pixelFormat == PixelFormat.Format48bppRgb ) ||
                    ( pixelFormat == PixelFormat.Format64bppArgb ) )
                {
                    // 48/64 bpp color image
                    int basePtr = (int) image.ImageData.ToPointer( );
                    int stride = image.Stride;
                    int pixelSize = ( pixelFormat == PixelFormat.Format48bppRgb ) ? 3 : 4;

                    // histogram arrays
                    int[] r = new int[width];
                    int[] g = new int[width];
                    int[] b = new int[width];

                    // for each line
                    for ( int y = 0; y < height; y++ )
                    {
                        ushort* p = (ushort*) ( basePtr + stride * y );

                        // for each pixel
                        for ( int x = 0; x < width; x++, p += pixelSize )
                        {
                            r[x] += p[RGB.R];
                            g[x] += p[RGB.G];
                            b[x] += p[RGB.B];
                        }
                    }

                    // create histograms
                    red   = new Histogram( r );
                    green = new Histogram( g );
                    blue  = new Histogram( b );
                }
            }
        }
Beispiel #11
0
        // Selection changed in channels combo
        private void channelCombo_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            AForge.Math.Histogram h = null;
            Color    color          = Color.White;
            IntRange input          = new IntRange(0, 255);
            IntRange output         = new IntRange(0, 255);
            int      index          = channelCombo.SelectedIndex;

            if (!imgStat.IsGrayscale)
            {
                // RGB image
                histogram.Color = colors[index];

                switch (index)
                {
                case 0:         // red
                    h      = imgStat.Red;
                    input  = inRed;
                    output = outRed;
                    color  = Color.FromArgb(255, 0, 0);
                    break;

                case 1:         // green
                    h      = imgStat.Green;
                    input  = inGreen;
                    output = outGreen;
                    color  = Color.FromArgb(0, 255, 0);
                    break;

                case 2:         // blue
                    h      = imgStat.Blue;
                    input  = inBlue;
                    output = outBlue;
                    color  = Color.FromArgb(0, 0, 255);
                    break;
                }
            }
            else
            {
                // grayscale image
                histogram.Color = colors[3];
                h = imgStat.Gray;

                input  = inGreen;
                output = outGreen;
            }
            histogram.Values = h.Values;

            inMinBox.Text  = input.Min.ToString( );
            inMaxBox.Text  = input.Max.ToString( );
            outMinBox.Text = output.Min.ToString( );
            outMaxBox.Text = output.Max.ToString( );

            // input slider
            inSlider.Color2 = color;
            inSlider.Min    = input.Min;
            inSlider.Max    = input.Max;
            // output slider
            outSlider.Color2 = color;
            outSlider.Min    = output.Min;
            outSlider.Max    = output.Max;
        }
        // Switch channel
        public void SwitchChannel( int channel )
        {
            if ( ( channel >= 0 ) && ( channel <= 2 ) )
            {
                if ( !stat.IsGrayscale )
                {
                    histogram.Color = colors[channel];
                    activeHistogram = ( channel == 0 ) ? stat.Red : ( channel == 1 ) ? stat.Green : stat.Blue;
                }
            }
            else if ( channel == 3 )
            {
                if ( stat.IsGrayscale )
                {
                    histogram.Color = colors[3];
                    activeHistogram = stat.Gray;
                }
            }

            if ( activeHistogram != null )
            {
                histogram.Values = activeHistogram.Values;

                meanLabel.Text = activeHistogram.Mean.ToString( "F2" );
                stdDevLabel.Text = activeHistogram.StdDev.ToString( "F2" );
                medianLabel.Text = activeHistogram.Median.ToString( );
                minLabel.Text = activeHistogram.Min.ToString( );
                maxLabel.Text = activeHistogram.Max.ToString( );
            }
        }
        /// <summary>
        /// Remove peaks from the histogram, which don't contain maximum value.
        /// </summary>
        /// 
        /// <param name="histogram">Histogram to process.</param>
        /// 
        private void FilterNoisyPeaks( Histogram histogram )
        {
            int[] values = histogram.Values;
            int   globalMax = 0;

            // find global maximum value
            for ( int k = 0; k < values.Length; k++ )
            {
                if ( values[k] > globalMax )
                {
                    globalMax = values[k];
                }
            }

            int i = 0;

            // process all peaks
            while ( i < values.Length )
            {
                // find start of next peak
                while ( ( i < values.Length ) && ( values[i] == 0 ) )
                {
                    i++;
                }

                int localMax = 0;

                // find peak's maximum value
                while ( ( i < values.Length ) && ( values[i] != 0 ) )
                {
                    if ( values[i] > localMax )
                    {
                        localMax = values[i];
                    }
                    i++;
                }

                // remove this peak if it does not contain global maximum
                if ( localMax < globalMax )
                {
                    int j = i - 1;

                    while ( ( j >= 0 ) && ( values[j] != 0 ) )
                    {
                        values[j] = 0;
                        j--;
                    }
                }
            }

            histogram.Update( );
        }
Beispiel #14
0
        /// <summary>
        /// Copyies _imGray with newSize, updates size and and null's the rest of the valeus
        /// </summary>
        /// <param name="origIm"></param>
        /// <param name="newSize"></param>
        public ImageInfo(ImageInfo origIm, Size newSize)
        {
            _disposed = false;

            _imGray = new Bitmap(origIm.getIm(), newSize);
            _hist = null;
            _imf = null;
            _imb = null;
            _path = null;
            _width = newSize.Width;
            _height = newSize.Height;
        }
Beispiel #15
0
        /// <summary>
        /// Gets the content.
        /// </summary>
        /// <param name="mincross">Минимальная разница яркости ячейки с кретсиком</param>
        /// <param name="maxcross">Максимальная разница яркости ячейки с кретсиком</param>
        public void GetContent(double mincross, double maxcross)
        {
            _content = false;
            _neurocontent = CellContent.Free;

            List<double> _lrange = new List<double>();
            BitmapData data = _parentimage.LockBits(_rect, ImageLockMode.ReadWrite, _parentimage.PixelFormat);
            VerticalIntensityStatistics vis = new VerticalIntensityStatistics(data);
            histogram = vis.Gray;

            HorizontalIntensityStatistics his = new HorizontalIntensityStatistics(data);
            Histogram hhistogram = his.Gray;
            List<double> _hrange = new List<double>();

            _parentimage.UnlockBits(data);

            for (int i = 8; i <= 15; i++)
            {
                _lrange.Add((histogram.Values[i]+hhistogram.Values[i])/2);
               // _hrange.Add(hhistogram.Values[i]);
            }
              // _britnessdispertion = (1 - RecogCore.Statistics.Mean(_lrange) / histogram.Values.Max()) + (1 - RecogCore.Statistics.Mean(_hrange) / hhistogram.Values.Max());
            _britnessdispertion = 1 - RecogCore.Statistics.Mean(_lrange) / histogram.Values.Max();
            if (_britnessdispertion <= mincross) { _neurocontent = CellContent.Free; _content = false; }
            if (_britnessdispertion > mincross & _britnessdispertion <= maxcross) { _neurocontent = CellContent.Cross; _content = true; }
            if (_britnessdispertion > maxcross) { _neurocontent = CellContent.Miss; _content = false; }
        }
Beispiel #16
0
        /// <summary>
        /// this construr gets the _imGray of an ImageInfo in order to get another object
        /// of that image without any more data, can be used when running filters on images
        /// </summary>
        /// <param name="imGray"></param>
        private ImageInfo(Bitmap imGray)
        {
            _disposed = false;

            _path = null;
            _hist = null;
            _imf = null;
            _imGray = (Bitmap)imGray.Clone();
            _width = _imGray.Width;
            _height = _imGray.Height;
        }
Beispiel #17
0
        //mathod return true if image is bad contrast
        private bool isBadContrast(Histogram hist)
        {
            int range; //num of pixels in range
            int max = getMaxValue(hist); // index of maximum point

            if (max < 20) // check range [0,20]
                range = pixelRange(hist, 0, 20);
            else if (max > 235) // check range [235,255]
                range = pixelRange(hist, 235, 255);
            else // check range [max-20,max+20]
                range = pixelRange(hist, max - 20, max + 20);

            double parcent = (double)range / (double)hist.TotalCount * 100; //parcent of range from image
            if (parcent > 70) // if is biggest than 70% return bad contrast
                return true;

            double bright = (double)pixelRange(hist, 235, 255) / (double)hist.TotalCount * 100; //bright parcent

            if (max < 20 && parcent + bright > 70 ) // if max is dark and the rest picture is bright return bad contrast
                return true;

            double dark = (double)pixelRange(hist, 0, 35) / (double)hist.TotalCount * 100; // dark parcent

            if (max > 240 && dark + parcent > 70) // id max is bright and the rest picture is dark return bad contrast
                return true;

            return false; // picture not bad contrast
        }
Beispiel #18
0
 /// <summary>
 /// **** THIS FUNCTION CAN BE CALLED ONLY ONES IN THE OBJECT LIFE TIME***
 /// creates an AForge.Math.Histogram object from _imGray into _hist
 /// </summary>
 private Histogram createHist()
 {
     lock (histLcok)
     {
         if (_hist != null) return _hist;
         _hist = (new ImageStatistics(_imGray)).Gray;
         return _hist;
     }
 }
Beispiel #19
0
 //return sum of pixeles in range [start,end]
 private int pixelRange(Histogram hist,int start, int end)
 {
     int sum = 0;
     for (int i = start; i < end; i++)
         sum += hist.Values[i];
     return sum;
 }
Beispiel #20
0
 /// <summary>
 /// DeepCopy Constructor
 /// </summary>
 /// <param name="from">Copied Source</param>
 public ImageInfo(ImageInfo from)
 {
     _disposed = false;
     // copy path
     _path = from.getPath();
     // copy gray image
     _imGray = new Bitmap(from.getIm());
     // copy histogram
     _hist = from.getHist() == null ? null : copyHist(from.getHist());
     // copy _imf
     if (from.getImF() != null)
     {
         _imf = new float[from.getImF().Length];
         from.getImF().CopyTo(_imf, 0);
     }
     else { _imf = null; }
     // copy _imb
     if (from.getImF() != null)
     {
         _imb = new byte[from.getImb().Length];
         from.getImb().CopyTo(_imb, 0);
     }
     else { _imb = null; }
     // copy size
     _width = from.Width;
     _height = from.Height;
 }
Beispiel #21
0
 // TODO - check if the arrays can be disposed somehow wthout massing the GC work flow
 protected virtual void Dispose(bool disposing)
 {
     if (!_disposed)
     {
         if (disposing)
         {
             _imGray.Dispose();
             _imGray = null;
             _imb = null;
             _imf = null;
             _hist = null;
         }
         _disposed = true;
     }
 }
        // Gather statistics
        private void ProcessImage( BitmapData imageData, int width, int height, PixelFormat pixelFormat )
        {
            pixels = pixelsWithoutBlack = 0;

            if ( grayscale = ( pixelFormat == PixelFormat.Format8bppIndexed ) )
            {
                // alloc arrays
                int[] g = new int[256];
                int[] gwb = new int[256];

                byte gv;

                int offset = imageData.Stride - width;

                // do the job
                unsafe
                {
                    byte * p = (byte *) imageData.Scan0.ToPointer( );

                    // for each pixel
                    for ( int y = 0; y < height; y++ )
                    {
                        // for each pixel
                        for ( int x = 0; x < width; x++, p++ )
                        {
                            // get pixel value
                            gv = *p;

                            g[gv]++;
                            pixels++;

                            if ( gv != 0 )
                            {
                                gwb[gv]++;
                                pixelsWithoutBlack++;
                            }
                        }
                        p += offset;
                    }
                }

                // create historgram for gray level
                gray = new Histogram( g );
                grayWithoutBlack = new Histogram( gwb );
            }
            else
            {
                // alloc arrays
                int[]	r = new int[256];
                int[]	g = new int[256];
                int[]	b = new int[256];

                int[]	rwb = new int[256];
                int[]	gwb = new int[256];
                int[]	bwb = new int[256];

                byte	rv, gv, bv;

                int offset = imageData.Stride - width * 3;

                // do the job
                unsafe
                {
                    byte * p = (byte *) imageData.Scan0.ToPointer( );

                    // for each line
                    for ( int y = 0; y < height; y++ )
                    {
                        // for each pixel
                        for ( int x = 0; x < width; x++, p += 3 )
                        {
                            // get pixel values
                            rv = p[RGB.R];
                            gv = p[RGB.G];
                            bv = p[RGB.B];

                            r[rv]++;
                            g[gv]++;
                            b[bv]++;
                            pixels++;

                            if ( ( rv != 0 ) || ( gv != 0 ) || ( bv != 0 ) )
                            {
                                rwb[rv]++;
                                gwb[gv]++;
                                bwb[bv]++;
                                pixelsWithoutBlack++;
                            }
                        }
                        p += offset;
                    }
                }

                // create histograms
                red		= new Histogram( r );
                green	= new Histogram( g );
                blue	= new Histogram( b );

                redWithoutBlack		= new Histogram( rwb );
                greenWithoutBlack	= new Histogram( gwb );
                blueWithoutBlack	= new Histogram( bwb );
            }
        }
        /// <summary>
        /// Filter histogram's low values.
        /// </summary>
        /// 
        /// <param name="histogram">Histogram to filter.</param>
        /// 
        private void FilterLowValues( Histogram histogram )
        {
            int[] values = histogram.Values;
            int   globalMax = 0;

            // find global maximum value
            for ( int k = 0; k < values.Length; k++ )
            {
                if ( values[k] > globalMax )
                {
                    globalMax = values[k];
                }
            }

            // filter values, which are below 10% of max
            int filterLevel = (int) ( (double) globalMax / 10 );

            // do filtering
            for ( int k = 0; k < values.Length; k++ )
            {
                if ( values[k] <= filterLevel )
                {
                    values[k] = 0;
                }
            }

            histogram.Update( );
        }