/// <summary>
        /// (1) MEAN SUBTRACTION
        /// Assumes the passed matrix is a spectrogram. i.e. rows=frames, cols=freq bins.
        /// Returns the noise profile over freq bins. i.e. one noise value per freq bin.
        /// Note that NoiseThresholds array is identical to NoiseMedian array.
        /// </summary>
        /// <param name="matrix">the spectrogram with origin top-left</param>
        public static NoiseProfile CalculateMeanNoiseProfile(double[,] matrix)
        {
            int colCount = matrix.GetLength(1);

            double[] noiseMean  = new double[colCount];
            double[] minsOfBins = new double[colCount];
            double[] maxsOfBins = new double[colCount];

            for (int col = 0; col < colCount; col++)
            {
                double[] freqBin = MatrixTools.GetColumn(matrix, col);
                noiseMean[col]  = freqBin.Average();
                minsOfBins[col] = freqBin.Min();
                maxsOfBins[col] = freqBin.Max();
            }

            var profile = new NoiseProfile()
            {
                NoiseMean       = noiseMean,
                NoiseSd         = null,
                NoiseThresholds = noiseMean,
                MinDb           = minsOfBins,
                MaxDb           = maxsOfBins,
            };

            return(profile);
        }
        public static NoiseProfile CalculatePercentileNoiseProfile(double[,] matrix, int percentile)
        {
            int rowCount = matrix.GetLength(0);
            int colCount = matrix.GetLength(1);

            double[] noiseMedian = new double[colCount];
            double[] minsOfBins  = new double[colCount];
            double[] maxsOfBins  = new double[colCount];

            for (int col = 0; col < colCount; col++)
            {
                double[] freqBin = MatrixTools.GetColumn(matrix, col);
                Array.Sort(freqBin);
                noiseMedian[col] = freqBin[rowCount * percentile / 100];
                minsOfBins[col]  = freqBin.Min();
                maxsOfBins[col]  = freqBin.Max();
            }

            var profile = new NoiseProfile()
            {
                NoiseMedian     = noiseMedian,
                NoiseSd         = null,
                NoiseThresholds = noiseMedian,
                MinDb           = minsOfBins,
                MaxDb           = maxsOfBins,
            };

            return(profile);
        }
        // #############################################################################################################################
        // ################################# FOUR DIFFERENT METHODS TO CALCULATE THE BACKGROUND NOISE PROFILE
        //
        // (1) MODAL METHOD
        // (2) LOWEST PERCENTILE FRAMES METHOD
        // (3) BIN-WISE LOWEST PERCENTILE CELLS METHOD
        // (4) FIRST N FRAMES
        // ##################

        /// <summary>
        /// (1) MODAL METHOD
        /// Assumes the passed matrix is a spectrogram. i.e. rows=frames, cols=freq bins.
        /// Returns the noise profile over freq bins. i.e. one noise value per freq bin.
        /// </summary>
        /// <param name="matrix">the spectrogram with origin top-left</param>
        /// <param name="sdCount">number of standard deviations</param>
        public static NoiseProfile CalculateModalNoiseProfile(double[,] matrix, double sdCount)
        {
            int colCount = matrix.GetLength(1);

            double[] noiseMode      = new double[colCount];
            double[] noiseSd        = new double[colCount];
            double[] noiseThreshold = new double[colCount];
            double[] minsOfBins     = new double[colCount];
            double[] maxsOfBins     = new double[colCount];
            for (int col = 0; col < colCount; col++)
            {
                double[]            freqBin  = MatrixTools.GetColumn(matrix, col);
                SNR.BackgroundNoise binNoise = SNR.CalculateModalBackgroundNoiseInSignal(freqBin, sdCount);
                noiseMode[col]      = binNoise.NoiseMode;
                noiseSd[col]        = binNoise.NoiseSd;
                noiseThreshold[col] = binNoise.NoiseThreshold;
                minsOfBins[col]     = binNoise.MinDb;
                maxsOfBins[col]     = binNoise.MaxDb;
            }

            var profile = new NoiseProfile()
            {
                NoiseMode       = noiseMode,
                NoiseSd         = noiseSd,
                NoiseThresholds = noiseThreshold,
                MinDb           = minsOfBins,
                MaxDb           = maxsOfBins,
            };

            return(profile);
        }
Beispiel #4
0
        /// <summary>
        /// Assumes the passed matrix is a spectrogram. i.e. rows=frames, cols=freq bins.
        /// WARNING: This method should NOT be used for short recordings (i.e LT approx 10-15 seconds long)
        /// because it obtains a background noise profile from the passed percentile of lowest energy frames.
        ///
        /// Same method as above except take square root of the cell energy divided by the noise.
        /// Taking the square root has the effect of reducing image contrast.
        /// </summary>
        public static double[,] NoiseReduction_byDivisionAndSqrRoot(double[,] matrix, int percentileThreshold)
        {
            double[] profile = NoiseProfile.GetNoiseProfile_fromLowestPercentileFrames(matrix, percentileThreshold);
            profile = DataTools.filterMovingAverage(profile, 3);

            // to prevent division by zero.
            double epsilon = 0.0001;

            int rowCount = matrix.GetLength(0);
            int colCount = matrix.GetLength(1);

            double[,] outM = new double[rowCount, colCount]; //to contain noise reduced matrix

            // for all cols i.e. freq bins
            for (int col = 0; col < colCount; col++)
            {
                double denominator = profile[col];
                if (denominator < epsilon)
                {
                    denominator = epsilon;
                }

                // for all rows
                for (int y = 0; y < rowCount; y++)
                {
                    outM[y, col] = Math.Sqrt(matrix[y, col] / denominator);
                } //end for all rows
            }     //end for all cols

            return(outM);
        }
