Skip to content

Commit

Permalink
Merge pull request #211 from QutEcoacoustics/Second-Fix-to-Issue-#199
Browse files Browse the repository at this point in the history
Adds rendering of ALL grayscale LD spectrograms to standard indices generation. Closes #199 (again)
  • Loading branch information
atruskie authored Feb 4, 2019
2 parents 1372bd6 + a8c91b1 commit 36a8583
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 57 deletions.
26 changes: 13 additions & 13 deletions src/AnalysisConfigFiles/IndexPropertiesConfig.yml
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ DIF:
Comment: "Spectrum of summed DIFFERENCES between consecutive FFT coeff's in the ampl spgram. This spgram not displayed. It is used as intermediate for subsequent calculation of ACI."
DataType: double[]
DefaultValue: 0.0
DoDisplay: true
DoDisplay: false
NormMin: 0.0
NormMax: 10.0
CalculateNormMin: false
Expand Down Expand Up @@ -650,8 +650,8 @@ OSC:
DataType: double[]
DefaultValue: 0.0
DoDisplay: true
NormMin: 0.0
NormMax: 10.0
NormMin: 0.1
NormMax: 5.0
CalculateNormMin: true
CalculateNormMax: true
ProjectID: Acoustic Indices
Expand All @@ -661,7 +661,7 @@ SUM:
Comment: "Spectrum of summed FFT coefficients derived from the ampl spgram. This spgram not displayed. It is used for intermediate calculations only."
DataType: double[]
DefaultValue: 0.0
DoDisplay: true
DoDisplay: false
NormMin: 0.0
NormMax: 10.0
CalculateNormMin: false
Expand All @@ -687,7 +687,7 @@ RHZ:
DefaultValue: 0.0
DoDisplay: true
NormMin: 0.1
NormMax: 1.5
NormMax: 1.0
CalculateNormMin: false
CalculateNormMax: false
ProjectID: Acoustic Indices
Expand All @@ -700,8 +700,8 @@ RVT:
DoDisplay: true
NormMin: 0.1
NormMax: 0.4
CalculateNormMin: false
CalculateNormMax: false
CalculateNormMin: true
CalculateNormMax: true
ProjectID: Acoustic Indices
Units: "tracks/s"
RPS:
Expand All @@ -712,8 +712,8 @@ RPS:
DoDisplay: true
NormMin: 0.0
NormMax: 0.4
CalculateNormMin: false
CalculateNormMax: false
CalculateNormMin: true
CalculateNormMax: true
ProjectID: Acoustic Indices
Units: "tracks/s"
RNG:
Expand All @@ -724,8 +724,8 @@ RNG:
DoDisplay: true
NormMin: 0.0
NormMax: 0.4
CalculateNormMin: false
CalculateNormMax: false
CalculateNormMin: true
CalculateNormMax: true
ProjectID: Acoustic Indices
Units: "tracks/s"
R3D:
Expand All @@ -736,8 +736,8 @@ R3D:
DoDisplay: true
NormMin: 0.15
NormMax: 1.0
CalculateNormMin: false
CalculateNormMax: false
CalculateNormMin: true
CalculateNormMax: true
ProjectID: Acoustic Indices
Units: "tracks/s"
SPT:
Expand Down
77 changes: 64 additions & 13 deletions src/AnalysisPrograms/Sandpit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ namespace AnalysisPrograms
{
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.Globalization;
Expand All @@ -16,17 +15,15 @@ namespace AnalysisPrograms
using System.Threading.Tasks;
using Acoustics.Shared;
using Acoustics.Shared.Csv;
using AnalyseLongRecordings;
using AnalysisPrograms.AnalyseLongRecordings;
using AudioAnalysisTools;
using AudioAnalysisTools.DSP;
using AudioAnalysisTools.Indices;
using AudioAnalysisTools.LongDurationSpectrograms;
using AudioAnalysisTools.StandardSpectrograms;
using AudioAnalysisTools.WavTools;
using log4net.Util;
using McMaster.Extensions.CommandLineUtils;
using Production;
using Production.Arguments;
using AnalysisPrograms.Production.Arguments;
using TowseyLibrary;

/// <summary>
Expand Down Expand Up @@ -74,6 +71,7 @@ public override Task<int> Execute(CommandLineApplication app)
//CodeToPlaceScoreTracksUnderSingleImage();

//ConcatenateIndexFilesAndSpectrograms();
ConcatenateGreyScaleSpectrogramImages();
//ConcatenateMarineImages();
//ConcatenateImages();
//ConcatenateTwelveImages();
Expand Down Expand Up @@ -323,6 +321,10 @@ public static void Audio2CsvOverOneFile()
//string outputPath = @"G:\SensorNetworks\Output\BradLaw\Pillaga24";
//string configPath = @"C:\Work\GitHub\audio-analysis\AudioAnalysis\AnalysisConfigFiles\Towsey.Acoustic.yml";

string recordingPath = @"C:\Ecoacoustics\WavFiles\LizZnidersic\TasmanIsland2015_Unit2_Mez\SM304256_0+1_20151114_001652.wav";
string outputPath = @"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\01";
string configPath = @"C:\Work\GitHub\audio-analysis\src\AnalysisConfigFiles\Towsey.Acoustic.yml";

// Ivan Campos recordings
//string recordingPath = @"G:\SensorNetworks\WavFiles\Ivancampos\INCIPO01_20161031_024006_898.wav";
//string outputPath = @"G:\SensorNetworks\Output\IvanCampos\17";
Expand Down Expand Up @@ -384,11 +386,11 @@ public static void Audio2CsvOverOneFile()
//string outputPath = @"C:\Ecoacoustics\Output\SERF\SERFIndicesNew_2013June19";
//string configPath = @"C:\Work\GitHub\audio-analysis\src\AnalysisConfigFiles\Towsey.Acoustic.yml";

// USE 24-hour data or parts of from MEZ, TASMAn ISLAND, liz Znidersic
// USE 24-hour data or parts of from MEZ, TASMAn ISLAND, liz Znidersic
// these are six hour recordings
string recordingPath = @"C:\Ecoacoustics\WavFiles\LizZnidersic\TasmanIsland2015_Unit2_Mez\SM304256_0+1_20151114_031652.wav";
string outputPath = @"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\04";
string configPath = @"C:\Work\GitHub\audio-analysis\src\AnalysisConfigFiles\Towsey.Acoustic.yml";
//string recordingPath = @"C:\Ecoacoustics\WavFiles\LizZnidersic\TasmanIsland2015_Unit2_Mez\SM304256_0+1_20151114_031652.wav";
//string outputPath = @"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\04";
//string configPath = @"C:\Work\GitHub\audio-analysis\src\AnalysisConfigFiles\Towsey.Acoustic.yml";

// GROUND PARROT
//string recordingPath = @"C:\SensorNetworks\WavFiles\TestRecordings\groundParrot_Perigian_TEST.wav";
Expand Down Expand Up @@ -1056,11 +1058,60 @@ public static void ConcatenateIndexFilesAndSpectrograms()
}

