public static AudioToSonogramResult GenerateFourSpectrogramImages( FileInfo sourceRecording, FileInfo path2SoxSpectrogram, Dictionary <string, string> configDict, bool dataOnly = false, bool makeSoxSonogram = false) { var result = new AudioToSonogramResult(); if (dataOnly && makeSoxSonogram) { throw new ArgumentException("Can't produce data only for a SoX sonogram"); } if (makeSoxSonogram) { SpectrogramTools.MakeSonogramWithSox(sourceRecording, configDict, path2SoxSpectrogram); result.Path2SoxImage = path2SoxSpectrogram; } else if (dataOnly) { var recordingSegment = new AudioRecording(sourceRecording.FullName); var sonoConfig = new SonogramConfig(configDict); // default values config // disable noise removal sonoConfig.NoiseReductionType = NoiseReductionType.None; Log.Warn("Noise removal disabled!"); var sonogram = new SpectrogramStandard(sonoConfig, recordingSegment.WavReader); result.DecibelSpectrogram = sonogram; } else { // init the image stack var list = new List <Image>(); // IMAGE 1) draw amplitude spectrogram var recordingSegment = new AudioRecording(sourceRecording.FullName); var sonoConfig = new SonogramConfig(configDict); // default values config // disable noise removal for first two spectrograms var disabledNoiseReductionType = sonoConfig.NoiseReductionType; sonoConfig.NoiseReductionType = NoiseReductionType.None; BaseSonogram sonogram = new AmplitudeSonogram(sonoConfig, recordingSegment.WavReader); // remove the DC bin if it has not already been removed. // Assume test of divisible by 2 is good enough. int binCount = sonogram.Data.GetLength(1); if (!binCount.IsEven()) { sonogram.Data = MatrixTools.Submatrix(sonogram.Data, 0, 1, sonogram.FrameCount - 1, binCount - 1); } //save spectrogram data at this point - prior to noise reduction var spectrogramDataBeforeNoiseReduction = sonogram.Data; const double neighbourhoodSeconds = 0.25; int neighbourhoodFrames = (int)(sonogram.FramesPerSecond * neighbourhoodSeconds); const double lcnContrastLevel = 0.001; LoggedConsole.WriteLine("LCN: FramesPerSecond (Prior to LCN) = {0}", sonogram.FramesPerSecond); LoggedConsole.WriteLine("LCN: Neighbourhood of {0} seconds = {1} frames", neighbourhoodSeconds, neighbourhoodFrames); const int lowPercentile = 20; sonogram.Data = NoiseRemoval_Briggs.NoiseReduction_byLowestPercentileSubtraction(sonogram.Data, lowPercentile); sonogram.Data = NoiseRemoval_Briggs.NoiseReduction_byLCNDivision(sonogram.Data, neighbourhoodFrames, lcnContrastLevel); //sonogram.Data = NoiseRemoval_Briggs.NoiseReduction_byLowestPercentileSubtraction(sonogram.Data, lowPercentile); var image = sonogram.GetImageFullyAnnotated("AMPLITUDE SPECTROGRAM + Bin LCN (Local Contrast Normalisation)"); list.Add(image); //string path2 = @"C:\SensorNetworks\Output\Sonograms\dataInput2.png"; //Histogram.DrawDistributionsAndSaveImage(sonogram.Data, path2); // double[,] matrix = sonogram.Data; double[,] matrix = ImageTools.WienerFilter(sonogram.Data, 3); double ridgeThreshold = 0.25; byte[,] hits = RidgeDetection.Sobel5X5RidgeDetectionExperiment(matrix, ridgeThreshold); hits = RidgeDetection.JoinDisconnectedRidgesInMatrix(hits, matrix, ridgeThreshold); image = SpectrogramTools.CreateFalseColourAmplitudeSpectrogram(spectrogramDataBeforeNoiseReduction, null, hits); image = sonogram.GetImageAnnotatedWithLinearHerzScale(image, "AMPLITUDE SPECTROGRAM + LCN + ridge detection"); list.Add(image); Image envelopeImage = ImageTrack.DrawWaveEnvelopeTrack(recordingSegment, image.Width); list.Add(envelopeImage); // IMAGE 2) now draw the standard decibel spectrogram sonogram = new SpectrogramStandard(sonoConfig, recordingSegment.WavReader); result.DecibelSpectrogram = (SpectrogramStandard)sonogram; image = sonogram.GetImageFullyAnnotated("DECIBEL SPECTROGRAM"); list.Add(image); Image segmentationImage = ImageTrack.DrawSegmentationTrack( sonogram, EndpointDetectionConfiguration.K1Threshold, EndpointDetectionConfiguration.K2Threshold, image.Width); list.Add(segmentationImage); // keep the sonogram data for later use double[,] dbSpectrogramData = (double[, ])sonogram.Data.Clone(); // 3) now draw the noise reduced decibel spectrogram // #NOISE REDUCTION PARAMETERS - restore noise reduction ################################################################## sonoConfig.NoiseReductionType = disabledNoiseReductionType; sonoConfig.NoiseReductionParameter = double.Parse(configDict[AnalysisKeys.NoiseBgThreshold] ?? "2.0"); // #NOISE REDUCTION PARAMETERS - MARINE HACK ################################################################## //sonoConfig.NoiseReductionType = NoiseReductionType.FIXED_DYNAMIC_RANGE; //sonoConfig.NoiseReductionParameter = 80.0; sonogram = new SpectrogramStandard(sonoConfig, recordingSegment.WavReader); image = sonogram.GetImageFullyAnnotated("DECIBEL SPECTROGRAM + Lamel noise subtraction"); list.Add(image); // keep the sonogram data for later use double[,] nrSpectrogramData = sonogram.Data; // 4) A FALSE-COLOUR VERSION OF SPECTROGRAM // ########################### SOBEL ridge detection ridgeThreshold = 3.5; matrix = ImageTools.WienerFilter(dbSpectrogramData, 3); hits = RidgeDetection.Sobel5X5RidgeDetectionExperiment(matrix, ridgeThreshold); // ########################### EIGEN ridge detection //double ridgeThreshold = 6.0; //double dominanceThreshold = 0.7; //var rotatedData = MatrixTools.MatrixRotate90Anticlockwise(dbSpectrogramData); //byte[,] hits = RidgeDetection.StructureTensorRidgeDetection(rotatedData, ridgeThreshold, dominanceThreshold); //hits = MatrixTools.MatrixRotate90Clockwise(hits); // ########################### EIGEN ridge detection image = SpectrogramTools.CreateFalseColourDecibelSpectrogram(dbSpectrogramData, nrSpectrogramData, hits); image = sonogram.GetImageAnnotatedWithLinearHerzScale(image, "DECIBEL SPECTROGRAM - Colour annotated"); list.Add(image); // 5) TODO: ONE OF THESE YEARS FIX UP THE CEPTRAL SONOGRAM ////SpectrogramCepstral cepgram = new SpectrogramCepstral((AmplitudeSonogram)amplitudeSpg); ////var mti3 = SpectrogramTools.Sonogram2MultiTrackImage(sonogram, configDict); ////var image3 = mti3.GetImage(); ////image3.Save(fiImage.FullName + "3", ImageFormat.Png); // 6) COMBINE THE SPECTROGRAM IMAGES result.CompositeImage = ImageTools.CombineImagesVertically(list); } return(result); }