Skip to content

Commit

Permalink
Further work on the flying fox recogniser.
Browse files Browse the repository at this point in the history
Issue-#238 Further work on the flying fox recogniser. Refactored a method used for frog recognisers and made it generally available in the class StandardSpectrograms.cs
  • Loading branch information
towsey authored and atruskie committed Aug 28, 2019
1 parent 414b392 commit d123d30
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
---
# Should be in proper casing. The full real name of the species
SpeciesName: Pteropus species
CommonName: Flying Fox
# Abbreviation of species name, format how you like
AbbreviatedSpeciesName: PteropusSp

#Proposed Approach:
Expand All @@ -26,8 +24,8 @@ Profiles:
# The below settings are a template
Standard: &STANDARD
# min and max of the freq band to search
MinHz: 3000
MaxHz: 5000
MinHz: 100
MaxHz: 7000
# duration of DCT in seconds
DctDuration: 0.15
# minimum acceptable value of a DCT coefficient
Expand All @@ -38,7 +36,7 @@ Profiles:
MaxOcilFreq: 140
# Minimum and maximum duration for the length of a true call.
MinDuration: 0.1
MaxDuration: 0.8
MaxDuration: 0.5
# Event threshold - use this to determine FP / FN trade-off for events.
EventThreshold: 0.30
# This notation means the Groote profile has all of the settings that the Standard profile has,
Expand Down
6 changes: 3 additions & 3 deletions src/AnalysisPrograms/Recognizers/LitoriaFallax.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LitoriaFallax.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 @@ -201,7 +201,7 @@ private void WriteDebugImage(
bool displayDebugImage = MainEntry.InDEBUG;
if (displayDebugImage)
{
Image debugImage1 = LitoriaRothii.DisplayDebugImage(sonogram, acousticEvents, plots, hits);
Image debugImage1 = SpectrogramTools.GetSonogramPlusCharts(sonogram, acousticEvents, plots, hits);
var debugPath1 =
outputDirectory.Combine(
FilenameHelpers.AnalysisResultName(
Expand Down Expand Up @@ -231,7 +231,7 @@ private void WriteDebugImage(
this.Identifier,
"png",
"DebugSpectrogram2"));
Image debugImage2 = LitoriaRothii.DisplayDebugImage(sonogram2, acousticEvents, plots, null);
Image debugImage2 = SpectrogramTools.GetSonogramPlusCharts(sonogram2, acousticEvents, plots, null);
debugImage2.Save(debugPath2.FullName);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/AnalysisPrograms/Recognizers/LitoriaFreycineti.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LitoriaFreycineti.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 @@ -195,7 +195,7 @@ private void WriteDebugImage(
bool displayDebugImage = MainEntry.InDEBUG;
if (displayDebugImage)
{
Image debugImage1 = LitoriaRothii.DisplayDebugImage(sonogram, acousticEvents, plots, hits);
Image debugImage1 = SpectrogramTools.GetSonogramPlusCharts(sonogram, acousticEvents, plots, hits);
var debugPath1 =
outputDirectory.Combine(
FilenameHelpers.AnalysisResultName(
Expand Down Expand Up @@ -225,7 +225,7 @@ private void WriteDebugImage(
this.Identifier,
"png",
"DebugSpectrogram2"));
Image debugImage2 = LitoriaRothii.DisplayDebugImage(sonogram2, acousticEvents, plots, null);
Image debugImage2 = SpectrogramTools.GetSonogramPlusCharts(sonogram2, acousticEvents, plots, null);
debugImage2.Save(debugPath2.FullName);
}
}
Expand Down
36 changes: 2 additions & 34 deletions src/AnalysisPrograms/Recognizers/LitoriaRothii.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LitoriaRothii.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 @@ -223,7 +223,7 @@ public override RecognizerResults Recognize(AudioRecording recording, Config con
var lowPassPlot = new Plot("Low Pass", normalisedScores, normalisedThreshold);

var debugPlots = new List<Plot> { ampltdPlot, lowPassPlot, demeanedPlot, plot };
Image debugImage = DisplayDebugImage(sonogram, acousticEvents, debugPlots, null);
Image debugImage = SpectrogramTools.GetSonogramPlusCharts(sonogram, acousticEvents, debugPlots, null);
var debugPath = outputDirectory.Combine(FilenameHelpers.AnalysisResultName(Path.GetFileNameWithoutExtension(recording.BaseName), this.Identifier, "png", "DebugSpectrogram"));
debugImage.Save(debugPath.FullName);
}
Expand All @@ -236,37 +236,5 @@ public override RecognizerResults Recognize(AudioRecording recording, Config con
Events = acousticEvents,
};
}

public static Image DisplayDebugImage(BaseSonogram sonogram, List<AcousticEvent> events, List<Plot> scores, double[,] hits)
{
var image = new Image_MultiTrack(sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false));
image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond));
if (scores != null)
{
foreach (var plot in scores)
{
image.AddTrack(ImageTrack.GetNamedScoreTrack(plot.data, 0.0, 1.0, plot.threshold, plot.title)); //assumes data normalised in 0,1
}
}

if (hits != null)
{
image.OverlayRainbowTransparency(hits);
}

if (events.Count > 0)
{
// set colour for the events
foreach (AcousticEvent ev in events)
{
ev.BorderColour = AcousticEvent.DefaultBorderColor;
ev.ScoreColour = AcousticEvent.DefaultScoreColor;
}

image.AddEvents(events, sonogram.NyquistFrequency, sonogram.Configuration.FreqBinCount, sonogram.FramesPerSecond);
}

return image.GetImage();
}
}
}
56 changes: 49 additions & 7 deletions src/AnalysisPrograms/Recognizers/PteropusSpecies.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace AnalysisPrograms.Recognizers
using System.Linq;
using System.Reflection;
using System.Text;
using Acoustics.Shared;
using Acoustics.Shared.ConfigFile;
using Acoustics.Tools.Wav;
using AnalysisBase;
Expand Down Expand Up @@ -81,10 +82,6 @@ public override void SummariseResults(
/// <returns>recogniser results.</returns>
public override RecognizerResults Recognize(AudioRecording audioRecording, Config configuration, TimeSpan segmentStartOffset, Lazy<IndexCalculateResult[]> getSpectralIndexes, DirectoryInfo outputDirectory, int? imageWidth)
{
// get the common properties
string speciesName = configuration[AnalysisKeys.SpeciesName] ?? "<no species>";
string abbreviatedSpeciesName = configuration[AnalysisKeys.AbbreviatedSpeciesName] ?? "<no.sp>";

RecognizerResults results = Gruntwork(audioRecording, configuration, outputDirectory, segmentStartOffset);

return results;
Expand All @@ -100,12 +97,19 @@ public override RecognizerResults Recognize(AudioRecording audioRecording, Confi
/// <returns>a list of events.</returns>
internal static RecognizerResults Gruntwork(AudioRecording audioRecording, Config configuration, DirectoryInfo outputDirectory, TimeSpan segmentStartOffset)
{
// get the common properties
string speciesName = configuration[AnalysisKeys.SpeciesName] ?? "<no species>";
string abbreviatedSpeciesName = configuration[AnalysisKeys.AbbreviatedSpeciesName] ?? "<no.sp>";
int minHz = configuration.GetIntOrNull(AnalysisKeys.MinHz) ?? 500;
int maxHz = configuration.GetIntOrNull(AnalysisKeys.MaxHz) ?? 8000;
double minDuration = configuration.GetIntOrNull(AnalysisKeys.MinDuration) ?? 0.1;
double maxDuration = configuration.GetIntOrNull(AnalysisKeys.MaxDuration) ?? 0.5;

// Get a value from the config file - without a string accessor, as a double
double someExampleSettingA = configuration.GetDoubleOrNull("SomeExampleSettingA") ?? 0.0;
//double someExampleSettingA = configuration.GetDoubleOrNull("SomeExampleSettingA") ?? 0.0;

/*
* Examples of using profiles
*/
// Examples of the APIs available. You don't need all of these commands! Pick and choose.
bool hasProfiles = ConfigFile.HasProfiles(configuration);
Expand All @@ -121,6 +125,7 @@ internal static RecognizerResults Gruntwork(AudioRecording audioRecording, Confi
// object currentProfile = profile.Profile;
// Log.Info(profile.Name + ": " + ((int)currentProfile.MinHz).ToString());
// }
*/

//######################
//2.Convert each segment to a spectrogram.
Expand All @@ -139,7 +144,44 @@ internal static RecognizerResults Gruntwork(AudioRecording audioRecording, Confi
// get frame parameters for the analysis
var sonogram = (BaseSonogram)new SpectrogramStandard(sonoConfig, audioRecording.WavReader);

var sonoImage = sonogram.GetImageFullyAnnotated("Test");
var data = sonogram.Data;
var score = MatrixTools.GetRowAverages(data);
score = DataTools.NormaliseInZeroOne(score, 0, 12);
//var eventThreshold = 0.25; // equivalent to 3dB
var eventThreshold = 0.5; // equivalent to 6dB
var plot = new Plot(speciesName, score, eventThreshold);
var plots = new List<Plot> { plot };

//iii: CONVERT decibel SCORES TO ACOUSTIC EVENTS
var acousticEvents = AcousticEvent.ConvertScoreArray2Events(
score,
minHz,
maxHz,
sonogram.FramesPerSecond,
sonogram.FBinWidth,
eventThreshold,
minDuration,
maxDuration,
segmentStartOffset);

// ######################################################################
acousticEvents.ForEach(ae =>
{
ae.SpeciesName = speciesName;
ae.SegmentDurationSeconds = audioRecording.Duration.TotalSeconds;
ae.SegmentStartSeconds = segmentStartOffset.TotalSeconds;
ae.Name = abbreviatedSpeciesName;
});

var sonoImage = SpectrogramTools.GetSonogramPlusCharts(sonogram, acousticEvents, plots, null);
//var sonoImage = sonogram.GetImageFullyAnnotated("Test");

//var opPath =
// outputDirectory.Combine(
// FilenameHelpers.AnalysisResultName(
// Path.GetFileNameWithoutExtension(recording.BaseName), speciesName, "png", "DebugSpectrogram"));
//sonoImage.Save(opPath.FullName);

string imageFilename = "Test.png";
sonoImage.Save(Path.Combine(outputDirectory.FullName, imageFilename));

Expand Down
6 changes: 3 additions & 3 deletions src/AnalysisPrograms/Recognizers/UperoleiaInundata.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UperoleiaInundata.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 @@ -201,7 +201,7 @@ private void WriteDebugImage(
bool displayDebugImage = MainEntry.InDEBUG;
if (displayDebugImage)
{
Image debugImage1 = LitoriaRothii.DisplayDebugImage(sonogram, acousticEvents, plots, hits);
Image debugImage1 = SpectrogramTools.GetSonogramPlusCharts(sonogram, acousticEvents, plots, hits);
var debugPath1 =
outputDirectory.Combine(
FilenameHelpers.AnalysisResultName(
Expand Down Expand Up @@ -231,7 +231,7 @@ private void WriteDebugImage(
this.Identifier,
"png",
"DebugSpectrogram2"));
Image debugImage2 = LitoriaRothii.DisplayDebugImage(sonogram2, acousticEvents, plots, null);
Image debugImage2 = SpectrogramTools.GetSonogramPlusCharts(sonogram2, acousticEvents, plots, null);
debugImage2.Save(debugPath2.FullName);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/AnalysisPrograms/Recognizers/UperoleiaMimula.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// --------------------------------------------------------------------------------------------------------------------
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UperoleiaMimula.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 @@ -206,7 +206,7 @@ private void WriteDebugImage(
bool displayDebugImage = MainEntry.InDEBUG;
if (displayDebugImage)
{
Image debugImage1 = LitoriaRothii.DisplayDebugImage(sonogram, acousticEvents, plots, hits);
Image debugImage1 = SpectrogramTools.GetSonogramPlusCharts(sonogram, acousticEvents, plots, hits);
var debugPath1 = outputDirectory.Combine(FilenameHelpers.AnalysisResultName(Path.GetFileNameWithoutExtension(recording.BaseName), this.Identifier, "png", "DebugSpectrogram1"));
debugImage1.Save(debugPath1.FullName);

Expand All @@ -224,7 +224,7 @@ private void WriteDebugImage(
BaseSonogram sonogram2 = new SpectrogramStandard(sonoConfig2, recording.WavReader);

var debugPath2 = outputDirectory.Combine(FilenameHelpers.AnalysisResultName(Path.GetFileNameWithoutExtension(recording.BaseName), this.Identifier, "png", "DebugSpectrogram2"));
Image debugImage2 = LitoriaRothii.DisplayDebugImage(sonogram2, acousticEvents, plots, null);
Image debugImage2 = SpectrogramTools.GetSonogramPlusCharts(sonogram2, acousticEvents, plots, null);
debugImage2.Save(debugPath2.FullName);
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/AudioAnalysisTools/StandardSpectrograms/SpectrogramTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace AudioAnalysisTools.StandardSpectrograms
using System.Drawing;
using System.IO;
using Acoustics.Shared;
using AudioAnalysisTools.WavTools;
using ColorMine.ColorSpaces;
using DSP;
using LongDurationSpectrograms;
Expand Down Expand Up @@ -178,6 +179,45 @@ public static BaseSonogram Audio2DecibelSonogram(FileInfo fiAudio, Dictionary<st
return m;
}

/// <summary>
/// THis method draws a sonogram 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 GetSonogramPlusCharts(BaseSonogram sonogram, List<AcousticEvent> events, List<Plot> plots, double[,] hits)
{
var image = new Image_MultiTrack(sonogram.GetImage(doHighlightSubband: false, add1KHzLines: true, doMelScale: false));
image.AddTrack(ImageTrack.GetTimeTrack(sonogram.Duration, sonogram.FramesPerSecond));
if (plots != null)
{
foreach (var plot in plots)
{
image.AddTrack(ImageTrack.GetNamedScoreTrack(plot.data, 0.0, 1.0, plot.threshold, plot.title)); //assumes data normalised in 0,1
}
}

if (hits != null)
{
image.OverlayRainbowTransparency(hits);
}

if (events != null && events.Count > 0)
{
// set colour for the events
foreach (AcousticEvent ev in events)
{
ev.BorderColour = AcousticEvent.DefaultBorderColor;
ev.ScoreColour = AcousticEvent.DefaultScoreColor;
}

image.AddEvents(events, sonogram.NyquistFrequency, sonogram.Configuration.FreqBinCount, sonogram.FramesPerSecond);
}

return image.GetImage();
}

/*
/// <summary>
///
Expand Down

0 comments on commit d123d30

Please sign in to comment.