/// <summary>
/// read a set of Spectral index files and extract values from frequency band
/// This work done for Liz Znidersic paper.
/// End of the method requires access to Liz tagging info.
/// TODO Combine the grey scale spectrograms produced by AnalysisPrograms.exe
/// This method will be useful for comparing the response of different spectral indices to the same acoustic event.
/// Use this when you want best acoustic features for doing ML using spectral index features.
/// </summary>
public static void ExtractSpectralFeatures()
public static void ConcatenateGreyScaleSpectrogramImages()
{

var ipDirInfo = new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\01\Towsey.Acoustic");
var opDirInfo = new DirectoryInfo(@"C:\Ecoacoustics\Output\Test\Test24HourRecording\TasmanIslandMez\01\Towsey.Acoustic");
var opFileName = "SM304256_0+1_20151114_001652";

//string[] keys = { "ACI", "BGN", "CVR", "ENT", "EVN", "OSC", "PMN", "R3D", "RHZ", "RNG", "RPS", "RVT", "SPT" };
var keys = SpectralIndexValues.Keys;

//Read list of images into List
var listOfImages = new List<Image>();

foreach (var key in keys)
{
if (key == "DIF" || key == "SUM")
{
continue;
}

// construct the path
//var path = Path.Combine(ipDirInfo.FullName, opFileName + key + ".png");
var path = FilenameHelpers.AnalysisResultPath(ipDirInfo, opFileName, key, "png");
var indexImage = ImageTools.ReadImage2Bitmap(path);

listOfImages.Add(indexImage);
}

var opPath = FilenameHelpers.AnalysisResultPath(opDirInfo, opFileName, "KEYS", "png");

// check how wide combined image will be. If tracks are wider than 180 = 3 hours, then go vertical
int imageCount = listOfImages.Count;
if (listOfImages[0].Width * imageCount > 180 * imageCount)
{
var combinedImage = ImageTools.CombineImagesVertically(listOfImages);
combinedImage?.Save(opPath);
}
else
{
var combinedImage = ImageTools.CombineImagesInLine(listOfImages);
combinedImage?.Save(opPath);
}
}

