/// <summary> /// This method compares the acoustic indices derived from two different long duration recordings of the same length. /// It takes as input six csv files of acoustic indices in spectrogram columns, three csv files for each of the original recordings to be compared. /// The method produces one spectrogram image files: /// 1) A false-colour difference spectrogram, where the difference is shown as a plus/minus departure from grey. /// </summary> public static void DrawDifferenceSpectrogram(DirectoryInfo ipdir, FileInfo ipFileName1, FileInfo ipFileName2, DirectoryInfo opdir) { var cs1 = new LDSpectrogramRGB(minuteOffset, xScale, sampleRate, frameWidth, colorMap) { FileName = ipFileName1.Name, ColorMode = colorMap, BackgroundFilter = backgroundFilterCoeff, }; string[] keys = colorMap.Split('-'); cs1.ReadCsvFiles(ipdir, ipFileName1.Name, keys); if (cs1.GetCountOfSpectrogramMatrices() == 0) { LoggedConsole.WriteLine("There are no spectrogram matrices in cs1.dictionary."); return; } var cs2 = new LDSpectrogramRGB(minuteOffset, xScale, sampleRate, frameWidth, colorMap) { FileName = ipFileName2.Name, ColorMode = colorMap, BackgroundFilter = backgroundFilterCoeff, }; cs2.ReadCsvFiles(ipdir, ipFileName2.Name, keys); if (cs2.GetCountOfSpectrogramMatrices() == 0) { LoggedConsole.WriteLine("There are no spectrogram matrices in cs2.dictionary."); return; } //string title1 = String.Format("DIFFERENCE SPECTROGRAM ({0} - {1}) (scale:hours x kHz) (colour: R-G-B={2})", ipFileName1, ipFileName2, cs1.ColorMODE); //Image deltaSp1 = LDSpectrogramDifference.DrawDifferenceSpectrogram(cs1, cs2, colourGain); //Image titleBar1 = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title1, deltaSp1.Width, SpectrogramConstants.HEIGHT_OF_TITLE_BAR); //deltaSp1 = LDSpectrogramRGB.FrameSpectrogram(deltaSp1, titleBar1, minuteOffset, cs1.X_interval, cs1.Y_interval); //string opFileName1 = ipFileName1 + ".Difference.COLNEG.png"; //deltaSp1.Save(Path.Combine(opdir.FullName, opFileName1)); //Draw positive difference spectrograms in one image. double colourGain = 2.0; Image <Rgb24>[] images = DrawPositiveDifferenceSpectrograms(cs1, cs2, colourGain); int nyquist = cs1.SampleRate / 2; int herzInterval = 1000; string title = $"DIFFERENCE SPECTROGRAM where {ipFileName1} > {ipFileName2}. (scale:hours x kHz) (colour: R-G-B={cs1.ColorMode})"; var titleBar = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, images[0].Width); images[0] = LDSpectrogramRGB.FrameLDSpectrogram(images[0], titleBar, cs1, nyquist, herzInterval); title = string.Format("DIFFERENCE SPECTROGRAM where {1} > {0} (scale:hours x kHz) (colour: R-G-B={2})", ipFileName1, ipFileName2, cs1.ColorMode); titleBar = LDSpectrogramRGB.DrawTitleBarOfFalseColourSpectrogram(title, images[1].Width); images[1] = LDSpectrogramRGB.FrameLDSpectrogram(images[1], titleBar, cs1, nyquist, herzInterval); Image combinedImage = ImageTools.CombineImagesVertically(images); string opFileName = ipFileName1 + "-" + ipFileName2 + ".Difference.png"; combinedImage.Save(Path.Combine(opdir.FullName, opFileName)); }
/// <summary> /// This is cut down version of the method of same name in LDSpectrogramRGB.cs. /// </summary> /// <param name="ldSpectrogramConfig">config for ldfc spectrogram.</param> /// <param name="outputDirectory">outputDirectory.</param> /// <param name="indexGenerationData">indexGenerationData.</param> /// <param name="basename">stem name of the original recording.</param> /// <param name="indexSpectrograms">Optional spectra to pass in. If specified the spectra will not be loaded from disk!.</param> private static string DrawSpectrogramsFromSpectralIndices( LdSpectrogramConfig ldSpectrogramConfig, DirectoryInfo outputDirectory, IndexGenerationData indexGenerationData, string basename, Dictionary <string, double[, ]> indexSpectrograms = null) { string colorMap1 = ldSpectrogramConfig.ColorMap1; // SpectrogramConstants.RGBMap_ACI_ENT_EVN; string colorMap2 = ldSpectrogramConfig.ColorMap2; // SpectrogramConstants.RGBMap_BGN_PMN_OSC; double blueEnhanceParameter = ldSpectrogramConfig.BlueEnhanceParameter.Value; var cs1 = new LDSpectrogramRGB(ldSpectrogramConfig, indexGenerationData, colorMap1); string fileStem = basename; cs1.FileName = fileStem; // calculate start time by combining DatetimeOffset with minute offset. cs1.StartOffset = indexGenerationData.AnalysisStartOffset; if (indexGenerationData.RecordingStartDate.HasValue) { DateTimeOffset dto = (DateTimeOffset)indexGenerationData.RecordingStartDate; cs1.RecordingStartDate = dto; if (dto != null) { cs1.StartOffset = dto.TimeOfDay + cs1.StartOffset; } } var indexProperties = IndexCalculateSixOnly.GetIndexProperties(); cs1.SetSpectralIndexProperties(indexProperties); // Load the Index Spectrograms into a Dictionary cs1.LoadSpectrogramDictionary(indexSpectrograms); if (cs1.GetCountOfSpectrogramMatrices() == 0) { Log.Error("No spectrogram matrices in the dictionary. Spectrogram files do not exist?"); throw new InvalidOperationException("Cannot find spectrogram matrix files"); } // draw all available gray scale index spectrograms. var keys = indexProperties.Keys.ToArray(); cs1.DrawGreyScaleSpectrograms(outputDirectory, fileStem, keys); // create two false-color spectrogram images var image1NoChrome = cs1.DrawFalseColorSpectrogramChromeless(cs1.ColorMode, colorMap1, blueEnhanceParameter); var image2NoChrome = cs1.DrawFalseColorSpectrogramChromeless(cs1.ColorMode, colorMap2, blueEnhanceParameter); var spacer = new Image <Rgb24>(image1NoChrome.Width, 10); var imageList = new[] { image1NoChrome, spacer, image2NoChrome, spacer }; Image image3 = ImageTools.CombineImagesVertically(imageList); var outputPath = FilenameHelpers.AnalysisResultPath(outputDirectory, fileStem, "2Maps", "png"); image3.Save(outputPath); return(outputPath); }
} // method DrawRidgeSpectrograms() public static Image DrawRidgeSpectrograms(DirectoryInfo inputDirectory, FileInfo ipConfig, string fileStem, double scale, Dictionary <string, double[, ]> spectra = null) { string analysisType = AcousticIndices.TowseyAcoustic; //double backgroundFilter = 0.0; // 0.0 means small values are removed. double backgroundFilter = 0.75; // 0.75 means small values are accentuated. var dataScale = TimeSpan.FromSeconds(scale); Dictionary <string, IndexProperties> indexProperties = IndexProperties.GetIndexProperties(ipConfig); string[] keys = SpectralPeakTracks.GetDefaultRidgeKeys(); // read the csv files of the indices in keys array if (spectra == null) { //C:\SensorNetworks\Output\BIRD50\Training\ID0001\Towsey.Acoustic\ID0001__Towsey.Acoustic.ACI spectra = IndexMatrices.ReadSpectralIndices(inputDirectory, fileStem, analysisType, keys); } var cs1 = new LDSpectrogramRGB(minuteOffset: TimeSpan.Zero, xScale: dataScale, sampleRate: 22050, frameWidth: 512, colorMap: null) { FileName = fileStem, BackgroundFilter = backgroundFilter, IndexCalculationDuration = dataScale, }; // set the relevant dictionary of index properties cs1.SetSpectralIndexProperties(indexProperties); cs1.SpectrogramMatrices = spectra; if (cs1.GetCountOfSpectrogramMatrices() == 0) { LoggedConsole.WriteLine("WARNING: " + fileStem + ": No spectrogram matrices in the dictionary. Spectrogram files do not exist?"); return(null); } else if (cs1.GetCountOfSpectrogramMatrices() < keys.Length) { LoggedConsole.WriteLine("WARNING: " + fileStem + ": Missing indices in the dictionary. Some files do not exist?"); return(null); } var stringFont = Drawing.Tahoma8; // constants for labels Color[] color = { Color.Blue, Color.Green, Color.Red, Color.Orange, Color.Purple }; int labelYvalue = 3; int labelIndex = 0; Image <Rgb24> ridges = null; foreach (string key in keys) { Image <Rgb24> greyScaleImage = (Image <Rgb24>)cs1.DrawGreyscaleSpectrogramOfIndex(key); var pixelWidth = greyScaleImage.Width; int height = greyScaleImage.Height; ridges.Mutate(g2 => { if (ridges == null) { ridges = new Image <Rgb24>(pixelWidth, height); g2.Clear(Color.White); } g2.DrawText(key, stringFont, color[labelIndex], new PointF(0, labelYvalue)); }); labelYvalue += 10; //g1.DrawLine(new Pen(Color.Black, 1), 0, 0, width, 0);//draw upper boundary //g1.DrawLine(new Pen(Color.Black, 1), 0, 1, width, 1);//draw upper boundary // transfer greyscale image to colour image for (int y = 0; y < height; y++) { for (int x = 0; x < pixelWidth; x++) { var col = greyScaleImage[x, y]; if (col.G < 150) { ridges[x, y] = color[labelIndex]; } } } labelIndex += 1; } //foreach key return(ridges); } // method DrawRidgeSpectrograms()
} // method DrawAggregatedSpectrograms() public static Image <Rgb24> DrawGrayScaleSpectrograms(Arguments arguments, string fileStem, TimeSpan dataScale, Dictionary <string, double[, ]> spectra = null) { // default values int sampleRate = 22050; int frameWidth = 512; //double backgroundFilter = 0.0; // 0.0 means small values are removed. double backgroundFilter = 0.75; // 0.75 means small values are accentuated. string analysisType = AcousticIndices.TowseyAcoustic; string[] keys = LDSpectrogramRGB.GetArrayOfAvailableKeys(); var inputDirectory = arguments.InputDataDirectory; Dictionary <string, IndexProperties> indexProperties = IndexProperties.GetIndexProperties(arguments.IndexPropertiesConfig.ToFileInfo()); if (spectra == null) { spectra = IndexMatrices.ReadSpectralIndices(inputDirectory.ToDirectoryInfo(), fileStem, analysisType, keys); } // note: the spectra are oriented as per visual orientation, i.e. xAxis = time frames //int frameCount = spectra[keys[0]].GetLength(1); var cs1 = new LDSpectrogramRGB(minuteOffset: TimeSpan.Zero, xScale: dataScale, sampleRate: sampleRate, frameWidth: frameWidth, colorMap: null) { FileName = fileStem, BackgroundFilter = backgroundFilter, IndexCalculationDuration = dataScale, }; cs1.SetSpectralIndexProperties(indexProperties); // set the relevant dictionary of index properties cs1.SpectrogramMatrices = spectra; if (cs1.GetCountOfSpectrogramMatrices() == 0) { LoggedConsole.WriteLine("WARNING: " + fileStem + ": No spectrogram matrices in the dictionary. Spectrogram files do not exist?"); return(null); } var list = new List <Image <Rgb24> >(); var stringFont = Drawing.Arial14; foreach (string key in keys) { var image = cs1.DrawGreyscaleSpectrogramOfIndex(key); int width = 70; int height = image.Height; var label = new Image <Rgb24>(width, height); label.Mutate(g1 => { g1.Clear(Color.Gray); g1.DrawText(key, stringFont, Color.Black, new PointF(4, 30)); g1.DrawLine(new Pen(Color.Black, 1), 0, 0, width, 0); //draw upper boundary g1.DrawLine(new Pen(Color.Black, 1), 0, 1, width, 1); //draw upper boundary }); var imagearray = new[] { label, image }; var labelledImage = ImageTools.CombineImagesInLine(imagearray); list.Add(labelledImage); } //foreach key var combinedImage = ImageTools.CombineImagesVertically(list); return(combinedImage); } // method DrawGrayScaleSpectrograms()
} // method DrawAggregatedSpectrograms() public static Image DrawGrayScaleSpectrograms(Arguments arguments, string fileStem, TimeSpan dataScale, Dictionary <string, double[, ]> spectra = null) { int sampleRate = 22050; int frameWidth = 512; //double backgroundFilter = 0.0; // 0.0 means small values are removed. double backgroundFilter = 0.75; // 0.75 means small values are accentuated. string analysisType = AcousticIndices.TowseyAcoustic; string[] keys = LDSpectrogramRGB.GetArrayOfAvailableKeys(); //LoggedConsole.WriteLine("# Spectrogram Config file: " + arguments.SpectrogramConfigPath); //LoggedConsole.WriteLine("# Index Properties Config file: " + arguments.IndexPropertiesConfig); var inputDirectory = arguments.InputDataDirectory; Dictionary <string, IndexProperties> indexProperties = IndexProperties.GetIndexProperties(arguments.IndexPropertiesConfig.ToFileInfo()); if (spectra == null) { //C:\SensorNetworks\Output\BIRD50\Training\ID0001\Towsey.Acoustic\ID0001__Towsey.Acoustic.ACI spectra = IndexMatrices.ReadSpectralIndices(inputDirectory.ToDirectoryInfo(), fileStem, analysisType, keys); } // note: the spectra are oriented as per visual orientation, i.e. xAxis = time frames //int frameCount = spectra[keys[0]].GetLength(1); var cs1 = new LDSpectrogramRGB(minuteOffset: TimeSpan.Zero, xScale: dataScale, sampleRate: sampleRate, frameWidth: frameWidth, colourMap: null) { FileName = fileStem, BackgroundFilter = backgroundFilter, IndexCalculationDuration = dataScale, }; cs1.SetSpectralIndexProperties(indexProperties); // set the relevant dictionary of index properties cs1.SpectrogramMatrices = spectra; if (cs1.GetCountOfSpectrogramMatrices() == 0) { LoggedConsole.WriteLine("WARNING: " + fileStem + ": No spectrogram matrices in the dictionary. Spectrogram files do not exist?"); return(null); } List <Image> list = new List <Image>(); Font stringFont = new Font("Arial", 14); foreach (string key in keys) { var image = cs1.DrawGreyscaleSpectrogramOfIndex(key); int width = 70; int height = image.Height; var label = new Bitmap(width, height); var g1 = Graphics.FromImage(label); g1.Clear(Color.Gray); g1.DrawString(key, stringFont, Brushes.Black, new PointF(4, 30)); g1.DrawLine(new Pen(Color.Black), 0, 0, width, 0); //draw upper boundary g1.DrawLine(new Pen(Color.Black), 0, 1, width, 1); //draw upper boundary Image[] imagearray = { label, image }; var labelledImage = ImageTools.CombineImagesInLine(imagearray); list.Add(labelledImage); } //foreach key var combinedImage = ImageTools.CombineImagesVertically(list.ToArray()); return(combinedImage); } // method DrawGrayScaleSpectrograms()