Beispiel #5
0
        /// <summary>
        /// Assumes the passed matrix is a spectrogram. i.e. rows=frames, cols=freq bins.
        /// First obtains background noise profile calculated from lowest 20% of cells for each freq bin independently.
        /// Loop over freq bins (columns) - subtract noise and divide by LCN (Local Contrast Normalisation.
        ///
        /// The LCN denominator = (contrastLevelConstant + Sqrt(localVariance[y])
        /// Note that sqrt of variance = std dev.
        /// A low contrastLevel = 0.1 give more grey image.
        /// A high contrastLevel = 1.0 give mostly white high contrast image.
        /// </summary>
        public static double[,] NoiseReduction_ShortRecordings_SubtractAndLCN(double[,] matrix, int lowPercent, int neighbourhood, double contrastLevel)
        {
            double[] noiseProfile = NoiseProfile.GetNoiseProfile_BinWiseFromLowestPercentileCells(matrix, lowPercent);
            noiseProfile = DataTools.filterMovingAverage(noiseProfile, 5);
            int rowCount = matrix.GetLength(0);
            int colCount = matrix.GetLength(1);

            //to contain noise reduced matrix
            double[,] outM = new double[rowCount, colCount];

            //for all cols i.e. freq bins
            for (int col = 0; col < colCount; col++)
            {
                double[] column        = MatrixTools.GetColumn(matrix, col);
                double[] localVariance = NormalDist.CalculateLocalVariance(column, neighbourhood);

                // NormaliseMatrixValues with local column variance
                // for all rows
                for (int y = 0; y < rowCount; y++)
                {
                    //outM[y, col] = matrix[y, col] / (contrastLevel + localVariance[y]);
                    outM[y, col] = (matrix[y, col] - noiseProfile[col]) / (contrastLevel + Math.Sqrt(localVariance[y]));
                } //end for all rows
            }     //end for all cols

            return(outM);
        }
Beispiel #6
0
        /// <summary>
        /// 10-percentile Noise Reduction
        /// </summary>
        public static double[,] NoiseReduction(double[,] matrix)
        {
            double[,] nrm = matrix;

            // calculate 10-percentile noise profile
            NoiseProfile profile = NoiseProfile.CalculatePercentileNoiseProfile(matrix, 10);

            // smooth the noise profile
            double[] smoothedProfile = DataTools.filterMovingAverage(profile.NoiseThresholds, width: 7);

            nrm = SNR.TruncateBgNoiseFromSpectrogram(nrm, smoothedProfile);

            return(nrm);
        }
        /// <summary>
        /// Median Noise Reduction
        /// </summary>
        public static double[,] NoiseReduction(double[,] matrix)
        {
            double[,] nrm = matrix;

            // calculate modal noise profile
            // NoiseProfile profile = NoiseProfile.CalculateModalNoiseProfile(matrix, sdCount: 0.0);
            NoiseProfile profile = NoiseProfile.CalculateMedianNoiseProfile(matrix);

            // smooth the noise profile
            double[] smoothedProfile = DataTools.filterMovingAverage(profile.NoiseThresholds, width: 7);

            nrm = SNR.TruncateBgNoiseFromSpectrogram(nrm, smoothedProfile);

            // nrm = SNR.NoiseReduce_Standard(nrm, smoothedProfile, nhBackgroundThreshold: 2.0);

            return(nrm);
        }
        /// <summary>
        /// Assumes the passed matrix is a spectrogram. i.e. rows=frames, cols=freq bins.
        /// WARNING: This method should NOT be used for short recordings (i.e LT approx 10-15 seconds long)
        /// Obtains a background noise profile from the passed percentile of lowest energy frames,
        /// Then subtracts the noise profile value from every cell.
        /// This method was adapted from a paper by Briggs.
        /// </summary>
        /// <param name="matrix"></param>
        /// <param name="percentileThreshold"></param>
        /// <returns></returns>
        public static double[,] NoiseReduction_byLowestPercentileSubtraction(double[,] matrix, int percentileThreshold)
        {
            double[] profile = NoiseProfile.GetNoiseProfile_fromLowestPercentileFrames(matrix, percentileThreshold);
            profile = DataTools.filterMovingAverage(profile, 3);

            int rowCount = matrix.GetLength(0);
            int colCount = matrix.GetLength(1);

            double[,] outM = new double[rowCount, colCount]; //to contain noise reduced matrix

            for (int col = 0; col < colCount; col++)         //for all cols i.e. freq bins
            {
                for (int y = 0; y < rowCount; y++)           //for all rows
                {
                    outM[y, col] = matrix[y, col] - profile[col];
                } //end for all rows
            }     //end for all cols

            return(outM);
        }