/// <summary>
/// read a set of Spectral index files and extract values from frequency band
/// This work done for Liz Znidersic paper.
/// End of the method requires access to Liz tagging info.
/// </summary>
public static void ExtractSpectralFeatures()
{
// parameters
string dir =
Expand Down
6 changes: 4 additions & 2 deletions src/AudioAnalysisTools/DSP/FrequencyScale.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// <copyright file="FrequencyScale.cs" company="QutEcoacoustics">
// <copyright file="FrequencyScale.cs" company="QutEcoacoustics">
// All code in this file and all associated files are the copyright and property of the QUT Ecoacoustics Research Group (formerly MQUTeR, and formerly QUT Bioacoustics Research Group).
// </copyright>

Expand Down Expand Up @@ -396,9 +396,11 @@ public static void DrawFrequencyLinesOnImage(Bitmap bmp, int[,] gridLineLocation
for (int b = 0; b < bandCount; b++)
{
int y = height - gridLineLocations[b, 0];
int hertzValue = gridLineLocations[b, 1];

if (y > 1)
{
g.DrawString($"{gridLineLocations[b, 1]}", new Font("Thachoma", 8), txtColour, 1, y);
g.DrawString($"{hertzValue}", new Font("Thachoma", 8), txtColour, 1, y);
}
}
} //end AddHzGridLines()
Expand Down
65 changes: 47 additions & 18 deletions src/AudioAnalysisTools/LongDurationSpectrograms/LDSpectrogramRGB.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace AudioAnalysisTools.LongDurationSpectrograms
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
Expand Down Expand Up @@ -476,6 +477,12 @@ public void LoadSpectrogramDictionary(Dictionary<string, double[,]> dictionary)
{
minBound = indexProperties.NormMin;
}

// Do not want OSC min set too low. Happens because min can = zero
if (key.Equals("OSC") && minBound < indexProperties.NormMin)
{
minBound = indexProperties.NormMin;
}
}

if (indexProperties.CalculateNormMax)
Expand All @@ -488,6 +495,15 @@ public void LoadSpectrogramDictionary(Dictionary<string, double[,]> dictionary)
maxBound = this.IndexStats[key].Maximum * 0.1;
}
}

// In some rare cases the resulting range is zero which will produce NaNs when normalized.
// In this case we just reset the bounds backs to the defaults in the config file.
// ReSharper disable once CompareOfFloatsByEqualityOperator - we are interested in ranges that are exactly zero distance
if (maxBound == minBound)
{
minBound = indexProperties.NormMin;
maxBound = indexProperties.NormMax;
}
}

// check min, max values
Expand All @@ -499,16 +515,6 @@ public void LoadSpectrogramDictionary(Dictionary<string, double[,]> dictionary)
return matrix;
}

/// <summary>
/// Draws all available spectrograms in grey scale
/// </summary>
public void DrawGreyScaleSpectrograms(DirectoryInfo opdir, string opFileName)
{
var keys = SpectralIndexValues.Keys;
//string[] keys = this.SpectrogramKeys;
this.DrawGreyScaleSpectrograms(opdir, opFileName, keys);
}

