/// <summary> /// Can be used for visual checking and debugging purposes. /// </summary> public static void DrawNormalisedIndexMatrices(DirectoryInfo dir, string baseName, Dictionary <string, double[, ]> dictionary) { var list = new List <Image>(); foreach (string key in ContentSignatures.IndexNames) { var bmp = ImageTools.DrawReversedMatrixWithoutNormalisation(dictionary[key]); // need to rotate spectrogram to get correct orientation. bmp.RotateFlip(RotateFlipType.Rotate270FlipNone); // draw grid lines and add axis scales var xAxisPixelDuration = TimeSpan.FromSeconds(60); var fullDuration = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * bmp.Width); var freqScale = new FrequencyScale(11025, 512, 1000); SpectrogramTools.DrawGridLinesOnImage((Bitmap)bmp, TimeSpan.Zero, fullDuration, xAxisPixelDuration, freqScale); const int trackHeight = 20; var recordingStartDate = default(DateTimeOffset); var timeBmp = ImageTrack.DrawTimeTrack(fullDuration, recordingStartDate, bmp.Width, trackHeight); var array = new Image[2]; array[0] = bmp; array[1] = timeBmp; var image = ImageTools.CombineImagesVertically(array); // add a header to the spectrogram var header = new Bitmap(image.Width, 20); Graphics g = Graphics.FromImage(header); g.Clear(Color.LightGray); g.SmoothingMode = SmoothingMode.AntiAlias; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.DrawString(key, new Font("Tahoma", 9), Brushes.Black, 4, 4); list.Add(ImageTools.CombineImagesVertically(new List <Image>(new[] { header, image }))); } // save the image - the directory for the path must exist var path = Path.Combine(dir.FullName, baseName + "__Towsey.Acoustic.GreyScaleImages.png"); var indexImage = ImageTools.CombineImagesInLine(list); indexImage?.Save(path); }
public static Image DrawFalseColourSpectrograms(Arguments args, string fileStem, Dictionary <string, IndexProperties> indexProperties, Dictionary <string, double[, ]> spectra = null) { // note: the spectra are oriented as per visual orientation, i.e. xAxis = time framesDictionary<string, Int16>.KeyCollection keys = AuthorList.Keys // string[] keys = spectra.Keys.ToCommaSeparatedList().Split(','); // int frameCount = spectra[keys[0]].GetLength(1); int sampleRate = 22050; int frameWidth = 512; double backgroundFilter = 0.75; // 0.75 means small values are accentuated. var minuteOffset = TimeSpan.Zero; var dataScale = args.TemporalScale; string colourMap = args.ColourMap1 ?? LDSpectrogramRGB.DefaultColorMap1; var cs1 = new LDSpectrogramRGB(minuteOffset, dataScale, sampleRate, frameWidth, colourMap) { FileName = fileStem, BackgroundFilter = backgroundFilter, IndexCalculationDuration = dataScale, }; cs1.SetSpectralIndexProperties(indexProperties); // set the relevant dictionary of index properties cs1.SpectrogramMatrices = spectra; var image1 = cs1.DrawFalseColourSpectrogramChromeless("NEGATIVE", colourMap); var fullDuration = TimeSpan.FromSeconds(image1.Width * dataScale.TotalSeconds); string title = fileStem; var titleImage = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, image1.Width); int trackHeight = 20; var timeScale = ImageTrack.DrawTimeRelativeTrack(fullDuration, image1.Width, trackHeight); colourMap = args.ColourMap2 ?? LDSpectrogramRGB.DefaultColorMap2; var image2 = cs1.DrawFalseColourSpectrogramChromeless("NEGATIVE", colourMap); var list = new List <Image> { titleImage, image1, timeScale, image2 }; var combinedImage = ImageTools.CombineImagesVertically(list.ToArray()); return(combinedImage); }
/// <summary> /// Overlays the spectral cluster IDs on a spectrogram from which the clusters derived. /// </summary> public static Image DrawClusterSpectrogram(BaseSonogram sonogram, ClusterInfo clusterInfo, TrainingDataInfo data, int lowerBinBound) { using (var img = sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false)) using (var image = new Image_MultiTrack(img)) { //image.AddTrack(ImageTrack.GetScoreTrack(DataTools.Bool2Binary(clusterInfo.selectedFrames),0.0, 1.0, 0.0)); //add time scale image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond)); image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); // add cluster track, show ID of cluster of each frame string label = string.Format(clusterInfo.ClusterCount + " Clusters"); var scores = new Plot(label, DataTools.normalise(clusterInfo.ClusterHits2), 0.0); // location of cluster hits image.AddTrack(ImageTrack.GetNamedScoreTrack(scores.data, 0.0, 1.0, scores.threshold, scores.title)); // overlay cluster hits on spectrogram int[,] hits = AssembleClusterSpectrogram(sonogram.Data, lowerBinBound, clusterInfo, data); image.OverlayDiscreteColorMatrix(hits); return(image.GetImage()); }// using }
} // Analysis() private static Image DrawSonogram( BaseSonogram sonogram, double[,] hits, Plot scores, List <AcousticEvent> predictedEvents, double eventThreshold) { const bool DoHighlightSubband = false; const bool Add1KHzLines = true; var image = new Image_MultiTrack(sonogram.GetImage(DoHighlightSubband, Add1KHzLines)); ////System.Drawing.Image img = sonogram.GetImage(doHighlightSubband, add1kHzLines); ////img.Save(@"C:\SensorNetworks\temp\testimage1.png", System.Drawing.Imaging.ImageFormat.Png); ////Image_MultiTrack image = new Image_MultiTrack(img); image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond)); image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); if (scores != null) { image.AddTrack(ImageTrack.GetNamedScoreTrack(scores.data, 0.0, 1.0, scores.threshold, scores.title)); } if (hits != null) { image.OverlayRedTransparency(hits); } if ((predictedEvents != null) && (predictedEvents.Count > 0)) { image.AddEvents( predictedEvents, sonogram.NyquistFrequency, sonogram.Configuration.FreqBinCount, sonogram.FramesPerSecond); } return(image.GetImage()); }
/// <summary> /// Can be used for visual checking and debugging purposes. /// </summary> public static void DrawNormalisedIndexMatrices(DirectoryInfo dir, string baseName, Dictionary <string, double[, ]> dictionary) { var list = new List <Image <Rgb24> >(); foreach (string key in ContentSignatures.IndexNames) { var bmp = ImageTools.DrawReversedMatrixWithoutNormalisation(dictionary[key]); // need to rotate spectrogram to get correct orientation. bmp.RotateFlip(RotateFlipType.Rotate270FlipNone); // draw grid lines and add axis scales var xAxisPixelDuration = TimeSpan.FromSeconds(60); var fullDuration = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * bmp.Width); var freqScale = new FrequencyScale(11025, 512, 1000); SpectrogramTools.DrawGridLinesOnImage((Image <Rgb24>)bmp, TimeSpan.Zero, fullDuration, xAxisPixelDuration, freqScale); const int trackHeight = 20; var recordingStartDate = default(DateTimeOffset); var timeBmp = ImageTrack.DrawTimeTrack(fullDuration, recordingStartDate, bmp.Width, trackHeight); var image = ImageTools.CombineImagesVertically(bmp, timeBmp); // add a header to the spectrogram var header = Drawing.NewImage(image.Width, 20, Color.LightGray); header.Mutate(g => { g.DrawText(key, Drawing.Tahoma9, Color.Black, new PointF(4, 4)); list.Add(ImageTools.CombineImagesVertically(header, image)); }); } // save the image - the directory for the path must exist var path = Path.Combine(dir.FullName, baseName + "__Towsey.Acoustic.GreyScaleImages.png"); var indexImage = ImageTools.CombineImagesInLine(list); indexImage?.Save(path); }
}//Sonogram2MultiTrackImage() public static Image Sonogram2Image(BaseSonogram sonogram, Dictionary <string, string> configDict, double[,] hits, List <Plot> scores, List <AcousticEvent> predictedEvents, double eventThreshold) { Image_MultiTrack multiTrackImage = Sonogram2MultiTrackImage(sonogram, configDict); if (scores != null) { foreach (Plot plot in scores) { multiTrackImage.AddTrack(ImageTrack.GetNamedScoreTrack(plot.data, 0.0, 1.0, plot.threshold, plot.title)); //assumes data normalised in 0,1 } } if (hits != null) { multiTrackImage.OverlayRainbowTransparency(hits); } if (predictedEvents.Count > 0) { multiTrackImage.AddEvents(predictedEvents, sonogram.NyquistFrequency, sonogram.Configuration.FreqBinCount, sonogram.FramesPerSecond); } return(multiTrackImage.GetImage()); } //Sonogram2Image()
public static Image DrawSonogram(BaseSonogram sonogram, Plot scores, List <AcousticEvent> poi, double eventThreshold, double[,] overlay) { Image_MultiTrack image = new Image_MultiTrack(sonogram.GetImage(doHighlightSubband: false, add1KHzLines: false, doMelScale: false)); image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond)); image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); if (scores != null) { image.AddTrack(ImageTrack.GetNamedScoreTrack(scores.data, 0.0, 1.0, scores.threshold, scores.title)); } if (poi != null && poi.Count > 0) { image.AddEvents(poi, sonogram.NyquistFrequency, sonogram.Configuration.FreqBinCount, sonogram.FramesPerSecond); } if (overlay != null) { var m = MatrixTools.ThresholdMatrix2Binary(overlay, 0.5); image.OverlayDiscreteColorMatrix(m); } return(image.GetImage()); }
/// <summary> /// This method assumes that the height of the passed sonogram image is half of the original frame size. /// This assumption allows the frequency scale grid lines to be placed at the correct intervals. /// </summary> public static Image <Rgb24> FrameSonogram( Image <Rgb24> sonogramImage, Image <Rgb24> titleBar, TimeSpan minuteOffset, TimeSpan xAxisTicInterval, TimeSpan xAxisPixelDuration, TimeSpan labelInterval, int nyquist, int hertzInterval) { double secondsDuration = xAxisPixelDuration.TotalSeconds * sonogramImage.Width; var fullDuration = TimeSpan.FromSeconds(secondsDuration); // init frequency scale int frameSize = sonogramImage.Height * 2; var freqScale = new FrequencyScale(nyquist, frameSize, hertzInterval); SpectrogramTools.DrawGridLinesOnImage((Image <Rgb24>)sonogramImage, minuteOffset, fullDuration, xAxisTicInterval, freqScale); int imageWidth = sonogramImage.Width; var timeBmp = ImageTrack.DrawShortTimeTrack(minuteOffset, xAxisPixelDuration, xAxisTicInterval, labelInterval, imageWidth, "Seconds"); return(ImageTools.CombineImagesVertically(titleBar, timeBmp, sonogramImage, timeBmp)); }
private static Image DrawSonogram( BaseSonogram sonogram, double[,] hits, Plot scores, List <AcousticEvent> predictedEvents, double eventThreshold) { var image = new Image_MultiTrack(sonogram.GetImage()); ////System.Drawing.Image img = sonogram.GetImage(doHighlightSubband, add1kHzLines); ////Image_MultiTrack image = new Image_MultiTrack(img); image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond)); image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); if (scores != null) { image.AddTrack(ImageTrack.GetNamedScoreTrack(scores.data, 0.0, 1.0, scores.threshold, scores.title)); } ////if (hits != null) image.OverlayRedTransparency(hits); if (hits != null) { image.OverlayRainbowTransparency(hits); } if (predictedEvents != null && predictedEvents.Count > 0) { image.AddEvents( predictedEvents, sonogram.NyquistFrequency, sonogram.Configuration.FreqBinCount, sonogram.FramesPerSecond); } return(image.GetImage()); }
/// <summary> /// Converts summary indices to a tracks image, one track for each index. /// </summary> public static Image <Rgb24> DrawImageOfSummaryIndices( Dictionary <string, IndexProperties> listOfIndexProperties, Dictionary <string, double[]> dictionaryOfSummaryIndices, string titleText, TimeSpan indexCalculationDuration, DateTimeOffset?recordingStartDate, List <GapsAndJoins> errors = null, bool verbose = true) { const int trackHeight = DefaultTrackHeight; int scaleLength = 0; var backgroundColour = Color.White; // init list of bitmap images to store image tracks var bitmapList = new List <Tuple <IndexProperties, Image <Rgb24> > >(dictionaryOfSummaryIndices.Keys.Count); // set up strings to store info about which indices are used var s1 = new StringBuilder("Indices not found:"); var s2 = new StringBuilder("Indices not plotted:"); // accumulate the individual tracks in a List foreach (string key in dictionaryOfSummaryIndices.Keys) { if (!listOfIndexProperties.ContainsKey(key)) { s1.Append(" {0},".Format2(key)); continue; } IndexProperties ip = listOfIndexProperties[key]; if (!ip.DoDisplay) { s2.Append(" {0},".Format2(key)); continue; } //string name = ip.Name; double[] array = dictionaryOfSummaryIndices[key]; scaleLength = array.Length; // alternate rows have different colour to make tracks easier to read backgroundColour = backgroundColour == Color.LightGray ? Color.White : Color.LightGray; var bitmap = ip.GetPlotImage(array, backgroundColour, errors); bitmapList.Add(Tuple.Create(ip, bitmap)); } if (verbose) { Logger.Warn(s1.ToString()); Logger.Warn(s2.ToString()); } var listOfBitmaps = bitmapList // .OrderBy(tuple => tuple.Item1.Order) // don't order because want to preserve alternating gray/white rows. .Select(tuple => tuple.Item2) .Where(b => b != null).ToList(); //set up the composite image parameters int x_offset = 2; int graphWidth = x_offset + scaleLength; int imageWidth = x_offset + scaleLength + TrackEndPanelWidth; Image <Rgb24> titleBmp = ImageTrack.DrawTitleTrack(imageWidth, trackHeight, titleText); TimeSpan xAxisPixelDuration = indexCalculationDuration; TimeSpan fullDuration = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * graphWidth); Image <Rgb24> timeBmp1 = ImageTrack.DrawTimeRelativeTrack(fullDuration, graphWidth, trackHeight); Image <Rgb24> timeBmp2 = timeBmp1; DateTimeOffset?dateTimeOffset = recordingStartDate; if (dateTimeOffset.HasValue) { // draw extra time scale with absolute start time. AND THEN Do SOMETHING WITH IT. timeBmp2 = ImageTrack.DrawTimeTrack(fullDuration, dateTimeOffset, graphWidth, trackHeight); } //draw the composite bitmap var imageList = new List <Image <Rgb24> > { titleBmp, timeBmp1, }; foreach (var image in listOfBitmaps) { imageList.Add(image); } imageList.Add(timeBmp2); var compositeBmp = (Image <Rgb24>)ImageTools.CombineImagesVertically(imageList); return(compositeBmp); }
/// <summary> /// Converts summary indices to a tracks image /// </summary> /// <param name="listOfIndexProperties"></param> /// <param name="dictionaryOfSummaryIndices"></param> /// <param name="titleText"></param> /// <param name="indexCalculationDuration"></param> /// <param name="recordingStartDate"></param> /// <param name="sunriseDataFile"></param> /// <param name="errors"></param> public static Bitmap DrawImageOfSummaryIndices( Dictionary <string, IndexProperties> listOfIndexProperties, Dictionary <string, double[]> dictionaryOfSummaryIndices, string titleText, TimeSpan indexCalculationDuration, DateTimeOffset?recordingStartDate, FileInfo sunriseDataFile = null, List <GapsAndJoins> errors = null, bool verbose = false) { // to translate past keys into current keys Dictionary <string, string> translationDictionary = InitialiseIndexProperties.GetKeyTranslationDictionary(); const int trackHeight = DefaultTrackHeight; int scaleLength = 0; var bitmapList = new List <Tuple <IndexProperties, Image> >(dictionaryOfSummaryIndices.Keys.Count); // accumulate the individual tracks in a List foreach (string key in dictionaryOfSummaryIndices.Keys) { string correctKey = key; if (!listOfIndexProperties.ContainsKey(key)) { if (translationDictionary.ContainsKey(key)) { correctKey = translationDictionary[key]; LoggedConsole.WriteWarnLine( "The csv header is an unknown index <{0}>. Translated to <{1}>", key, correctKey); } else { if (verbose) { Logger.Warn( "A index properties configuration could not be found for {0} (not even in the translation directory). Property is ignored and not rendered" .Format2(key)); } continue; } } IndexProperties ip = listOfIndexProperties[correctKey]; if (!ip.DoDisplay) { continue; } string name = ip.Name; double[] array = dictionaryOfSummaryIndices[key]; scaleLength = array.Length; Image bitmap = ip.GetPlotImage(array, errors); bitmapList.Add(Tuple.Create(ip, bitmap)); } var listOfBitmaps = bitmapList .OrderBy(tuple => tuple.Item1.Order) .Select(tuple => tuple.Item2) .Where(b => b != null).ToList(); //set up the composite image parameters int X_offset = 2; int graphWidth = X_offset + scaleLength; int imageWidth = X_offset + scaleLength + TrackEndPanelWidth; TimeSpan scaleDuration = TimeSpan.FromMinutes(scaleLength); int imageHt = trackHeight * (listOfBitmaps.Count + 4); //+3 for title and top and bottom time tracks Bitmap titleBmp = ImageTrack.DrawTitleTrack(imageWidth, trackHeight, titleText); //Bitmap time1Bmp = ImageTrack.DrawTimeTrack(scaleDuration, TimeSpan.Zero, DrawSummaryIndices.TimeScale, graphWidth, TrackHeight, "Time (hours)"); TimeSpan xAxisPixelDuration = indexCalculationDuration; TimeSpan fullDuration = TimeSpan.FromTicks(xAxisPixelDuration.Ticks * graphWidth); Bitmap timeBmp1 = ImageTrack.DrawTimeRelativeTrack(fullDuration, graphWidth, trackHeight); Bitmap timeBmp2 = timeBmp1; Bitmap suntrack = null; DateTimeOffset?dateTimeOffset = recordingStartDate; if (dateTimeOffset.HasValue) { // draw extra time scale with absolute start time. AND THEN Do SOMETHING WITH IT. timeBmp2 = ImageTrack.DrawTimeTrack(fullDuration, dateTimeOffset, graphWidth, trackHeight); suntrack = SunAndMoon.AddSunTrackToImage(scaleLength, dateTimeOffset, sunriseDataFile); } //draw the composite bitmap var imageList = new List <Image>(); imageList.Add(titleBmp); imageList.Add(timeBmp1); for (int i = 0; i < listOfBitmaps.Count; i++) { imageList.Add(listOfBitmaps[i]); } imageList.Add(timeBmp2); imageList.Add(suntrack); Bitmap compositeBmp = (Bitmap)ImageTools.CombineImagesVertically(imageList); return(compositeBmp); }
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); }
// ############################################################################################################## // ######################### ORIGINAL METHOD FOR STITCHING Gianna Pavan's DATA (10 minutes every 30 minutes) /// <summary> /// This method stitches together spectrogram images derived from consecutive shorter recordings over a 24 hour period. /// Currently set for the recording protocol of Gianna Pavan (10 minutes every 30 minutes). /// /// Call this method from Sandpit or where ever! /// /// IMPORTANT NOTE: This method does NOT check to see if the images are in temporal order. /// A SORT line should be inserted somewhere /// </summary> public static void StitchPartialSpectrograms() { //###################################################### // ********************* set the below parameters var inputDirectory = new DirectoryInfo(@"Z:\Italy_GianniPavan\output4\Towsey.Acoustic"); string opFileStem = "Sassofratino_24hours_v3"; var outputDirectory = new DirectoryInfo(@"Z:\Italy_GianniPavan\output4\"); // a filter to select images to be stitched string endString = "_000.2MAPS.png"; // recording protocol int minutesBetweenRecordingStarts = 30; TimeSpan minOffset = TimeSpan.Zero; // assume first recording in sequence started at midnight // X-axis timescale int pixelColumnsPerHour = 60; int trackHeight = IndexDisplay.DefaultTrackHeight; // ********************* set the above parameters //###################################################### string[] fileEntries = Directory.GetFiles(inputDirectory.FullName); var images = new List <Image>(); bool interpolateSpacer = true; var imagePair = new Image[2]; TimeSpan xAxisTicInterval = TimeSpan.FromMinutes(pixelColumnsPerHour); // assume 60 pixels per hour // loop through all files in the required directory foreach (string path in fileEntries) { // filter files. if (!path.EndsWith(endString)) { continue; } var image = new Bitmap(path); int spacerWidth = minutesBetweenRecordingStarts - image.Width; if (interpolateSpacer) { var spacer = new Bitmap(spacerWidth, image.Height); imagePair[0] = image; imagePair[1] = spacer; image = (Bitmap)ImageTools.CombineImagesInLine(imagePair); } images.Add(image); } var compositeBmp = ImageTools.CombineImagesInLine(images.ToArray()); var fullDuration = TimeSpan.FromMinutes(compositeBmp.Width); var timeBmp = ImageTrack.DrawTimeTrack(fullDuration, minOffset, xAxisTicInterval, compositeBmp.Width, trackHeight, "hours"); var gr = Graphics.FromImage(compositeBmp); int halfHeight = compositeBmp.Height / 2; //add in the title bars string title = $"24 hour FALSE-COLOUR SPECTROGRAM (scale: hours x kHz) (colour: R-G-B = BGN-AVG-CVR) {Meta.OrganizationTag} "; var titleBmp = ImageTrack.DrawTitleTrack(compositeBmp.Width, trackHeight, title); int offset = 0; gr.DrawImage(titleBmp, 0, offset); //draw in the top time scale title = $"24 hour FALSE-COLOUR SPECTROGRAM (scale: hours x kHz) (colour: R-G-B = ACI-ENT-EVN) {Meta.OrganizationTag} "; titleBmp = ImageTrack.DrawTitleTrack(compositeBmp.Width, trackHeight, title); offset = halfHeight; gr.DrawImage(titleBmp, 0, offset); //draw in the top time scale //add in the timescale tracks offset = trackHeight; gr.DrawImage(timeBmp, 0, offset); //draw in the top time scale offset = compositeBmp.Height - trackHeight; gr.DrawImage(timeBmp, 0, offset); //draw in the top time scale offset = halfHeight - trackHeight; gr.DrawImage(timeBmp, 0, offset); //draw in the top time scale offset = halfHeight + trackHeight; gr.DrawImage(timeBmp, 0, offset); //draw in the top time scale compositeBmp.Save(Path.Combine(outputDirectory.FullName, opFileStem + ".png")); }
/// <summary> /// This method draws a spectrogram with other useful information attached. /// </summary> /// <param name="sonogram">of BaseSonogram class.</param> /// <param name="events">a list of acoustic events.</param> /// <param name="plots">a list of plots relevant to the spectrogram scores.</param> /// <param name="hits">not often used - can be null.</param> public static Image <Rgb24> GetSonogramPlusCharts( BaseSonogram sonogram, List <EventCommon> events, List <Plot> plots, double[,] hits) { var spectrogram = sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false); Contract.RequiresNotNull(spectrogram, nameof(spectrogram)); var height = spectrogram.Height; var width = spectrogram.Width; var frameSize = sonogram.Configuration.WindowSize; //var segmentDuration = sonogram.Duration; var spectrogramDuration = width * sonogram.FrameStep; // init with linear frequency scale and draw freq grid lines on image int hertzInterval = 1000; if (height < 200) { hertzInterval = 2000; } var nyquist = sonogram.NyquistFrequency; var freqScale = new FrequencyScale(nyquist, frameSize, hertzInterval); FrequencyScale.DrawFrequencyLinesOnImage(spectrogram, freqScale.GridLineLocations, includeLabels: true); // draw event outlines onto spectrogram. if (events != null && events.Count > 0) { foreach (SpectralEvent ev in events) { var options = new EventRenderingOptions(new UnitConverters(ev.SegmentStartSeconds, spectrogramDuration, nyquist, width, height)); spectrogram.Mutate(x => ev.Draw(x, options)); } } // now add in hits to the spectrogram image. if (hits != null) { spectrogram = Image_MultiTrack.OverlayScoresAsRedTransparency(spectrogram, hits); } int pixelWidth = spectrogram.Width; var titleBar = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram("TITLE", pixelWidth); var timeTrack = ImageTrack.DrawTimeTrack(sonogram.Duration, pixelWidth); var imageList = new List <Image <Rgb24> > { titleBar, timeTrack, spectrogram, timeTrack, }; if (plots != null) { foreach (var plot in plots) { // Next line assumes plot data normalised in 0,1 var plotImage = plot.DrawAnnotatedPlot(ImageTrack.DefaultHeight); // the following draws same plot without the title. //var plotImage = ImageTrack.DrawScoreArrayTrack(plot.data, plot.threshold, pixelWidth); imageList.Add(plotImage); } } var compositeImage = ImageTools.CombineImagesVertically(imageList); return(compositeImage); }
public static void Execute(Arguments arguments) { var inputDirs = arguments.InputDataDirectories.Select(FileInfoExtensions.ToDirectoryInfo); var output = arguments.OutputDirectory.ToDirectoryInfo(); string date = "# DATE AND TIME: " + DateTime.Now; LoggedConsole.WriteLine("\n# DRAW an EASY IMAGE from consecutive days of SUMMARY INDICES in CSV files."); LoggedConsole.WriteLine("# IT IS ASSUMED THAT THE CSV files are already concatenated into 24 hour files."); LoggedConsole.WriteLine(date); LoggedConsole.WriteLine("# Summary Index.csv files are in directories:"); foreach (DirectoryInfo dir in inputDirs) { LoggedConsole.WriteLine(" {0}", dir.FullName); } LoggedConsole.WriteLine("# Output directory: " + output); if (arguments.StartDate == null) { LoggedConsole.WriteLine("# Start date = NULL (No argument provided). Will revise start date ...."); } else { LoggedConsole.WriteLine("# Start date = " + arguments.StartDate.ToString()); } if (arguments.EndDate == null) { LoggedConsole.WriteLine("# End date = NULL (No argument provided). Will revise end date ...."); } else { LoggedConsole.WriteLine("# End date = " + arguments.EndDate.ToString()); } LoggedConsole.WriteLine("# FILE FILTER = " + arguments.FileFilter); LoggedConsole.WriteLine(); // PATTERN SEARCH FOR SUMMARY INDEX FILES. //string pattern = "*__Towsey.Acoustic.Indices.csv"; FileInfo[] csvFiles = IndexMatrices.GetFilesInDirectories(inputDirs.ToArray(), arguments.FileFilter); //LoggedConsole.WriteLine("# Subdirectories Count = " + subDirectories.Length); LoggedConsole.WriteLine("# SummaryIndexFiles.csv Count = " + csvFiles.Length); if (csvFiles.Length == 0) { LoggedConsole.WriteErrorLine("\n\nWARNING from method DrawEasyImage.Execute():"); LoggedConsole.WriteErrorLine(" No SUMMARY index files were found."); LoggedConsole.WriteErrorLine(" RETURNING EMPTY HANDED!"); return; } // Sort the files by date and return as a dictionary: sortedDictionaryOfDatesAndFiles<DateTimeOffset, FileInfo> //var sortedDictionaryOfDatesAndFiles = LDSpectrogramStitching.FilterFilesForDates(csvFiles, arguments.TimeSpanOffsetHint); // calculate new start date if passed value = null. DateTimeOffset?startDate = arguments.StartDate; DateTimeOffset?endDate = arguments.EndDate; TimeSpan totalTimespan = (DateTimeOffset)endDate - (DateTimeOffset)startDate; int dayCount = totalTimespan.Days + 1; // assume last day has full 24 hours of recording available. LoggedConsole.WriteLine("\n# Start date = " + startDate.ToString()); LoggedConsole.WriteLine("# End date = " + endDate.ToString()); LoggedConsole.WriteLine(string.Format("# Elapsed time = {0:f1} hours", dayCount * 24)); LoggedConsole.WriteLine("# Day count = " + dayCount + " (inclusive of start and end days)"); LoggedConsole.WriteLine("# Time Zone = " + arguments.TimeSpanOffsetHint.ToString()); // create top level output directory if it does not exist. DirectoryInfo opDir = output; if (!opDir.Exists) { opDir.Create(); } // SET UP DEFAULT SITE LOCATION INFO -- DISCUSS IWTH ANTHONY // The following location data is used only to draw the sunrise/sunset tracks on images. double?latitude = null; double?longitude = null; var siteDescription = new SiteDescription(); siteDescription.SiteName = arguments.FileStemName; siteDescription.Latitude = latitude; siteDescription.Longitude = longitude; // the following required if drawing the index images FileInfo indexPropertiesConfig = null; // require IndexGenerationData and indexPropertiesConfig for drawing //indexGenerationData = IndexGenerationData.GetIndexGenerationData(csvFiles[0].Directory); indexPropertiesConfig = arguments.IndexPropertiesConfig.ToFileInfo(); Dictionary <string, IndexProperties> listOfIndexProperties = IndexProperties.GetIndexProperties(indexPropertiesConfig); Tuple <List <string>, List <double[]> > tuple = CsvTools.ReadCSVFile(csvFiles[0].FullName); var names = tuple.Item1; // default EASY indices int redID = 3; // backgroundNoise int grnID = 5; // avSNROfActiveframes int bluID = 7; // events per second string rep = @"bgn-avsnr-evn"; // ACI Ht Hpeaks EASY indices if (false) { redID = 11; // ACI grnID = 12; // Ht //bluID = 13; // HavgSp //bluID = 14; // Hvariance //bluID = 15; // Hpeaks bluID = 16; // Hcov //bluID = 7; // SPT rep = @"aci-ht-hcov"; //rep = @"aci-ht-spt"; } // LF, MF, HF if (true) { redID = 10; // LF grnID = 9; // MF bluID = 8; // HF rep = @"lf-mf-hf"; } IndexProperties redIndexProps = listOfIndexProperties[names[redID]]; IndexProperties grnIndexProps = listOfIndexProperties[names[grnID]]; IndexProperties bluIndexProps = listOfIndexProperties[names[bluID]]; int dayPixelHeight = 4; int rowCount = (dayPixelHeight * dayCount) + 35; // +30 for grid lines int colCount = 1440; var bitmap = new Image <Rgb24>(colCount, rowCount); var colour = Color.Yellow; int currentRow = 0; var oneDay = TimeSpan.FromHours(24); int graphWidth = colCount; int trackHeight = 20; var stringFont = Drawing.Arial8; string[] monthNames = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; // for drawing the y-axis scale int scaleWidth = trackHeight + 7; var yAxisScale = new Image <Rgb24>(scaleWidth, rowCount + (2 * trackHeight)); yAxisScale.Mutate(g => { g.Clear(Color.Black); // loop over days for (int d = 0; d < dayCount; d++) { var thisday = ((DateTimeOffset)startDate).AddDays(d); if (thisday.Day == 1) { int nextRow = currentRow + 1; for (int c = 0; c < colCount; c++) { bitmap[c, currentRow] = Color.Gray; bitmap[c, nextRow] = Color.Gray; } for (int c = 0; c < scaleWidth; c++) { yAxisScale[c, currentRow + trackHeight] = Color.Gray; yAxisScale[c, nextRow + trackHeight] = Color.Gray; } string month = monthNames[thisday.Month - 1]; if (thisday.Month == 1) // January { g.DrawText(thisday.Year.ToString(), stringFont, Color.White, new PointF(0, nextRow + trackHeight + 1)); //draw time g.DrawText(month, stringFont, Color.White, new PointF(1, nextRow + trackHeight + 11)); //draw time } else { g.DrawText(month, stringFont, Color.White, new PointF(1, nextRow + trackHeight + 1)); //draw time } currentRow += 2; } // get the exact date and time LoggedConsole.WriteLine($"READING DAY {d + 1} of {dayCount}: {thisday.ToString()}"); // CREATE DAY LEVEL OUTPUT DIRECTORY for this day string dateString = $"{thisday.Year}{thisday.Month:D2}{thisday.Day:D2}"; tuple = CsvTools.ReadCSVFile(csvFiles[d].FullName); var arrays = tuple.Item2; var redArray = arrays[redID]; var grnArray = arrays[grnID]; var bluArray = arrays[bluID]; // NormaliseMatrixValues the indices redArray = DataTools.NormaliseInZeroOne(redArray, redIndexProps.NormMin, redIndexProps.NormMax); grnArray = DataTools.NormaliseInZeroOne(grnArray, grnIndexProps.NormMin, grnIndexProps.NormMax); bluArray = DataTools.NormaliseInZeroOne(bluArray, bluIndexProps.NormMin, bluIndexProps.NormMax); for (int c = 0; c < colCount; c++) { for (int r = 0; r < dayPixelHeight; r++) { //transformedValue = Math.Sqrt(redArray[c]); var transformedValue = redArray[c] * redArray[c]; int redVal = (int)Math.Round(transformedValue * 255); if (redVal < 0) { redVal = 0; } else if (redVal > 255) { redVal = 255; } //transformedValue = Math.Sqrt(grnArray[c]); transformedValue = grnArray[c] * grnArray[c]; // square the value int grnVal = (int)Math.Round(transformedValue * 255); if (grnVal < 0) { grnVal = 0; } else if (grnVal > 255) { grnVal = 255; } //transformedValue = Math.Sqrt(bluArray[c]); transformedValue = bluArray[c] * bluArray[c]; // square the value int bluVal = (int)Math.Round(transformedValue * 255); if (bluVal < 0) { bluVal = 0; } else if (bluVal > 255) { bluVal = 255; } bitmap[c, currentRow + r] = Color.FromRgb((byte)redVal, (byte)grnVal, (byte)bluVal); } } // over all columns currentRow += dayPixelHeight; if (thisday.Day % 7 == 0) { for (int c = 0; c < colCount; c++) { bitmap[c, currentRow] = Color.Gray; } currentRow++; } } // over days }); // draw on civil dawn and dusk lines int startdayOfYear = ((DateTimeOffset)startDate).DayOfYear; int endDayOfYear = ((DateTimeOffset)endDate).DayOfYear; SunAndMoon.AddSunRiseSetLinesToImage(bitmap, arguments.BrisbaneSunriseDatafile.ToFileInfo(), startdayOfYear, endDayOfYear, dayPixelHeight); // add the time scales Image <Rgb24> timeBmp1 = ImageTrack.DrawTimeRelativeTrack(oneDay, graphWidth, trackHeight); var imageList = new [] { timeBmp1, bitmap, timeBmp1 }; Image <Rgb24> compositeBmp1 = (Image <Rgb24>)ImageTools.CombineImagesVertically(imageList); imageList = new [] { yAxisScale, compositeBmp1 }; Image <Rgb24> compositeBmp2 = (Image <Rgb24>)ImageTools.CombineImagesInLine(imageList); // indices used for image string indicesDescription = $"{redIndexProps.Name}|{grnIndexProps.Name}|{bluIndexProps.Name}"; string startString = $"{startDate.Value.Year}/{startDate.Value.Month}/{startDate.Value.Day}"; string endString = $"{endDate.Value.Year}/{endDate.Value.Month}/{endDate.Value.Day}"; string title = $"EASY: {arguments.FileStemName} From {startString} to {endString} Indices: {indicesDescription}"; Image <Rgb24> titleBar = ImageTrack.DrawTitleTrack(compositeBmp2.Width, trackHeight, title); imageList = new [] { titleBar, compositeBmp2 }; compositeBmp2 = (Image <Rgb24>)ImageTools.CombineImagesVertically(imageList); var outputFileName = Path.Combine(opDir.FullName, arguments.FileStemName + "." + rep + ".EASY.png"); compositeBmp2.Save(outputFileName); } // Execute()
public static void Main(Arguments arguments) { // 1. set up the necessary files FileInfo sourceRecording = arguments.Source; FileInfo configFile = arguments.Config.ToFileInfo(); DirectoryInfo opDir = arguments.Output; opDir.Create(); if (arguments.StartOffset.HasValue ^ arguments.EndOffset.HasValue) { throw new InvalidStartOrEndException("If StartOffset or EndOffset is specified, then both must be specified"); } var offsetsProvided = arguments.StartOffset.HasValue && arguments.EndOffset.HasValue; // set default offsets - only use defaults if not provided in argments list TimeSpan?startOffset = null; TimeSpan?endOffset = null; if (offsetsProvided) { startOffset = TimeSpan.FromSeconds(arguments.StartOffset.Value); endOffset = TimeSpan.FromSeconds(arguments.EndOffset.Value); } const string Title = "# MAKE A SONOGRAM FROM AUDIO RECORDING and do OscillationsGeneric activity."; string date = "# DATE AND TIME: " + DateTime.Now; LoggedConsole.WriteLine(Title); LoggedConsole.WriteLine(date); LoggedConsole.WriteLine("# Input audio file: " + sourceRecording.Name); string sourceName = Path.GetFileNameWithoutExtension(sourceRecording.FullName); // 2. get the config dictionary Config configuration = ConfigFile.Deserialize(configFile); // below three lines are examples of retrieving info from Config config // string analysisIdentifier = configuration[AnalysisKeys.AnalysisName]; // bool saveIntermediateWavFiles = (bool?)configuration[AnalysisKeys.SaveIntermediateWavFiles] ?? false; // scoreThreshold = (double?)configuration[AnalysisKeys.EventThreshold] ?? scoreThreshold; // Resample rate must be 2 X the desired Nyquist. Default is that of recording. var resampleRate = configuration.GetIntOrNull(AnalysisKeys.ResampleRate) ?? AppConfigHelper.DefaultTargetSampleRate; var configDict = new Dictionary <string, string>(configuration.ToDictionary()); // #NOISE REDUCTION PARAMETERS //string noisereduce = configDict[ConfigKeys.Mfcc.Key_NoiseReductionType]; configDict[AnalysisKeys.NoiseDoReduction] = "false"; configDict[AnalysisKeys.NoiseReductionType] = "NONE"; configDict[AnalysisKeys.AddAxes] = configuration[AnalysisKeys.AddAxes] ?? "true"; configDict[AnalysisKeys.AddSegmentationTrack] = configuration[AnalysisKeys.AddSegmentationTrack] ?? "true"; configDict[ConfigKeys.Recording.Key_RecordingCallName] = sourceRecording.FullName; configDict[ConfigKeys.Recording.Key_RecordingFileName] = sourceRecording.Name; configDict[AnalysisKeys.AddTimeScale] = configuration[AnalysisKeys.AddTimeScale] ?? "true"; configDict[AnalysisKeys.AddAxes] = configuration[AnalysisKeys.AddAxes] ?? "true"; configDict[AnalysisKeys.AddSegmentationTrack] = configuration[AnalysisKeys.AddSegmentationTrack] ?? "true"; // #################################################################### // print out the sonogram parameters LoggedConsole.WriteLine("\nPARAMETERS"); foreach (KeyValuePair <string, string> kvp in configDict) { LoggedConsole.WriteLine("{0} = {1}", kvp.Key, kvp.Value); } LoggedConsole.WriteLine("Sample Length for detecting oscillations = {0}", SampleLength); // 3: GET RECORDING FileInfo tempAudioSegment = new FileInfo(Path.Combine(opDir.FullName, "tempWavFile.wav")); // delete the temp audio file if it already exists. if (File.Exists(tempAudioSegment.FullName)) { File.Delete(tempAudioSegment.FullName); } // This line creates a temporary version of the source file downsampled as per entry in the config file MasterAudioUtility.SegmentToWav(sourceRecording, tempAudioSegment, new AudioUtilityRequest() { TargetSampleRate = resampleRate }); // 1) get amplitude spectrogram AudioRecording recordingSegment = new AudioRecording(tempAudioSegment.FullName); SonogramConfig sonoConfig = new SonogramConfig(configDict); // default values config BaseSonogram sonogram = new AmplitudeSonogram(sonoConfig, recordingSegment.WavReader); Console.WriteLine("FramesPerSecond = {0}", sonogram.FramesPerSecond); // remove the DC bin sonogram.Data = MatrixTools.Submatrix(sonogram.Data, 0, 1, sonogram.FrameCount - 1, sonogram.Configuration.FreqBinCount); // ############################################################### // DO LocalContrastNormalisation //int fieldSize = 9; //sonogram.Data = LocalContrastNormalisation.ComputeLCN(sonogram.Data, fieldSize); // LocalContrastNormalisation over frequency bins is better and faster. int neighbourhood = 15; double contrastLevel = 0.5; sonogram.Data = NoiseRemoval_Briggs.NoiseReduction_byLCNDivision(sonogram.Data, neighbourhood, contrastLevel); // ############################################################### // lowering the sensitivity threshold increases the number of hits. if (configDict.ContainsKey(AnalysisKeys.OscilDetection2014SensitivityThreshold)) { Oscillations2014.DefaultSensitivityThreshold = double.Parse(configDict[AnalysisKeys.OscilDetection2014SensitivityThreshold]); } if (configDict.ContainsKey(AnalysisKeys.OscilDetection2014SampleLength)) { Oscillations2014.DefaultSampleLength = int.Parse(configDict[AnalysisKeys.OscilDetection2014SensitivityThreshold]); } var list1 = new List <Image>(); //var result = Oscillations2014.GetFreqVsOscillationsDataAndImage(sonogram, 64, "Autocorr-FFT"); //list1.Add(result.FreqOscillationImage); var result = Oscillations2014.GetFreqVsOscillationsDataAndImage(sonogram, "Autocorr-FFT"); list1.Add(result.FreqOscillationImage); result = Oscillations2014.GetFreqVsOscillationsDataAndImage(sonogram, "Autocorr-SVD-FFT"); list1.Add(result.FreqOscillationImage); result = Oscillations2014.GetFreqVsOscillationsDataAndImage(sonogram, "Autocorr-WPD"); list1.Add(result.FreqOscillationImage); Image compositeOscImage1 = ImageTools.CombineImagesInLine(list1.ToArray()); // ############################################################### // init the sonogram image stack var sonogramList = new List <Image>(); var image = sonogram.GetImageFullyAnnotated("AMPLITUDE SPECTROGRAM"); sonogramList.Add(image); //string testPath = @"C:\SensorNetworks\Output\Sonograms\amplitudeSonogram.png"; //image.Save(testPath, ImageFormat.Png); Image envelopeImage = ImageTrack.DrawWaveEnvelopeTrack(recordingSegment, image.Width); sonogramList.Add(envelopeImage); // 2) now draw the standard decibel spectrogram sonogram = new SpectrogramStandard(sonoConfig, recordingSegment.WavReader); // ############################################################### list1 = new List <Image>(); //result = Oscillations2014.GetFreqVsOscillationsDataAndImage(sonogram, 64, "Autocorr-FFT"); //list1.Add(result.FreqOscillationImage); result = Oscillations2014.GetFreqVsOscillationsDataAndImage(sonogram, "Autocorr-FFT"); list1.Add(result.FreqOscillationImage); result = Oscillations2014.GetFreqVsOscillationsDataAndImage(sonogram, "Autocorr-SVD-FFT"); list1.Add(result.FreqOscillationImage); result = Oscillations2014.GetFreqVsOscillationsDataAndImage(sonogram, "Autocorr-WPD"); list1.Add(result.FreqOscillationImage); Image compositeOscImage2 = ImageTools.CombineImagesInLine(list1.ToArray()); // ############################################################### //image = sonogram.GetImageFullyAnnotated("DECIBEL SPECTROGRAM"); //list.Add(image); // combine eight images list1 = new List <Image>(); list1.Add(compositeOscImage1); list1.Add(compositeOscImage2); Image compositeOscImage3 = ImageTools.CombineImagesVertically(list1.ToArray()); string imagePath3 = Path.Combine(opDir.FullName, sourceName + "_freqOscilMatrix.png"); compositeOscImage3.Save(imagePath3, ImageFormat.Png); Image segmentationImage = ImageTrack.DrawSegmentationTrack( sonogram, EndpointDetectionConfiguration.K1Threshold, EndpointDetectionConfiguration.K2Threshold, image.Width); sonogramList.Add(segmentationImage); // 3) now draw the noise reduced decibel spectrogram sonoConfig.NoiseReductionType = NoiseReductionType.Standard; sonoConfig.NoiseReductionParameter = configuration.GetDoubleOrNull(AnalysisKeys.NoiseBgThreshold) ?? 3.0; sonogram = new SpectrogramStandard(sonoConfig, recordingSegment.WavReader); image = sonogram.GetImageFullyAnnotated("NOISE-REDUCED DECIBEL SPECTROGRAM"); sonogramList.Add(image); // ############################################################### // deriving osscilation graph from this noise reduced spectrogram did not work well //Oscillations2014.SaveFreqVsOscillationsDataAndImage(sonogram, sampleLength, algorithmName, opDir); // ############################################################### Image compositeSonogram = ImageTools.CombineImagesVertically(sonogramList); string imagePath2 = Path.Combine(opDir.FullName, sourceName + ".png"); compositeSonogram.Save(imagePath2, ImageFormat.Png); LoggedConsole.WriteLine("\n##### FINISHED FILE ###################################################\n"); }
/// <summary> /// /// </summary> /// <returns></returns> public static Image_MultiTrack Sonogram2MultiTrackImage(BaseSonogram sonogram, Dictionary <string, string> configDict) { bool doHighlightSubband = false; //check if doing a reduced sonogram //int timeReductionFactor = 1; //if (configDict.ContainsKey(Keys.TIME_REDUCTION_FACTOR)) // timeReductionFactor = ConfigDictionary.GetInt(Keys.TIME_REDUCTION_FACTOR, configDict); //int freqReductionFactor = 1; //if (configDict.ContainsKey(Keys.FREQ_REDUCTION_FACTOR)) // freqReductionFactor = ConfigDictionary.GetInt(Keys.FREQ_REDUCTION_FACTOR, configDict); //if (!((timeReductionFactor == 1) && (freqReductionFactor == 1))) //{ // sonogram.Data = ReduceDimensionalityOfSpectrogram(sonogram.Data, timeReductionFactor, freqReductionFactor); // return sonogram.GetImage(doHighlightSubband, add1kHzLines); //} // (iii) NOISE REDUCTION //bool doNoiseReduction = false; //if (configDict.ContainsKey(AnalysisKeys.NoiseDoReduction)) // doNoiseReduction = ConfigDictionary.GetBoolean(AnalysisKeys.NoiseDoReduction, configDict); //if (doNoiseReduction) //{ // //LoggedConsole.WriteLine("PERFORMING NOISE REDUCTION"); // double bgThreshold = 3.0; // if (configDict.ContainsKey(AnalysisKeys.NoiseBgThreshold)) // bgThreshold = ConfigDictionary.GetDouble(AnalysisKeys.NoiseBgThreshold, configDict); // var tuple = SNR.NoiseReduce(sonogram.Data, NoiseReductionType.STANDARD, bgThreshold); // sonogram.Data = tuple.Item1; // store data matrix //} //ADD time and frequency scales bool addScale = false; if (configDict.ContainsKey(AnalysisKeys.AddTimeScale)) { addScale = ConfigDictionary.GetBoolean(AnalysisKeys.AddTimeScale, configDict); } else if (configDict.ContainsKey(AnalysisKeys.AddAxes)) { addScale = ConfigDictionary.GetBoolean(AnalysisKeys.AddAxes, configDict); } Image img = sonogram.GetImage(doHighlightSubband, add1KHzLines: addScale, doMelScale: false); Image_MultiTrack mti = new Image_MultiTrack(img); if (addScale) { mti.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond)); //add time scale } bool addSegmentationTrack = false; //add segmentation track if (configDict.ContainsKey(AnalysisKeys.AddSegmentationTrack)) { addSegmentationTrack = ConfigDictionary.GetBoolean(AnalysisKeys.AddSegmentationTrack, configDict); } if (addSegmentationTrack) { mti.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); //add segmentation track } return(mti); //mti.AddTrack(ImageTrack.GetWavEnvelopeTrack(sonogram)); //add segmentation track }//Sonogram2MultiTrackImage()
public static void Main(Arguments arguments) { //1. set up the necessary files //DirectoryInfo diSource = arguments.Source.Directory; FileInfo fiSourceRecording = arguments.Source; FileInfo fiConfig = arguments.Config.ToFileInfo(); FileInfo fiImage = arguments.Output.ToFileInfo(); fiImage.CreateParentDirectories(); string title = "# CREATE FOUR (4) SONOGRAMS FROM AUDIO RECORDING"; string date = "# DATE AND TIME: " + DateTime.Now; LoggedConsole.WriteLine(title); LoggedConsole.WriteLine(date); LoggedConsole.WriteLine("# Input audio file: " + fiSourceRecording.Name); LoggedConsole.WriteLine("# Output image file: " + fiImage); //2. get the config dictionary Config configuration = ConfigFile.Deserialize(fiConfig); //below three lines are examples of retrieving info from Config config //string analysisIdentifier = configuration[AnalysisKeys.AnalysisName]; //bool saveIntermediateWavFiles = (bool?)configuration[AnalysisKeys.SaveIntermediateWavFiles] ?? false; //scoreThreshold = (double?)configuration[AnalysisKeys.EventThreshold] ?? scoreThreshold; //3 transfer conogram parameters to a dictionary to be passed around var configDict = new Dictionary <string, string>(); // #Resample rate must be 2 X the desired Nyquist. Default is that of recording. configDict["ResampleRate"] = (configuration.GetIntOrNull(AnalysisKeys.ResampleRate) ?? 17640).ToString(); configDict["FrameLength"] = configuration[AnalysisKeys.FrameLength] ?? "512"; int frameSize = configuration.GetIntOrNull(AnalysisKeys.FrameLength) ?? 512; // #Frame Overlap as fraction: default=0.0 configDict["FrameOverlap"] = configuration[AnalysisKeys.FrameOverlap] ?? "0.0"; double windowOverlap = configuration.GetDoubleOrNull(AnalysisKeys.FrameOverlap) ?? 0.0; // #MinHz: 500 // #MaxHz: 3500 // #NOISE REDUCTION PARAMETERS configDict["DoNoiseReduction"] = configuration["DoNoiseReduction"] ?? "true"; configDict["BgNoiseThreshold"] = configuration["BgNoiseThreshold"] ?? "3.0"; configDict["ADD_AXES"] = configuration["ADD_AXES"] ?? "true"; configDict["AddSegmentationTrack"] = configuration["AddSegmentationTrack"] ?? "true"; // 3: GET RECORDING var startOffsetMins = TimeSpan.Zero; var endOffsetMins = TimeSpan.Zero; FileInfo fiOutputSegment = fiSourceRecording; if (!(startOffsetMins == TimeSpan.Zero && endOffsetMins == TimeSpan.Zero)) { var buffer = new TimeSpan(0, 0, 0); fiOutputSegment = new FileInfo(Path.Combine(fiImage.DirectoryName, "tempWavFile.wav")); //This method extracts segment and saves to disk at the location fiOutputSegment. var resampleRate = configuration.GetIntOrNull(AnalysisKeys.ResampleRate) ?? AppConfigHelper.DefaultTargetSampleRate; AudioRecording.ExtractSegment(fiSourceRecording, startOffsetMins, endOffsetMins, buffer, resampleRate, fiOutputSegment); } var recording = new AudioRecording(fiOutputSegment.FullName); // EXTRACT ENVELOPE and SPECTROGRAM var dspOutput = DSP_Frames.ExtractEnvelopeAndFfts(recording, frameSize, windowOverlap); // average absolute value over the minute recording ////double[] avAbsolute = dspOutput.Average; // (A) ################################## EXTRACT INDICES FROM THE SIGNAL WAVEFORM ################################## // var wavDuration = TimeSpan.FromSeconds(recording.WavReader.Time.TotalSeconds); // double totalSeconds = wavDuration.TotalSeconds; // double[] signalEnvelope = dspOutput.Envelope; // double avSignalEnvelope = signalEnvelope.Average(); // double[] frameEnergy = dspOutput.FrameEnergy; // double highAmplIndex = dspOutput.HighAmplitudeCount / totalSeconds; // double binWidth = dspOutput.BinWidth; // int nyquistBin = dspOutput.NyquistBin; // dspOutput.WindowPower, // dspOutput.FreqBinWidth int nyquistFreq = dspOutput.NyquistFreq; double epsilon = recording.Epsilon; // i: prepare amplitude spectrogram double[,] amplitudeSpectrogramData = dspOutput.AmplitudeSpectrogram; // get amplitude spectrogram. var image1 = ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(amplitudeSpectrogramData)); // ii: prepare decibel spectrogram prior to noise removal double[,] decibelSpectrogramdata = MFCCStuff.DecibelSpectra(dspOutput.AmplitudeSpectrogram, dspOutput.WindowPower, recording.SampleRate, epsilon); decibelSpectrogramdata = MatrixTools.NormaliseMatrixValues(decibelSpectrogramdata); var image2 = ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(decibelSpectrogramdata)); // iii: Calculate background noise spectrum in decibels // Calculate noise value for each freq bin. double sdCount = 0.0; // number of SDs above the mean for noise removal var decibelProfile = NoiseProfile.CalculateModalNoiseProfile(decibelSpectrogramdata, sdCount); // DataTools.writeBarGraph(dBProfile.NoiseMode); // iv: Prepare noise reduced spectrogram decibelSpectrogramdata = SNR.TruncateBgNoiseFromSpectrogram(decibelSpectrogramdata, decibelProfile.NoiseThresholds); //double dBThreshold = 1.0; // SPECTRAL dB THRESHOLD for smoothing background //decibelSpectrogramdata = SNR.RemoveNeighbourhoodBackgroundNoise(decibelSpectrogramdata, dBThreshold); var image3 = ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(decibelSpectrogramdata)); // prepare new sonogram config and draw second image going down different code pathway var config = new SonogramConfig { MinFreqBand = 0, MaxFreqBand = 10000, NoiseReductionType = SNR.KeyToNoiseReductionType("Standard"), NoiseReductionParameter = 1.0, WindowSize = frameSize, WindowOverlap = windowOverlap, }; //var mfccConfig = new MfccConfiguration(config); int bandCount = config.mfccConfig.FilterbankCount; bool doMelScale = config.mfccConfig.DoMelScale; int ccCount = config.mfccConfig.CcCount; int fftBins = config.FreqBinCount; //number of Hz bands = 2^N +1 because includes the DC band int minHz = config.MinFreqBand ?? 0; int maxHz = config.MaxFreqBand ?? nyquistFreq; var standardSonogram = new SpectrogramStandard(config, recording.WavReader); var image4 = standardSonogram.GetImage(); // TODO next line crashes - does not produce cepstral sonogram. //SpectrogramCepstral cepSng = new SpectrogramCepstral(config, recording.WavReader); //Image image5 = cepSng.GetImage(); //var mti = SpectrogramTools.Sonogram2MultiTrackImage(sonogram, configDict); //var image = mti.GetImage(); //Image image = SpectrogramTools.Matrix2SonogramImage(deciBelSpectrogram, config); //Image image = SpectrogramTools.Audio2SonogramImage(FileInfo fiAudio, Dictionary<string, string> configDict); //prepare sonogram images var protoImage6 = new Image_MultiTrack(standardSonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false)); protoImage6.AddTrack(ImageTrack.GetTimeTrack(standardSonogram.Duration, standardSonogram.FramesPerSecond)); protoImage6.AddTrack(ImageTrack.GetWavEnvelopeTrack(recording, protoImage6.SonogramImage.Width)); protoImage6.AddTrack(ImageTrack.GetSegmentationTrack(standardSonogram)); var image6 = protoImage6.GetImage(); var list = new List <Image <Rgb24> >(); list.Add(image1); // amplitude spectrogram list.Add(image2); // decibel spectrogram before noise removal list.Add(image3); // decibel spectrogram after noise removal list.Add(image4); // second version of noise reduced spectrogram //list.Add(image5); // ceptral sonogram list.Add(image6.CloneAs <Rgb24>()); // multitrack image Image finalImage = ImageTools.CombineImagesVertically(list); finalImage.Save(fiImage.FullName); ////2: NOISE REMOVAL //double[,] originalSg = sonogram.Data; //double[,] mnr = sonogram.Data; //mnr = ImageTools.WienerFilter(mnr, 3); //double backgroundThreshold = 4.0; //SETS MIN DECIBEL BOUND //var output = SNR.NoiseReduce(mnr, NoiseReductionType.STANDARD, backgroundThreshold); //double ConfigRange = 70; //sets the the max dB //mnr = SNR.SetConfigRange(output.Item1, 0.0, ConfigRange); ////3: Spectral tracks sonogram //byte[,] binary = MatrixTools.IdentifySpectralRidges(mnr); //binary = MatrixTools.ThresholdBinarySpectrum(binary, mnr, 10); //binary = MatrixTools.RemoveOrphanOnesInBinaryMatrix(binary); ////binary = MatrixTools.PickOutLines(binary); //syntactic approach //sonogram.SetBinarySpectrum(binary); ////sonogram.Data = SNR.SpectralRidges2Intensity(binary, originalSg); //image = new Image_MultiTrack(sonogram.GetImage(doHighlightSubband, false)); //image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond)); //image.AddTrack(ImageTrack.GetWavEnvelopeTrack(recording, image.sonogramImage.Width)); //image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); //fn = outputFolder + wavFileName + "_tracks.png"; //image.Save(fn); //LoggedConsole.WriteLine("Spectral tracks sonogram to file: " + fn); //3: prepare image of spectral peaks sonogram //sonogram.Data = SNR.NoiseReduce_Peaks(originalSg, dynamicRange); //image = new Image_MultiTrack(sonogram.GetImage(doHighlightSubband, add1kHzLines)); //image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration)); //image.AddTrack(ImageTrack.GetWavEnvelopeTrack(recording, image.Image.Width)); //image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); //fn = outputFolder + wavFileName + "_peaks.png"; //image.Save(fn); //LoggedConsole.WriteLine("Spectral peaks sonogram to file: " + fn); //4: Sobel approach //sonogram.Data = SNR.NoiseReduce_Sobel(originalSg, dynamicRange); //image = new Image_MultiTrack(sonogram.GetImage(doHighlightSubband, add1kHzLines)); //image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration)); //image.AddTrack(ImageTrack.GetWavEnvelopeTrack(recording, image.Image.Width)); //image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); //fn = outputFolder + wavFileName + "_sobel.png"; //image.Save(fn); //LoggedConsole.WriteLine("Sobel sonogram to file: " + fn); // I1.txt contains the sonogram matrix produced by matlab //string matlabFile = @"C:\SensorNetworks\Software\AudioAnalysis\AED\Test\matlab\GParrots_JB2_20090607-173000.wav_minute_3\I1.txt"; //double[,] matlabMatrix = Util.fileToMatrix(matlabFile, 256, 5166); //LoggedConsole.WriteLine(matrix[0, 2] + " vs " + matlabMatrix[254, 0]); //LoggedConsole.WriteLine(matrix[0, 3] + " vs " + matlabMatrix[253, 0]); // TODO put this back once sonogram issues resolved /* * LoggedConsole.WriteLine("START: AED"); * IEnumerable<Oblong> oblongs = AcousticEventDetection.detectEvents(3.0, 100, matrix); * LoggedConsole.WriteLine("END: AED"); * * * //set up static variables for init Acoustic events * //AcousticEvent. doMelScale = config.DoMelScale; * AcousticEvent.FreqBinCount = config.FreqBinCount; * AcousticEvent.FreqBinWidth = config.FftConfig.NyquistFreq / (double)config.FreqBinCount; * // int minF = (int)config.MinFreqBand; * // int maxF = (int)config.MaxFreqBand; * AcousticEvent.FrameDuration = config.GetFrameOffset(); * * * var events = new List<EventPatternRecog.Rectangle>(); * foreach (Oblong o in oblongs) * { * var e = new AcousticEvent(o); * events.Add(new EventPatternRecog.Rectangle(e.StartTime, (double) e.MaxFreq, e.StartTime + e.Duration, (double)e.MinFreq)); * //LoggedConsole.WriteLine(e.StartTime + "," + e.Duration + "," + e.MinFreq + "," + e.MaxFreq); * } * * LoggedConsole.WriteLine("# AED events: " + events.Count); * * LoggedConsole.WriteLine("START: EPR"); * IEnumerable<EventPatternRecog.Rectangle> eprRects = EventPatternRecog.detectGroundParrots(events); * LoggedConsole.WriteLine("END: EPR"); * * var eprEvents = new List<AcousticEvent>(); * foreach (EventPatternRecog.Rectangle r in eprRects) * { * var ae = new AcousticEvent(r.Left, r.Right - r.Left, r.Bottom, r.Top, false); * LoggedConsole.WriteLine(ae.WriteProperties()); * eprEvents.Add(ae); * } * * string imagePath = Path.Combine(outputFolder, "RESULTS_" + Path.GetFileNameWithoutExtension(recording.BaseName) + ".png"); * * bool doHighlightSubband = false; bool add1kHzLines = true; * var image = new Image_MultiTrack(sonogram.GetImage(doHighlightSubband, add1kHzLines)); * //image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration)); * //image.AddTrack(ImageTrack.GetWavEnvelopeTrack(recording, image.Image.Width)); * //image.AddTrack(ImageTrack.GetSegmentationTrack(sonogram)); * image.AddEvents(eprEvents); * image.Save(outputFolder + wavFileName + ".png"); */ LoggedConsole.WriteLine("\nFINISHED!"); }
public static AudioToSonogramResult GenerateSpectrogramImages(FileInfo sourceRecording, Dictionary <string, string> configDict, DirectoryInfo outputDirectory) { // the source name was set up in the Analyse() method. But it could also be obtained directly from recording. string sourceName = configDict[ConfigKeys.Recording.Key_RecordingFileName]; sourceName = Path.GetFileNameWithoutExtension(sourceName); var result = new AudioToSonogramResult(); // init the image stack var list = new List <Image>(); // 1) draw amplitude spectrogram var recordingSegment = new AudioRecording(sourceRecording.FullName); // default values config except disable noise removal for first two spectrograms SonogramConfig sonoConfig = new SonogramConfig(configDict) { NoiseReductionType = NoiseReductionType.None }; BaseSonogram sonogram = new AmplitudeSonogram(sonoConfig, recordingSegment.WavReader); // remove the DC bin sonogram.Data = MatrixTools.Submatrix(sonogram.Data, 0, 1, sonogram.FrameCount - 1, sonogram.Configuration.FreqBinCount); // save spectrogram data at this point - prior to noise reduction double[,] spectrogramDataBeforeNoiseReduction = sonogram.Data; const int lowPercentile = 20; const double neighbourhoodSeconds = 0.25; int neighbourhoodFrames = (int)(sonogram.FramesPerSecond * neighbourhoodSeconds); const double lcnContrastLevel = 0.25; ////LoggedConsole.WriteLine("LCN: FramesPerSecond (Prior to LCN) = {0}", sonogram.FramesPerSecond); ////LoggedConsole.WriteLine("LCN: Neighbourhood of {0} seconds = {1} frames", neighbourhoodSeconds, neighbourhoodFrames); sonogram.Data = NoiseRemoval_Briggs.NoiseReduction_ShortRecordings_SubtractAndLCN(sonogram.Data, lowPercentile, neighbourhoodFrames, lcnContrastLevel); // draw amplitude spectrogram unannotated FileInfo outputImage1 = new FileInfo(Path.Combine(outputDirectory.FullName, sourceName + ".amplitd.bmp")); ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(sonogram.Data), outputImage1.FullName); // draw amplitude spectrogram annotated 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); // 2) A FALSE-COLOUR VERSION OF AMPLITUDE SPECTROGRAM double ridgeThreshold = 0.20; double[,] matrix = ImageTools.WienerFilter(sonogram.Data, 3); 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); // 3) now draw the standard decibel spectrogram sonogram = new SpectrogramStandard(sonoConfig, recordingSegment.WavReader); // remove the DC bin sonogram.Data = MatrixTools.Submatrix(sonogram.Data, 0, 1, sonogram.FrameCount - 1, sonogram.Configuration.FreqBinCount); // draw decibel spectrogram unannotated FileInfo outputImage2 = new FileInfo(Path.Combine(outputDirectory.FullName, sourceName + ".deciBel.bmp")); ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(sonogram.Data), outputImage2.FullName); 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 (NOT noise reduced) for later use double[,] dbSpectrogramData = (double[, ])sonogram.Data.Clone(); // 4) now draw the noise reduced decibel spectrogram sonoConfig.NoiseReductionType = NoiseReductionType.Standard; sonoConfig.NoiseReductionParameter = 3; ////sonoConfig.NoiseReductionType = NoiseReductionType.SHORT_RECORDING; ////sonoConfig.NoiseReductionParameter = 50; sonogram = new SpectrogramStandard(sonoConfig, recordingSegment.WavReader); // draw decibel spectrogram unannotated FileInfo outputImage3 = new FileInfo(Path.Combine(outputDirectory.FullName, sourceName + ".noNoise_dB.bmp")); ImageTools.DrawReversedMatrix(MatrixTools.MatrixRotate90Anticlockwise(sonogram.Data), outputImage3.FullName); image = sonogram.GetImageFullyAnnotated("DECIBEL SPECTROGRAM + Lamel noise subtraction"); list.Add(image); // keep the sonogram data for later use double[,] nrSpectrogramData = sonogram.Data; // 5) A FALSE-COLOUR VERSION OF DECIBEL SPECTROGRAM ridgeThreshold = 2.5; matrix = ImageTools.WienerFilter(dbSpectrogramData, 3); hits = RidgeDetection.Sobel5X5RidgeDetectionExperiment(matrix, ridgeThreshold); image = SpectrogramTools.CreateFalseColourDecibelSpectrogram(dbSpectrogramData, nrSpectrogramData, hits); image = sonogram.GetImageAnnotatedWithLinearHerzScale(image, "DECIBEL SPECTROGRAM - Colour annotated"); list.Add(image); // 6) COMBINE THE SPECTROGRAM IMAGES Image compositeImage = ImageTools.CombineImagesVertically(list); FileInfo outputImage = new FileInfo(Path.Combine(outputDirectory.FullName, sourceName + ".5spectro.png")); compositeImage.Save(outputImage.FullName, ImageFormat.Png); result.SpectrogramFile = outputImage; // 7) Generate the FREQUENCY x OSCILLATIONS Graphs and csv data ////bool saveData = true; ////bool saveImage = true; ////double[] oscillationsSpectrum = Oscillations2014.GenerateOscillationDataAndImages(sourceRecording, configDict, saveData, saveImage); return(result); }
public void AddTrack(ImageTrack track) { this.tracks.Add(track); }
/// <summary> /// This method draws a spectrogram with other useful information attached. /// </summary> /// <param name="sonogram">of BaseSonogram class.</param> /// <param name="events">a list of acoustic events.</param> /// <param name="plots">a list of plots relevant to the spectrogram scores.</param> /// <param name="hits">not often used - can be null.</param> public static Image <Rgb24> GetSonogramPlusCharts( BaseSonogram sonogram, List <AcousticEvent> events, List <Plot> plots, double[,] hits) { var spectrogram = sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false); Contract.RequiresNotNull(spectrogram, nameof(spectrogram)); var height = spectrogram.Height; var frameSize = sonogram.Configuration.WindowSize; // init with linear frequency scale and draw freq grid lines on image int hertzInterval = 1000; if (height < 200) { hertzInterval = 2000; } var freqScale = new FrequencyScale(sonogram.NyquistFrequency, frameSize, hertzInterval); FrequencyScale.DrawFrequencyLinesOnImage(spectrogram, freqScale.GridLineLocations, includeLabels: true); // draw event outlines onto spectrogram. if (events != null && events.Count > 0) { // set colour for the events foreach (AcousticEvent ev in events) { ev.BorderColour = AcousticEvent.DefaultBorderColor; ev.ScoreColour = AcousticEvent.DefaultScoreColor; ev.DrawEvent(spectrogram, sonogram.FramesPerSecond, sonogram.FBinWidth, height); } } // now add in hits to the spectrogram image. if (hits != null) { spectrogram = Image_MultiTrack.OverlayScoresAsRedTransparency(spectrogram, hits); // following line needs to be reworked if want to call OverlayRainbowTransparency(hits); //image.OverlayRainbowTransparency(hits); } int pixelWidth = spectrogram.Width; var titleBar = LDSpectrogramRGB.DrawTitleBarOfGrayScaleSpectrogram("TITLE", pixelWidth); var timeTrack = ImageTrack.DrawTimeTrack(sonogram.Duration, pixelWidth); var imageList = new List <Image <Rgb24> > { titleBar, timeTrack, spectrogram, timeTrack, }; if (plots != null) { foreach (var plot in plots) { // Next line assumes plot data normalised in 0,1 var plotImage = plot.DrawAnnotatedPlot(ImageTrack.DefaultHeight); // the following draws same plot without the title. //var plotImage = ImageTrack.DrawScoreArrayTrack(plot.data, plot.threshold, pixelWidth); imageList.Add(plotImage); } } var compositeImage = ImageTools.CombineImagesVertically(imageList); return(compositeImage); }
void delImageBlock(List <object> lstData) { try { int i = 0; //------------------------------------------------------ //Check whether user exist in the list of current downloading img of perticular user bool checkUser = false; for (i = 0; i < lstImageTrack.Count; i++) { if (lstImageTrack[i].uName == lstData[0].ToString()) { checkUser = true; break; } } //------------------------------------------------------ //------------------------------------------------------ //Now If user is not present in current downloading list of users if (!checkUser) { //Check IF sent block of img is not single block if ((bool)lstData[3] == false) { ImageTrack objImgTrack = new ImageTrack(); if (objImgTrack.FullImgBlock == null) { objImgTrack.FullImgBlock = new byte[int.Parse(lstData[1].ToString())]; objImgTrack.pointer = 0; } objImgTrack.uName = lstData[0].ToString(); for (int j = 0; j < ((byte[])lstData[2]).Length; j++) { objImgTrack.FullImgBlock[objImgTrack.pointer++] = ((byte[])lstData[2])[j]; } lstImageTrack.Add(objImgTrack); } //Check IF blcok of img is single else if ((bool)lstData[3]) { ctlImage objImage = new ctlImage("", ImgTag); prevTag = ImgTag; ImgTag += 1; objImage.ShowImage((byte[])lstData[2]); stackMain.Children.Add(objImage); lstImage.Add((byte[])lstData[2]); objImage.EntSelectedImage += new ctlImage.DelSelectedImage(singleBlock_EntSelectedImage); } } //IF user is all ready exist in list of downloading imag of user else if (checkUser) { try { if ((bool)lstData[3] == false) { for (int j = 0; j < ((byte[])lstData[2]).Length; j++) { lstImageTrack[i].FullImgBlock[lstImageTrack[i].pointer++] = ((byte[])lstData[2])[j]; } } else if ((bool)lstData[3]) { for (int j = 0; j < ((byte[])lstData[2]).Length; j++) { lstImageTrack[i].FullImgBlock[lstImageTrack[i].pointer++] = ((byte[])lstData[2])[j]; } ctlImage objImage = new ctlImage("", ImgTag); prevTag = ImgTag; ImgTag += 1; objImage.ShowImage(lstImageTrack[i].FullImgBlock); stackMain.Children.Add(objImage); lstImage.Add(lstImageTrack[i].FullImgBlock); objImage.EntSelectedImage += new ctlImage.DelSelectedImage(lastBlock_EntSelectedImage); fncRemoveUser(lstData[0].ToString()); } } catch (Exception ex) { VMuktiHelper.ExceptionHandler(ex, "delImageBlock", "ctlImageSharing.xaml.cs"); } } } catch (Exception ex) { VMuktiHelper.ExceptionHandler(ex, "delImageBlock", "ctlImageSharing.xaml.cs"); } }