/// <summary>
/// draws only those spectrograms in the passed array of keys
/// </summary>
Expand Down Expand Up @@ -540,16 +546,31 @@ public void DrawGreyScaleSpectrograms(DirectoryInfo opdir, string opFileName, st
continue;
}

// the directory for the following path must exist
var path = FilenameHelpers.AnalysisResultPath(opdir, opFileName, key, "png");
var ipList = this.GetSpectralIndexProperties();
if (!ipList[key].DoDisplay)
{
continue;
}

var bmp = this.DrawGreyscaleSpectrogramOfIndex(key);
bmp?.Save(path);

var header = new Bitmap(bmp.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);
var indexImage = ImageTools.CombineImagesVertically(new List<Image>(new Image[] { header, bmp }));

// save the image - the directory for the path must exist
var path = FilenameHelpers.AnalysisResultPath(opdir, opFileName, key, "png");
indexImage?.Save(path);
}
}

/// <summary>
/// Assume calling method has done all the reality checks
/// </summary>
/// Assume calling method has done all the reality checks </summary>
public Image DrawGreyscaleSpectrogramOfIndex(string key)
{
var matrix = this.GetNormalisedSpectrogramMatrix(key);
Expand Down Expand Up @@ -1475,11 +1496,19 @@ public static Tuple<Image, string>[] DrawSpectrogramsFromSpectralIndices(
cs1.IndexStats = indexStatistics;

// draw gray scale spectrogram for each index.
string[] keys = colorMap1.Split('-');
cs1.DrawGreyScaleSpectrograms(outputDirectory, fileStem, keys);
keys = colorMap2.Split('-');
//string[] keys = colorMap1.Split('-');
//cs1.DrawGreyScaleSpectrograms(outputDirectory, fileStem, keys);
//keys = colorMap2.Split('-');
// draw all available gray scale index spectrograms.
var keys = SpectralIndexValues.Keys;
cs1.DrawGreyScaleSpectrograms(outputDirectory, fileStem, keys);

// //string[] keys = this.SpectrogramKeys;
//cs1.DrawGreyScaleSpectrograms(outputDirectory, fileStem, keys);
//}
//keys = colorMap2.Split('-');
//cs1.DrawGreyScaleSpectrograms(outputDirectory, fileStem, keys);

// create and save first false-colour spectrogram image
var image1NoChrome = cs1.DrawFalseColourSpectrogramChromeless(cs1.ColorMode, colorMap1);
Image image1 = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void TestAnalyzeSr22050Recording()
var resultsDirectory = this.outputDirectory.Combine("Towsey.Acoustic");
var listOfFiles = resultsDirectory.EnumerateFiles().ToArray();

Assert.AreEqual(31, listOfFiles.Length);
Assert.AreEqual(38, listOfFiles.Length);

var csvCount = listOfFiles.Count(f => f.Name.EndsWith(".csv"));
Assert.AreEqual(16, csvCount);
Expand All @@ -107,7 +107,7 @@ public void TestAnalyzeSr22050Recording()
Assert.AreEqual(2, jsonCount);

var pngCount = listOfFiles.Count(f => f.Name.EndsWith(".png"));
Assert.AreEqual(13, pngCount);
Assert.AreEqual(20, pngCount);

var twoMapsImagePath = resultsDirectory.CombineFile("TemporaryRecording1__2Maps.png");
var twoMapsImage = ImageTools.ReadImage2Bitmap(twoMapsImagePath.FullName);
Expand Down Expand Up @@ -266,10 +266,10 @@ public void TestAnalyzeSr64000Recording()
analysisType: analysisType,
indexSpectrograms: dictionaryOfSpectra);

// test number of images - should now be 14
// test number of images - should now be 23
listOfFiles = resultsDirectory.EnumerateFiles().ToArray();
pngCount = listOfFiles.Count(f => f.Name.EndsWith(".png"));
Assert.AreEqual(14, pngCount);
Assert.AreEqual(21, pngCount);

var twoMapsImagePath = resultsDirectory.CombineFile(recordingName + "__2Maps.png");
var twoMapsImage = ImageTools.ReadImage2Bitmap(twoMapsImagePath.FullName);
Expand Down
Loading

0 comments on commit 36a8583

Please sign in to comment.